From 1a8ff99d61f745616d749818fc312d62399f4ffe Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 24 Oct 2021 13:08:04 +0200 Subject: [PATCH 001/501] refactor: Deprecate custom event listener implementation and default to the one provided by Selenium4 (#1541) --- docs/The-event_firing.md | 213 +++++--------- .../java_client/events/DefaultAspect.java | 4 + .../events/DefaultBeanConfiguration.java | 4 + .../java_client/events/DefaultListener.java | 4 + .../events/EventFiringObjectFactory.java | 4 + .../events/EventFiringWebDriverFactory.java | 4 + .../events/ListenerInvocationHandler.java | 4 + .../java_client/events/api/Listener.java | 2 + .../api/general/AlertEventListener.java | 4 + .../general/AppiumWebDriverEventListener.java | 4 + .../api/general/ElementEventListener.java | 4 + .../api/general/JavaScriptEventListener.java | 4 + .../api/general/ListensToException.java | 4 + .../api/general/NavigationEventListener.java | 4 + .../api/general/SearchingEventListener.java | 4 + .../api/general/WindowEventListener.java | 4 + .../api/mobile/ContextEventListener.java | 4 + .../api/mobile/RotationEventListener.java | 4 + .../AbilityToDefineListenersExternally.java | 99 ------- .../java_client/events/BaseListenerTest.java | 272 ------------------ .../java_client/events/CustomListener.java | 73 +++++ .../events/DefaultEventListenerTest.java | 96 ------- .../java_client/events/EmptyWebDriver.java | 249 ---------------- .../java_client/events/EventsFiringTest.java | 53 ++++ .../events/ExtendedEventListenerTest.java | 44 --- .../java_client/events/FewInstancesTest.java | 176 ------------ .../events/ListenableObjectTest.java | 132 --------- .../appium/java_client/events/StubAlert.java | 22 -- .../java_client/events/StubWebElement.java | 93 ------ .../appium/java_client/events/StubWindow.java | 36 --- ...bDriverEventListenerCompatibilityTest.java | 124 -------- .../events/listeners/AlertListener.java | 35 --- .../events/listeners/AlertListener2.java | 35 --- .../events/listeners/AppiumListener.java | 147 ---------- .../events/listeners/ContextListener.java | 18 -- .../events/listeners/ContextListener2.java | 18 -- .../events/listeners/ElementListener.java | 46 --- .../events/listeners/ElementListener2.java | 46 --- .../events/listeners/ExceptionListener.java | 14 - .../events/listeners/ExceptionListener2.java | 14 - .../events/listeners/JavaScriptListener.java | 18 -- .../events/listeners/JavaScriptListener2.java | 18 -- .../events/listeners/NavigationListener.java | 43 --- .../events/listeners/NavigationListener2.java | 43 --- .../events/listeners/RotationListener.java | 22 -- .../events/listeners/RotationListener2.java | 23 -- .../events/listeners/SearchingListener.java | 24 -- .../events/listeners/SearchingListener2.java | 26 -- .../events/listeners/SingleListeners.java | 12 - .../events/listeners/TestListener.java | 17 -- .../events/listeners/WindowListener.java | 57 ---- .../events/listeners/WindowListener2.java | 61 ---- .../events/stubs/EmptyWebDriver.java | 262 +++++++++++++++++ .../java_client/events/stubs/StubAlert.java | 37 +++ .../events/stubs/StubWebElement.java | 106 +++++++ .../java_client/events/stubs/StubWindow.java | 50 ++++ 56 files changed, 716 insertions(+), 2224 deletions(-) delete mode 100644 src/test/java/io/appium/java_client/events/AbilityToDefineListenersExternally.java delete mode 100644 src/test/java/io/appium/java_client/events/BaseListenerTest.java create mode 100644 src/test/java/io/appium/java_client/events/CustomListener.java delete mode 100644 src/test/java/io/appium/java_client/events/DefaultEventListenerTest.java delete mode 100644 src/test/java/io/appium/java_client/events/EmptyWebDriver.java create mode 100644 src/test/java/io/appium/java_client/events/EventsFiringTest.java delete mode 100644 src/test/java/io/appium/java_client/events/ExtendedEventListenerTest.java delete mode 100644 src/test/java/io/appium/java_client/events/FewInstancesTest.java delete mode 100644 src/test/java/io/appium/java_client/events/ListenableObjectTest.java delete mode 100644 src/test/java/io/appium/java_client/events/StubAlert.java delete mode 100644 src/test/java/io/appium/java_client/events/StubWebElement.java delete mode 100644 src/test/java/io/appium/java_client/events/StubWindow.java delete mode 100644 src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/AlertListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/AlertListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/AppiumListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/ContextListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/ContextListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/ElementListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/ElementListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/ExceptionListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/ExceptionListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/JavaScriptListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/JavaScriptListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/NavigationListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/NavigationListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/RotationListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/RotationListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/SearchingListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/SearchingListener2.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/SingleListeners.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/TestListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/WindowListener.java delete mode 100644 src/test/java/io/appium/java_client/events/listeners/WindowListener2.java create mode 100644 src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java create mode 100644 src/test/java/io/appium/java_client/events/stubs/StubAlert.java create mode 100644 src/test/java/io/appium/java_client/events/stubs/StubWebElement.java create mode 100644 src/test/java/io/appium/java_client/events/stubs/StubWindow.java diff --git a/docs/The-event_firing.md b/docs/The-event_firing.md index 1dcbc1024..7fa0a58d6 100644 --- a/docs/The-event_firing.md +++ b/docs/The-event_firing.md @@ -1,151 +1,76 @@ -since 4.1.0 +since v8.0.0 # The purpose -This feature allows end user to organize the event logging on the client side. Also this feature may be useful in a binding with standard or custom reporting -frameworks. - - -# The API - -The API was designed the way which allows end user to select events (searching, navigation, exception throwing etc.) which should be listened to. It contains -the following list of interfaces (new items may be added further): - -- `io.appium.java_client.events.api.Listener` is the basic interface -- `io.appium.java_client.events.api.general.AlertEventListener` is for the listening to alerts -- `io.appium.java_client.events.api.general.ElementEventListener` is for the listening to actions related to elements -- `io.appium.java_client.events.api.general.JavaScriptEventListener` is for the listening to java script executing -- `io.appium.java_client.events.api.general.ListensToException` is for the listening to exceptions which are thrown -- `io.appium.java_client.events.api.general.NavigationEventListener` is for the listening to events related to navigation -- `io.appium.java_client.events.api.general.SearchingEventListener` is for the listening to events related to the searching. -- `io.appium.java_client.events.api.general.WindowEventListener` is for the listening to actions on a window -- `io.appium.java_client.events.api.mobile.ContextEventListener` is for the listening to the switching to mobile context -- `io.appium.java_client.events.api.mobile.RotationEventListener` is for the listening to screen rotation -- `io.appium.java_client.events.api.general.AppiumWebDriverEventListener` was added to provide the compatibility with -user's implementation of `org.openqa.selenium.support.events.WebDriverEventListener`. Also it extends some interfaces above. - -# Briefly about the engine. - -This is pretty similar solution as the `org.openqa.selenium.support.events.EventFiringWebDriver` of the Selenium project. You -can read about this thing there [The blog post](https://seleniumworks.blogspot.com/2014/02/eventfiringwebdriver.html). - -Here we were trying to improve existing drawbacks and restrictions using: - -- API splitting, see above. - -- the binding of some [Spring framework engines](https://spring.io/projects/spring-framework) with [AspectJ](https://en.wikipedia.org/wiki/AspectJ). - -# How to use - -It is easy. - -```java -import io.appium.java_client.events.api.general.AlertEventListener; - -public class AlertListener implements AlertEventListener { -... -} - -... -import io.appium.java_client.events.api.general.ElementEventListener; - -public class ElementListener implements ElementEventListener { -... -} - -//and so on -... -import io.appium.java_client.events.EventFiringWebDriverFactory; -import io.appium.java_client.events.api.Listener; -... - -AndroidDriver driver = new AndroidDriver(parameters); -driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver, new AlertListener(), - new ElementListener()); - -//or -AndroidDriver driver2 = new AndroidDriver(parameters); -List listeners = new ArrayList<>(); -listeners.add(new AlertListener()); -listeners.add(new ElementListener()); -driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver2, listeners); -``` - -## What if there are listeners which used everywhere by default. - -In order to avoid the repeating actions an end user is free to do these things: - -- create folders `/META-INF/services` and put the file `io.appium.java_client.events.api.Listener` there. Please read about -[SPI](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html). - -![image](https://cloud.githubusercontent.com/assets/4927589/16731325/24eab680-4780-11e6-8551-a3c72d4b9c38.png) - -- define the list of default listeners at the `io.appium.java_client.events.api.Listener` - -![image](https://cloud.githubusercontent.com/assets/4927589/16731509/2734a4e0-4781-11e6-81cb-ab64a5924c35.png) - -And then it is enough +This feature allows end user to organize the event logging on the client side. +Also this feature may be useful in a binding with standard or custom reporting +frameworks. The feature has been introduced first since Selenium API v4. -```java - -//and so on -... -import io.appium.java_client.events.EventFiringWebDriverFactory; -... - -AndroidDriver driver = new AndroidDriver(parameters); -driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver); -``` - -If there are listeners defined externally when this collection is merged with default set of listeners. - -# How to reuse customized WebDriverEventListener - -If an end user has their own `org.openqa.selenium.support.events.WebDriverEventListener` implementation then in order to -make it compatible with this engine it is enough to do the following. - - -```java -import org.openqa.selenium.support.events.WebDriverEventListener; -import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; - -public class UsersWebDriverEventListener implements WebDriverEventListener, AppiumWebDriverEventListener { -... -} -``` - -or just - -```java -import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; - -public class UsersWebDriverEventListener implements AppiumWebDriverEventListener { -... -} -``` -# Also - -As soon as Appium java client has *Java 8-style* API (methods with default implementation) there was provided the ability to get objects created by these interfaces (anonymous types) listenable. Also there is an option to make some objects (some single element that has been found, for example) listenable too. +# The API +There are two main entities used to implement events firing logic: +- [org.openqa.selenium.support.events.EventFiringDecorator](https://github.com/SeleniumHQ/selenium/blob/trunk/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java) class +- [org.openqa.selenium.support.events.WebDriverListener](https://github.com/SeleniumHQ/selenium/blob/trunk/java/src/org/openqa/selenium/support/events/WebDriverListener.java) interface + +## WebDriverListener + +Classes that implement this interface are intended to be used with EventFiringDecorator. +This interface provides empty default implementation for all methods that do nothing. +You could easily extend that interface to add more methods that you'd like to listen to. +The strategy to add new/custom event listeners is the following. Let say there is a public `setOrientation` +method in the target WebDriver instance. Then you'd have to add `beforeSetOrientation` and/or +`afterSetOrientation` methods to your WebDriverListener descendant accepting single argument +of `WebDriver` type. If the target method accepts one or more arguments then these arguments +should also be added to the event listeners in the same order they are accepted by the original method, +but the very first argument should still be the firing WebDriver instance. + +_Important_: Make sure that your implementation of WebDriverListener class is public +and that event listener methods are also public. + +## EventFiringDecorator + +This decorator creates a wrapper around an arbitrary WebDriver instance that notifies +registered listeners about events happening in this WebDriver and derived objects, +such as WebElements and Alert. +Listeners should implement WebDriverListener. It supports three types of events: +- "before"-event: a method is about to be called; +- "after"-event: a method was called successfully and returned some result; +- "error"-event: a method was called and thrown an exception. + +To use this decorator you have to prepare a listener, create a decorator using this listener, +decorate the original WebDriver instance with this decorator and use the new WebDriver instance +created by the decorator instead of the original one: ```java -import static io.appium.java_client.events.EventFiringObjectFactory.getEventFiringObject; -... - -AppiumDriver appiumDriver = new AppiumDriver(parameters); -FindsByAndroidUIAutomator findsByAndroidUIAutomator = - new FindsByAndroidUIAutomator() { - - @Override - public AndroidElement findElement(String by, String using) { - return appiumDriver.findElement(String by, String using); - } - - @Override - public List findElements(String by, String using) { - return appiumDriver.findElements(by, using); - } -}; - -findsByAndroidUIAutomator = - getEventFiringObject(findsByAndroidUIAutomator, appiumDriver, listeners); +WebDriver original = new AndroidDriver(); +// it is expected that MyListener class implements WebDriverListener +// interface or its descendant +WebDriverListener listener = new MyListener(); +WebDriver decorated = new EventFiringDecorator(listener).decorate(original); +// the next call is going to fire: +// - beforeAnyCall +// - beforeAnyWebDriverCall +// - beforeGet +// - afterGet +// - afterAnyWebDriverCall +// - afterAnyCall +// events in the listener instence (in this order) +decorated.get("http://example.com/"); +// the next call is going to fire: +// - beforeAnyCall +// - beforeAnyWebDriverCall +// - beforeFindElement +// - afterFindElement +// - afterAnyWebDriverCall +// - afterAnyCall +// events in the listener instence (in this order) +WebElement header = decorated.findElement(By.tagName("h1")); +// if an error happens during any of these calls the the onError event is fired ``` +The instance of WebDriver created by the decorator implements all the same interfaces +as the original driver. A listener can subscribe to "specific" or "generic" events (or both). +A "specific" event correspond to a single specific method, a "generic" event correspond to any +method called in a class or in any class. To subscribe to a "specific" event a listener should +implement a method with a name derived from the target method to be watched. The listener methods +for "before"-events receive the parameters passed to the decorated method. The listener +methods for "after"-events receive the parameters passed to the decorated method as well as the +result returned by this method. diff --git a/src/main/java/io/appium/java_client/events/DefaultAspect.java b/src/main/java/io/appium/java_client/events/DefaultAspect.java index 3ce9794be..bb38d80e6 100644 --- a/src/main/java/io/appium/java_client/events/DefaultAspect.java +++ b/src/main/java/io/appium/java_client/events/DefaultAspect.java @@ -39,6 +39,10 @@ import java.util.Collection; import java.util.List; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated @SuppressWarnings("unused") @Aspect class DefaultAspect { diff --git a/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java b/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java index b50a36ee3..ac2dd1581 100644 --- a/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java +++ b/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java @@ -28,6 +28,10 @@ import java.util.ArrayList; import java.util.List; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) class DefaultBeanConfiguration { 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 b260b1875..87c2cf15d 100644 --- a/src/main/java/io/appium/java_client/events/DefaultListener.java +++ b/src/main/java/io/appium/java_client/events/DefaultListener.java @@ -42,6 +42,10 @@ import java.util.Collection; import java.util.List; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated class DefaultListener implements Listener, AppiumWebDriverEventListener, ListensToException, SearchingEventListener, NavigationEventListener, JavaScriptEventListener, ElementEventListener, AlertEventListener, diff --git a/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java b/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java index 7b5d723c0..867251ccd 100644 --- a/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java +++ b/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java @@ -12,6 +12,10 @@ import java.util.List; import java.util.ServiceLoader; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public class EventFiringObjectFactory { /** diff --git a/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java b/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java index 7b53dc346..f0d255772 100644 --- a/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java +++ b/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java @@ -23,6 +23,10 @@ import java.util.Collection; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public class EventFiringWebDriverFactory { /** diff --git a/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java b/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java index d6e51c0ce..7fe31125d 100644 --- a/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java +++ b/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java @@ -23,6 +23,10 @@ import java.lang.reflect.Method; import java.util.List; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated class ListenerInvocationHandler implements InvocationHandler { private final List listeners; diff --git a/src/main/java/io/appium/java_client/events/api/Listener.java b/src/main/java/io/appium/java_client/events/api/Listener.java index e1ea35c1d..aeb7e7986 100644 --- a/src/main/java/io/appium/java_client/events/api/Listener.java +++ b/src/main/java/io/appium/java_client/events/api/Listener.java @@ -18,6 +18,8 @@ /** * This interface just marks event listeners. + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. */ +@Deprecated public interface Listener { } diff --git a/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java b/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java index 2a96d1792..a9895b758 100644 --- a/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java @@ -20,6 +20,10 @@ import org.openqa.selenium.Alert; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface AlertEventListener extends Listener { /** diff --git a/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java b/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java index 5b249b3f2..d232c207e 100644 --- a/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java @@ -19,6 +19,10 @@ import io.appium.java_client.events.api.Listener; import org.openqa.selenium.support.events.WebDriverEventListener; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface AppiumWebDriverEventListener extends Listener, WebDriverEventListener, ListensToException, SearchingEventListener, NavigationEventListener, JavaScriptEventListener, ElementEventListener { 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 1f0f9be3e..6b5d72935 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 @@ -20,6 +20,10 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface ElementEventListener extends Listener { /** * Called before {@link WebElement#click WebElement.click()}. diff --git a/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java b/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java index f7addb68e..25556a961 100644 --- a/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java @@ -19,6 +19,10 @@ import io.appium.java_client.events.api.Listener; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface JavaScriptEventListener extends Listener { /** * Called before diff --git a/src/main/java/io/appium/java_client/events/api/general/ListensToException.java b/src/main/java/io/appium/java_client/events/api/general/ListensToException.java index 89733e693..a6f3b4b3d 100644 --- a/src/main/java/io/appium/java_client/events/api/general/ListensToException.java +++ b/src/main/java/io/appium/java_client/events/api/general/ListensToException.java @@ -19,6 +19,10 @@ import io.appium.java_client.events.api.Listener; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface ListensToException extends Listener { /** * Called whenever an exception would be thrown. diff --git a/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java b/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java index d8662960f..9b2b33e39 100644 --- a/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java @@ -19,6 +19,10 @@ import io.appium.java_client.events.api.Listener; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface NavigationEventListener extends Listener { /** diff --git a/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java b/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java index bd5d47ae3..03be74a3e 100644 --- a/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java @@ -21,6 +21,10 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface SearchingEventListener extends Listener { /** diff --git a/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java b/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java index 056043a59..5a50294ec 100644 --- a/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java @@ -21,6 +21,10 @@ import org.openqa.selenium.Point; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface WindowEventListener extends Listener { /** * This action will be performed each time before {@link WebDriver.Window#setSize(Dimension)}. diff --git a/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java b/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java index f3282df76..3372e1b2e 100644 --- a/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java @@ -19,6 +19,10 @@ import io.appium.java_client.events.api.Listener; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface ContextEventListener extends Listener { /** diff --git a/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java b/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java index a500c3d76..b57b8542e 100644 --- a/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java @@ -20,6 +20,10 @@ import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebDriver; +/** + * Deprecated. Use EventFiringDecorator and WebDriverListener instead. + */ +@Deprecated public interface RotationEventListener extends Listener { /** diff --git a/src/test/java/io/appium/java_client/events/AbilityToDefineListenersExternally.java b/src/test/java/io/appium/java_client/events/AbilityToDefineListenersExternally.java deleted file mode 100644 index 91fceed10..000000000 --- a/src/test/java/io/appium/java_client/events/AbilityToDefineListenersExternally.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.appium.java_client.events; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - -import io.appium.java_client.events.listeners.AlertListener2; -import io.appium.java_client.events.listeners.ContextListener2; -import io.appium.java_client.events.listeners.ElementListener2; -import io.appium.java_client.events.listeners.ExceptionListener2; -import io.appium.java_client.events.listeners.JavaScriptListener2; -import io.appium.java_client.events.listeners.NavigationListener2; -import io.appium.java_client.events.listeners.RotationListener2; -import io.appium.java_client.events.listeners.SearchingListener2; -import io.appium.java_client.events.listeners.WindowListener2; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class AbilityToDefineListenersExternally extends BaseListenerTest { - - private static final String PREFIX = "Externally defined listener: "; - private static EmptyWebDriver emptyWebDriver; - private static SearchingListener2 searchingListener = new SearchingListener2(); - private static NavigationListener2 navigationListener = new NavigationListener2(); - private static ElementListener2 elementListener = new ElementListener2(); - private static JavaScriptListener2 javaScriptListener = new JavaScriptListener2(); - private static ExceptionListener2 exceptionListener = new ExceptionListener2(); - private static AlertListener2 alertListener = new AlertListener2(); - private static ContextListener2 contextListener = new ContextListener2(); - private static RotationListener2 rotationListener = new RotationListener2(); - private static WindowListener2 windowListener = new WindowListener2(); - - @BeforeClass public static void beforeClass() { - emptyWebDriver = new EmptyWebDriver(); - emptyWebDriver = EventFiringWebDriverFactory.getEventFiringWebDriver(emptyWebDriver, - searchingListener, navigationListener, elementListener, javaScriptListener, - exceptionListener, alertListener, contextListener, rotationListener, windowListener); - } - - @Test - public void searchContextEventTest() { - assertThat(super.assertThatSearchListenerWorks(emptyWebDriver, searchingListener, PREFIX), - is(true)); - } - - @Test - public void navigationEventTest() throws Exception { - assertThat( - super - .assertThatNavigationListenerWorks(emptyWebDriver, navigationListener, PREFIX), - is(true)); - } - - @Test - public void elementEventTest() { - assertThat(super.assertThatElementListenerWorks(emptyWebDriver, elementListener, PREFIX), - is(true)); - } - - @Test - public void javaScriptEventTest() { - assertThat(super - .assertThatJavaScriptListenerWorks(emptyWebDriver, javaScriptListener, PREFIX), - is(true)); - } - - @Test - public void exceptionEventTest() { - assertThat(super.assertThatExceptionListenerWorks(emptyWebDriver, exceptionListener, PREFIX), - is(true)); - } - - @Test - public void alertEventTest() { - assertThat(super.assertThatAlertListenerWorks(emptyWebDriver, alertListener, PREFIX), - is(true)); - } - - @Test - public void contextEventListener() { - assertThat(super.assertThatConrextListenerWorks(emptyWebDriver, contextListener, PREFIX), - is(true)); - } - - @Test - public void rotationEventListener() { - assertThat(super.assertThatRotationListenerWorks(emptyWebDriver, rotationListener, PREFIX), - is(true)); - } - - @Test - public void windowEventListener() { - assertThat(super.assertThatWindowListenerWorks(emptyWebDriver, windowListener, PREFIX), - is(true)); - } -} diff --git a/src/test/java/io/appium/java_client/events/BaseListenerTest.java b/src/test/java/io/appium/java_client/events/BaseListenerTest.java deleted file mode 100644 index 5ce04f204..000000000 --- a/src/test/java/io/appium/java_client/events/BaseListenerTest.java +++ /dev/null @@ -1,272 +0,0 @@ -package io.appium.java_client.events; - -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.assertThat; - -import java.net.URL; - -import org.openqa.selenium.Alert; -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebDriverException; - -import io.appium.java_client.MobileBy; -import io.appium.java_client.events.listeners.TestListener; - -public class BaseListenerTest { - - protected boolean assertThatSearchListenerWorks(EmptyWebDriver driver, TestListener listener, - String prefix) { - try { - listener.messages.clear(); - - driver.findElement(By.id("someId")); - assertThat(listener.messages, - contains(prefix + "Attempt to find something using By.id: someId. The root element is null", - prefix + "The searching for something using By.id: someId has beed finished. " - + "The root element was null")); - - driver.findElements(By.id("someId2")); - - assertThat(listener.messages, - contains(prefix + "Attempt to find something using By.id: someId. The root element is null", - prefix + "The searching for something using By.id: someId has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.id: someId2. The root element is null", - prefix + "The searching for something using By.id: someId2 has beed finished. " - + "The root element was null")); - - driver.findElement(By.id("someId")).findElement(MobileBy.className("someClazz")); - - assertThat(listener.messages, - contains(prefix + "Attempt to find something using By.id: someId. The root element is null", - prefix + "The searching for something using By.id: someId has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.id: someId2. The root element is null", - prefix + "The searching for something using By.id: someId2 has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.id: someId. " - + "The root element is null", - prefix + "The searching for something using By.id: someId has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.className: someClazz. " - + "The root element is io.appium.java_client.events.StubWebElement", - prefix + "The searching for something using By.className: someClazz has beed finished. " - + "The root element was io.appium.java_client.events.StubWebElement")); - - driver.findElements(By.id("someId2")).get(0).findElements(MobileBy.className("someClazz2")); - assertThat(listener.messages, - contains(prefix + "Attempt to find something using By.id: someId. The root element is null", - prefix + "The searching for something using By.id: someId has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.id: someId2. The root element is null", - prefix + "The searching for something using By.id: someId2 has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.id: someId. The root element is null", - prefix + "The searching for something using By.id: someId has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.className: someClazz. " - + "The root element is io.appium.java_client.events.StubWebElement", - prefix + "The searching for something using By.className: someClazz has beed finished. " - + "The root element was io.appium.java_client.events.StubWebElement", - prefix + "Attempt to find something using By.id: someId2. The root element is null", - prefix + "The searching for something using By.id: someId2 has beed finished. " - + "The root element was null", - prefix + "Attempt to find something using By.className: someClazz2. " - + "The root element is io.appium.java_client.events.StubWebElement", - prefix + "The searching for something using By.className: someClazz2 has beed finished. " - + "The root element was io.appium.java_client.events.StubWebElement")); - return true; - } finally { - listener.messages.clear(); - } - } - - protected boolean assertThatNavigationListenerWorks(EmptyWebDriver driver, - TestListener listener, String prefix) throws Exception { - try { - driver.get("www.google.com"); - driver.navigate().to("www.google2.com"); - driver.navigate().to(new URL("https://www.google3.com")); - driver.navigate().forward(); - driver.navigate().back(); - driver.navigate().refresh(); - - assertThat(listener.messages, - contains(prefix + "Attempt to navigate to www.google.com", - prefix + "Navigation to www.google.com was successful", - prefix + "Attempt to navigate to www.google2.com", - prefix + "Navigation to www.google2.com was successful", - prefix + "Attempt to navigate to https://www.google3.com", - prefix + "Navigation to https://www.google3.com was successful", - prefix + "Attempt to navigate forward", - prefix + "Navigation forward was successful", - prefix + "Attempt to navigate back", - prefix + "Navigation back was successful", - prefix + "Attempt to refresh", - prefix + "The refreshing was successful")); - return true; - } finally { - listener.messages.clear(); - } - } - - protected boolean assertThatElementListenerWorks(EmptyWebDriver driver, TestListener listener, String prefix) { - try { - StubWebElement e = driver.findElement(MobileBy.AccessibilityId("SomeAccessibility")); - listener.messages.clear(); - - e.click(); - e.sendKeys("Test keys"); - - assertThat(listener.messages, - contains(prefix + "Attempt to click on the element", - prefix + "Thee element was clicked", - prefix + "Attempt to change value of the element", - prefix + "The value of the element was changed")); - return true; - } finally { - listener.messages.clear(); - } - } - - - protected boolean assertThatJavaScriptListenerWorks(EmptyWebDriver driver, TestListener listener, String prefix) { - try { - driver.executeScript("Some test script"); - driver.executeAsyncScript("Some test async script"); - - assertThat(listener.messages, - contains(prefix + "Attempt to perform java script: Some test script", - prefix + "Java script Some test script was performed", - prefix + "Attempt to perform java script: Some test async script", - prefix + "Java script Some test async script was performed")); - return true; - } finally { - listener.messages.clear(); - } - } - - protected boolean assertThatExceptionListenerWorks(EmptyWebDriver driver, TestListener listener, String prefix) { - try { - try { - StubWebElement element = driver.findElement(MobileBy.AccessibilityId("SomeAccessibility")); - listener.messages.clear(); - - element.getRect(); - } catch (Exception ignored) { - ignored.printStackTrace(); - } - - try { - driver.getPageSource(); - } catch (Exception ignored) { - ignored.printStackTrace(); - } - - - assertThat(listener.messages, - contains(prefix + "The exception was thrown: " - + WebDriverException.class, - prefix + "The exception was thrown: " - + WebDriverException.class)); - return true; - } finally { - listener.messages.clear(); - } - } - - protected boolean assertThatAlertListenerWorks(EmptyWebDriver driver, TestListener listener, String prefix) { - try { - Alert alert = driver.switchTo().alert(); - alert.accept(); - alert.dismiss(); - alert.sendKeys("Keys"); - - assertThat(listener.messages, - contains(prefix + "Attempt to accept alert", - prefix + "The alert was accepted", - prefix + "Attempt to dismiss alert", - prefix + "The alert was dismissed", - prefix + "Attempt to send keys to alert", - prefix + "Keys were sent to alert")); - return true; - } finally { - listener.messages.clear(); - } - } - - protected boolean assertThatConrextListenerWorks(EmptyWebDriver driver, TestListener listener, String prefix) { - try { - driver.context("NATIVE_APP"); - driver.context("WEB_VIEW"); - - assertThat(listener.messages, - contains(prefix + "Attempt to change current context to NATIVE_APP", - prefix + "The previous context has been changed to NATIVE_APP", - prefix + "Attempt to change current context to WEB_VIEW", - prefix + "The previous context has been changed to WEB_VIEW")); - return true; - } finally { - listener.messages.clear(); - } - } - - - protected boolean assertThatRotationListenerWorks(EmptyWebDriver driver, TestListener listener, - String prefix) { - try { - driver.rotate(ScreenOrientation.LANDSCAPE); - driver.rotate(ScreenOrientation.PORTRAIT); - - assertThat(listener.messages, - contains(prefix + "Attempt to change screen orientation. The new screen orientation is " - + ScreenOrientation.LANDSCAPE.toString(), - prefix + "The screen orientation has been changed to " - + ScreenOrientation.LANDSCAPE.toString(), - prefix + "Attempt to change screen orientation. The new screen orientation is " - + ScreenOrientation.PORTRAIT.toString(), - prefix + "The screen orientation has been changed to " - + ScreenOrientation.PORTRAIT.toString())); - return true; - } finally { - listener.messages.clear(); - } - } - - protected boolean assertThatWindowListenerWorks(EmptyWebDriver driver, TestListener listener, String prefix) { - try { - WebDriver.Window window = driver.manage().window(); - Dimension d = new Dimension(500, 500); - window.setSize(d); - - Point p = new Point(50, 50); - window.setPosition(p); - - window.maximize(); - - driver.switchTo().window("Test window"); - - assertThat(listener.messages, - contains(prefix + "Attempt to change size of the window. The height is " + d.getHeight() - + " the width is " + d.getWidth(), - prefix + "Size of the window has been changed. The height is " + d.getHeight() - + " the width is " + d.getWidth(), - prefix + "Attempt to change position of the window. The X is " + p.getX() - + " the Y is " + p.getY(), - prefix + "The position the window has been changed. The X is " + p.getX() - + " the Y is " + p.getY(), - prefix + "Attempt to maximize the window.", - prefix + "The window has been maximized", - prefix + "Attempt to switch to window Test window", - prefix + "driver is switched to window Test window")); - return true; - } finally { - listener.messages.clear(); - } - - } -} diff --git a/src/test/java/io/appium/java_client/events/CustomListener.java b/src/test/java/io/appium/java_client/events/CustomListener.java new file mode 100644 index 000000000..e9d446462 --- /dev/null +++ b/src/test/java/io/appium/java_client/events/CustomListener.java @@ -0,0 +1,73 @@ +/* + * 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.events; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.events.WebDriverListener; + +import java.lang.reflect.Method; + +public class CustomListener implements WebDriverListener { + private boolean didCallBeforeGet = false; + private boolean didCallAfterGet = false; + private String url; + + private boolean didCallBeforeAnyWebDriverCall = false; + private boolean didCallAfterWebDriverAnyCall = false; + + @Override + public void beforeGet(WebDriver driver, String url) { + didCallBeforeGet = true; + this.url = url; + } + + @Override + public void afterGet(WebDriver driver, String url) { + didCallAfterGet = true; + this.url = url; + } + + @Override + public void beforeAnyWebDriverCall(WebDriver driver, Method method, Object[] args) { + didCallBeforeAnyWebDriverCall = true; + } + + @Override + public void afterAnyWebDriverCall(WebDriver driver, Method method, Object[] args, Object result) { + didCallAfterWebDriverAnyCall = true; + } + + public boolean isDidCallBeforeGet() { + return didCallBeforeGet; + } + + public boolean isDidCallAfterGet() { + return didCallAfterGet; + } + + public String getUrl() { + return url; + } + + public boolean isDidCallBeforeAnyWebDriverCall() { + return didCallBeforeAnyWebDriverCall; + } + + public boolean isDidCallAfterWebDriverAnyCall() { + return didCallAfterWebDriverAnyCall; + } +} \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/events/DefaultEventListenerTest.java b/src/test/java/io/appium/java_client/events/DefaultEventListenerTest.java deleted file mode 100644 index 7cbdfee4f..000000000 --- a/src/test/java/io/appium/java_client/events/DefaultEventListenerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package io.appium.java_client.events; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import org.apache.commons.lang3.StringUtils; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; -import org.openqa.selenium.Capabilities; - -import io.appium.java_client.events.listeners.AlertListener; -import io.appium.java_client.events.listeners.ContextListener; -import io.appium.java_client.events.listeners.ElementListener; -import io.appium.java_client.events.listeners.ExceptionListener; -import io.appium.java_client.events.listeners.JavaScriptListener; -import io.appium.java_client.events.listeners.NavigationListener; -import io.appium.java_client.events.listeners.RotationListener; -import io.appium.java_client.events.listeners.SearchingListener; -import io.appium.java_client.events.listeners.SingleListeners; -import io.appium.java_client.events.listeners.WindowListener; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class DefaultEventListenerTest extends BaseListenerTest { - - private static EmptyWebDriver driver; - - @BeforeClass public static void beforeClass() { - EmptyWebDriver emptyWebDriver = new EmptyWebDriver(); - driver = EventFiringWebDriverFactory.getEventFiringWebDriver(emptyWebDriver); - } - - @Test - public void searchContextEventTest() { - assertThat(super.assertThatSearchListenerWorks(driver, SingleListeners - .listeners.get(SearchingListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void navigationEventTest() throws Exception { - assertThat(super.assertThatNavigationListenerWorks(driver, SingleListeners - .listeners.get(NavigationListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void elementEventTest() { - assertThat(super.assertThatElementListenerWorks(driver, SingleListeners - .listeners.get(ElementListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void javaScriptEventTest() { - assertThat(super.assertThatJavaScriptListenerWorks(driver, SingleListeners - .listeners.get(JavaScriptListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void exceptionEventTest() { - assertThat(super.assertThatExceptionListenerWorks(driver, SingleListeners - .listeners.get(ExceptionListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void alertEventTest() { - assertThat(super.assertThatAlertListenerWorks(driver, SingleListeners - .listeners.get(AlertListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void contextEventListener() { - assertThat(super.assertThatConrextListenerWorks(driver, SingleListeners - .listeners.get(ContextListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void rotationEventListener() { - assertThat(super.assertThatRotationListenerWorks(driver, SingleListeners - .listeners.get(RotationListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void windowEventListener() { - assertThat(super.assertThatWindowListenerWorks(driver, SingleListeners - .listeners.get(WindowListener.class), StringUtils.EMPTY), is(true)); - } - - @Test - public void whenNonListenableObjectIsReturned() { - Capabilities capabilities = driver.getCapabilities(); - assertNotNull(capabilities); - assertEquals(capabilities.asMap().size(), 2); - } -} diff --git a/src/test/java/io/appium/java_client/events/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/EmptyWebDriver.java deleted file mode 100644 index 5bc7149c0..000000000 --- a/src/test/java/io/appium/java_client/events/EmptyWebDriver.java +++ /dev/null @@ -1,249 +0,0 @@ -package io.appium.java_client.events; - -import com.google.common.collect.ImmutableList; - -import org.apache.commons.lang3.StringUtils; -import org.openqa.selenium.Alert; -import org.openqa.selenium.By; -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.OutputType; -import org.openqa.selenium.Rotatable; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.TakesScreenshot; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.WindowType; -import org.openqa.selenium.logging.Logs; -import org.openqa.selenium.remote.DesiredCapabilities; - -import java.net.URL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class EmptyWebDriver implements WebDriver, ContextAware, Rotatable, JavascriptExecutor, HasCapabilities, - TakesScreenshot { - - private static List createStubList() { - return ImmutableList.of(new StubWebElement(), new StubWebElement()); - } - - @Override public WebDriver context(String name) { - return null; - } - - @Override public Set getContextHandles() { - return null; - } - - @Override public String getContext() { - return StringUtils.EMPTY; - } - - @Override public void rotate(ScreenOrientation orientation) { - //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 - } - - @Override public String getCurrentUrl() { - return null; - } - - @Override public String getTitle() { - return null; - } - - @Override public StubWebElement findElement(By by) { - return new StubWebElement(); - } - - @Override public List findElements(By by) { - return createStubList(); - } - - @Override public String getPageSource() { - throw new WebDriverException(); - } - - @Override public void close() { - //There is no closing - } - - @Override public void quit() { - //It is only the stub - } - - @Override public Set getWindowHandles() { - return null; - } - - @Override public String getWindowHandle() { - throw new WebDriverException(); - } - - @Override public TargetLocator switchTo() { - return new StubTargetLocator(this); - } - - @Override public Navigation navigate() { - return new StubNavigation(); - } - - @Override public Options manage() { - return new StubOptions(); - } - - @Override public Object executeScript(String script, Object... args) { - return null; - } - - @Override public Object executeAsyncScript(String script, Object... args) { - return null; - } - - @Override public Capabilities getCapabilities() { - Map map = new HashMap<>(); - map.put("0",StringUtils.EMPTY); - map.put("1",StringUtils.EMPTY); - return new DesiredCapabilities(map); - } - - @Override - public X getScreenshotAs(OutputType target) throws WebDriverException { - return target.convertFromPngBytes(new byte[]{1,2}); - } - - private class StubTargetLocator implements TargetLocator { - - private final WebDriver driver; - - StubTargetLocator(WebDriver driver) { - this.driver = driver; - } - - @Override public WebDriver frame(int index) { - return driver; - } - - @Override public WebDriver frame(String nameOrId) { - return driver; - } - - @Override public WebDriver frame(WebElement frameElement) { - return driver; - } - - @Override public WebDriver parentFrame() { - return driver; - } - - @Override public WebDriver window(String nameOrHandle) { - return driver; - } - - @Override - public WebDriver newWindow(WindowType typeHint) { - return driver; - } - - @Override public WebDriver defaultContent() { - return driver; - } - - @Override public WebElement activeElement() { - return new StubWebElement(); - } - - @Override public Alert alert() { - return new StubAlert(); - } - } - - private class StubOptions implements Options { - - @Override public void addCookie(Cookie cookie) { - //STUB: No adding cookie - } - - @Override public void deleteCookieNamed(String name) { - //STUB No removal cookie - } - - @Override public void deleteCookie(Cookie cookie) { - //STUB No deleting cookie - } - - @Override public void deleteAllCookies() { - //STUB it does nothing - } - - @Override public Set getCookies() { - return null; - } - - @Override public Cookie getCookieNamed(String name) { - return null; - } - - @Override public Timeouts timeouts() { - return null; - } - - @Override public ImeHandler ime() { - return null; - } - - @Override public Window window() { - return new StubWindow(); - } - - @Override public Logs logs() { - return null; - } - } - - private class StubNavigation implements Navigation { - - @Override public void back() { - //STUB: It doesn't navigate back - } - - @Override public void forward() { - //STUB: No the navigation forward - } - - @Override public void to(String url) { - //STUB: Added only for event firing - } - - @Override public void to(URL url) { - //STUB: Event firing of the navigation to some URL - } - - @Override public void refresh() { - //STUB: The firing of the refreshing - } - } -} diff --git a/src/test/java/io/appium/java_client/events/EventsFiringTest.java b/src/test/java/io/appium/java_client/events/EventsFiringTest.java new file mode 100644 index 000000000..f6d0d2890 --- /dev/null +++ b/src/test/java/io/appium/java_client/events/EventsFiringTest.java @@ -0,0 +1,53 @@ +/* + * 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.events; + +import io.appium.java_client.events.stubs.EmptyWebDriver; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.events.EventFiringDecorator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class EventsFiringTest { + private final WebDriver emptyWebDriver = new EmptyWebDriver(); + private CustomListener listener; + private WebDriver decorated; + + @Before + public void beforeTest() { + listener = new CustomListener(); + decorated = new EventFiringDecorator(listener).decorate(emptyWebDriver); + } + + @Test + public void checkBasicEventsFiring() { + decorated.get("http://example.com/"); + assertTrue(listener.isDidCallBeforeGet()); + assertTrue(listener.isDidCallAfterGet()); + assertEquals(listener.getUrl(), "http://example.com/"); + } + + @Test + public void checkAnyWebDriverEventsFiring() { + decorated.get("http://example.com/"); + assertTrue(listener.isDidCallBeforeAnyWebDriverCall()); + assertTrue(listener.isDidCallAfterWebDriverAnyCall()); + } +} diff --git a/src/test/java/io/appium/java_client/events/ExtendedEventListenerTest.java b/src/test/java/io/appium/java_client/events/ExtendedEventListenerTest.java deleted file mode 100644 index 560875eb4..000000000 --- a/src/test/java/io/appium/java_client/events/ExtendedEventListenerTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.appium.java_client.events; - -import static org.hamcrest.core.IsIterableContaining.hasItems; -import static org.junit.Assert.assertThat; - -import io.appium.java_client.MobileBy; -import io.appium.java_client.events.listeners.SearchingListener; -import io.appium.java_client.events.listeners.SingleListeners; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openqa.selenium.By; - -public class ExtendedEventListenerTest { - - private static EmptyWebDriver stubWebDriver; - - @BeforeClass public static void beforeClass() { - stubWebDriver = new EmptyWebDriver(); - stubWebDriver = EventFiringWebDriverFactory.getEventFiringWebDriver(stubWebDriver); - } - - @Test - public void searchingTest() { - StubWebElement androidElement = stubWebDriver.findElement(By.id("someId")); - androidElement.findElement(MobileBy.custom("some value")) - .findElements(MobileBy.AndroidUIAutomator("Android UI Automator")); - androidElement.findElements(MobileBy.custom("some value2")).get(0) - .findElements(MobileBy.AndroidUIAutomator("Android UI Automator2")); - - SearchingListener listener = (SearchingListener) SingleListeners - .listeners.get(SearchingListener.class); - assertThat(listener.messages, - hasItems("Attempt to find something using By.AndroidUIAutomator: Android UI Automator. " - + "The root element is io.appium.java_client.events.StubWebElement", - "The searching for something using By.AndroidUIAutomator: Android UI Automator has " - + "beed finished. " - + "The root element was io.appium.java_client.events.StubWebElement", - "Attempt to find something using By.AndroidUIAutomator: Android UI Automator2. " - + "The root element is io.appium.java_client.events.StubWebElement", - "The searching for something using By.AndroidUIAutomator: Android UI Automator2 " - + "has beed finished. " - + "The root element was io.appium.java_client.events.StubWebElement")); - } -} diff --git a/src/test/java/io/appium/java_client/events/FewInstancesTest.java b/src/test/java/io/appium/java_client/events/FewInstancesTest.java deleted file mode 100644 index b195cc0ba..000000000 --- a/src/test/java/io/appium/java_client/events/FewInstancesTest.java +++ /dev/null @@ -1,176 +0,0 @@ -package io.appium.java_client.events; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertThat; - -import org.apache.commons.lang3.StringUtils; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openqa.selenium.WebDriver; - -import io.appium.java_client.events.listeners.AlertListener; -import io.appium.java_client.events.listeners.ContextListener; -import io.appium.java_client.events.listeners.ElementListener; -import io.appium.java_client.events.listeners.ExceptionListener; -import io.appium.java_client.events.listeners.JavaScriptListener; -import io.appium.java_client.events.listeners.NavigationListener; -import io.appium.java_client.events.listeners.RotationListener; -import io.appium.java_client.events.listeners.SearchingListener; -import io.appium.java_client.events.listeners.SingleListeners; -import io.appium.java_client.events.listeners.WindowListener; - -public class FewInstancesTest extends BaseListenerTest { - - private static EmptyWebDriver emptyWebDriver1; - private static SearchingListener searchingListener1; - private static NavigationListener navigationListener1; - private static ElementListener elementListener1; - private static JavaScriptListener javaScriptListener1; - private static ExceptionListener exceptionListener1; - private static AlertListener alertListener1; - private static ContextListener contextListener1; - private static RotationListener rotationListener1; - private static WindowListener windowListener1; - - private static SearchingListener searchingListener2; - private static NavigationListener navigationListener2; - private static ElementListener elementListener2; - private static JavaScriptListener javaScriptListener2; - private static ExceptionListener exceptionListener2; - private static AlertListener alertListener2; - private static ContextListener contextListener2; - private static RotationListener rotationListener2; - private static WindowListener windowListener2; - - @BeforeClass public static void beforeClass() { - emptyWebDriver1 = new EmptyWebDriver(); - emptyWebDriver1 = EventFiringWebDriverFactory.getEventFiringWebDriver(emptyWebDriver1); - - searchingListener1 = (SearchingListener) SingleListeners - .listeners.get(SearchingListener.class); - navigationListener1 = (NavigationListener) SingleListeners - .listeners.get(NavigationListener.class); - elementListener1 = (ElementListener) SingleListeners - .listeners.get(ElementListener.class); - javaScriptListener1 = (JavaScriptListener) SingleListeners - .listeners.get(JavaScriptListener.class); - exceptionListener1 = (ExceptionListener) SingleListeners - .listeners.get(ExceptionListener.class); - alertListener1 = (AlertListener) SingleListeners - .listeners.get(AlertListener.class); - contextListener1 = (ContextListener) SingleListeners - .listeners.get(ContextListener.class); - rotationListener1 = (RotationListener) SingleListeners - .listeners.get(RotationListener.class); - windowListener1 = - (WindowListener) SingleListeners.listeners.get(WindowListener.class); - - WebDriver stubWebDriver2 = new EmptyWebDriver(); - EventFiringWebDriverFactory.getEventFiringWebDriver(stubWebDriver2); - - searchingListener2 = (SearchingListener) SingleListeners - .listeners.get(SearchingListener.class); - navigationListener2 = (NavigationListener) SingleListeners - .listeners.get(NavigationListener.class); - elementListener2 = (ElementListener) SingleListeners - .listeners.get(ElementListener.class); - javaScriptListener2 = (JavaScriptListener) SingleListeners - .listeners.get(JavaScriptListener.class); - exceptionListener2 = (ExceptionListener) SingleListeners - .listeners.get(ExceptionListener.class); - alertListener2 = (AlertListener) SingleListeners - .listeners.get(AlertListener.class); - contextListener2 = (ContextListener) SingleListeners - .listeners.get(ContextListener.class); - rotationListener2 = (RotationListener) SingleListeners - .listeners.get(RotationListener.class); - windowListener2 = - (WindowListener) SingleListeners.listeners.get(WindowListener.class); - } - - @Test - public void listenersAreDifferent() { - assertNotEquals(searchingListener1, searchingListener2); - assertNotEquals(elementListener1, elementListener2); - assertNotEquals(navigationListener1, navigationListener2); - assertNotEquals(javaScriptListener1, javaScriptListener2); - assertNotEquals(exceptionListener1, exceptionListener2); - assertNotEquals(alertListener1, alertListener2); - assertNotEquals(contextListener1, contextListener2); - assertNotEquals(rotationListener1, rotationListener2); - assertNotEquals(windowListener1, windowListener2); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother() { - assertThat(super.assertThatSearchListenerWorks(emptyWebDriver1, - searchingListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second searching listener should have no messages", - searchingListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother3() throws Exception { - assertThat(super.assertThatNavigationListenerWorks(emptyWebDriver1, - navigationListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second navigation listener should have no messages", - navigationListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother4() { - assertThat(super.assertThatJavaScriptListenerWorks(emptyWebDriver1, - javaScriptListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second java script listener should have no messages", - javaScriptListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother5() { - assertThat(super.assertThatExceptionListenerWorks(emptyWebDriver1, - exceptionListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second exception listener should have no messages", - exceptionListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother6() { - assertThat(super.assertThatAlertListenerWorks(emptyWebDriver1, - alertListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second alert listener should have no messages", - alertListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother7() { - assertThat(super.assertThatConrextListenerWorks(emptyWebDriver1, - contextListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second context listener should have no messages", - contextListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother8() { - assertThat(super.assertThatRotationListenerWorks(emptyWebDriver1, - rotationListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second rotation listener should have no messages", - rotationListener2.messages.size(), is(0)); - } - - @Test - public void assertThatOneDriverDoNotListensToAnother9() { - assertThat(super.assertThatWindowListenerWorks(emptyWebDriver1, - windowListener1, StringUtils.EMPTY), - is(true)); - assertThat("The second window listener should have no messages", - windowListener2.messages.size(), is(0)); - } -} diff --git a/src/test/java/io/appium/java_client/events/ListenableObjectTest.java b/src/test/java/io/appium/java_client/events/ListenableObjectTest.java deleted file mode 100644 index 4d7002390..000000000 --- a/src/test/java/io/appium/java_client/events/ListenableObjectTest.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.appium.java_client.events; - -import static com.google.common.collect.ImmutableSortedSet.of; -import static io.appium.java_client.events.EventFiringObjectFactory.getEventFiringObject; -import static io.appium.java_client.events.EventFiringWebDriverFactory.getEventFiringWebDriver; -import static io.appium.java_client.events.listeners.SingleListeners.listeners; -import static org.apache.commons.lang3.StringUtils.EMPTY; -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - -import io.appium.java_client.events.listeners.AlertListener; -import io.appium.java_client.events.listeners.AlertListener2; -import io.appium.java_client.events.listeners.ContextListener; -import io.appium.java_client.events.listeners.ContextListener2; -import io.appium.java_client.events.listeners.SearchingListener; -import io.appium.java_client.events.listeners.SearchingListener2; -import org.junit.Test; -import org.openqa.selenium.Alert; -import org.openqa.selenium.By; -import org.openqa.selenium.ContextAware; -import org.openqa.selenium.WebDriver; - -import java.util.Set; -import java.util.function.Predicate; - -public class ListenableObjectTest { - private static final String PREFIX = "Externally defined listener: "; - - private final EmptyWebDriver emptyWebDriver = new EmptyWebDriver(); - private final ContextListener2 contextListener = new ContextListener2(); - private final AlertListener2 alertListener = new AlertListener2(); - private final SearchingListener2 searchingListener = new SearchingListener2(); - - private final ContextAware contextAware = new ContextAware() { - @Override - public WebDriver context(String name) { - return emptyWebDriver; - } - - @Override - public Set getContextHandles() { - return of(EMPTY); - } - - @Override - public String getContext() { - return EMPTY; - } - }; - - private final Predicate contextAwarePredicate = (contextAware) -> { - contextAware.context("WEB_VIEW"); - - assertThat(contextListener.messages, - contains(PREFIX + "Attempt to change current context to NATIVE_APP", - PREFIX + "The previous context has been changed to NATIVE_APP", - PREFIX + "Attempt to change current context to WEB_VIEW", - PREFIX + "The previous context has been changed to WEB_VIEW")); - - ContextListener singleContextListener = (ContextListener) - listeners.get(ContextListener.class); - assertThat(singleContextListener.messages, - contains("Attempt to change current context to NATIVE_APP", - "The previous context has been changed to NATIVE_APP", - "Attempt to change current context to WEB_VIEW", - "The previous context has been changed to WEB_VIEW")); - return true; - }; - - private final Predicate alertPredicate = alert -> { - alert.accept(); - alert.dismiss(); - alert.sendKeys("Keys"); - - assertThat(alertListener.messages, - contains(PREFIX + "Attempt to accept alert", - PREFIX + "The alert was accepted", - PREFIX + "Attempt to dismiss alert", - PREFIX + "The alert was dismissed", - PREFIX + "Attempt to send keys to alert", - PREFIX + "Keys were sent to alert")); - - AlertListener singleAlertListener = (AlertListener) - listeners.get(AlertListener.class); - - assertThat(singleAlertListener.messages, - contains("Attempt to accept alert", - "The alert was accepted", - "Attempt to dismiss alert", - "The alert was dismissed", - "Attempt to send keys to alert", - "Keys were sent to alert")); - return true; - }; - - private final Predicate webDriverPredicate = driver -> { - driver.findElement(By.id("someId")); - assertThat(searchingListener.messages, - contains(PREFIX + "Attempt to find something using By.id: someId. The root element is null", - PREFIX + "The searching for something using By.id: someId has beed finished. " - + "The root element was null")); - - SearchingListener singleSearchingListener = (SearchingListener) - listeners.get(SearchingListener.class); - - assertThat(singleSearchingListener.messages, - contains("Attempt to find something using By.id: someId. The root element is null", - "The searching for something using By.id: someId has beed finished. " - + "The root element was null")); - return true; - }; - - - @Test public void listenableObjectSample() { - try { - ContextAware listenableContextAware = - getEventFiringObject(contextAware, emptyWebDriver, contextListener, alertListener); - WebDriver webDriver = listenableContextAware.context("NATIVE_APP"); - assertTrue(contextAwarePredicate.test(listenableContextAware)); - - Alert alert = webDriver.switchTo().alert(); - assertTrue(alertPredicate.test(alert)); - - assertTrue(webDriverPredicate.test(getEventFiringWebDriver(webDriver, searchingListener))); - } finally { - listeners.get(ContextListener.class).messages.clear(); - listeners.get(AlertListener.class).messages.clear(); - listeners.get(SearchingListener.class).messages.clear(); - } - } -} diff --git a/src/test/java/io/appium/java_client/events/StubAlert.java b/src/test/java/io/appium/java_client/events/StubAlert.java deleted file mode 100644 index aad32c596..000000000 --- a/src/test/java/io/appium/java_client/events/StubAlert.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.appium.java_client.events; - -import org.apache.commons.lang3.StringUtils; -import org.openqa.selenium.Alert; - -public class StubAlert implements Alert { - @Override public void dismiss() { - //STUB it does nothing - } - - @Override public void accept() { - //STUB it does nothing - } - - @Override public String getText() { - return StringUtils.EMPTY; - } - - @Override public void sendKeys(String keysToSend) { - //STUB it does nothing - } -} diff --git a/src/test/java/io/appium/java_client/events/StubWebElement.java b/src/test/java/io/appium/java_client/events/StubWebElement.java deleted file mode 100644 index 0e9c2a5d6..000000000 --- a/src/test/java/io/appium/java_client/events/StubWebElement.java +++ /dev/null @@ -1,93 +0,0 @@ -package io.appium.java_client.events; - -import com.google.common.collect.ImmutableList; - -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.OutputType; -import org.openqa.selenium.Point; -import org.openqa.selenium.Rectangle; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; - -import java.util.ArrayList; -import java.util.List; - -public class StubWebElement implements WebElement { - - private static List createStubSubElementList() { - return new ArrayList<>(ImmutableList.of(new StubWebElement(), new StubWebElement())); - } - - @Override public void click() { - //There is no clicking. It is STUB. - } - - @Override public void submit() { - //No submitting - } - - @Override public void sendKeys(CharSequence... keysToSend) { - //There is no the sending keys. - } - - @Override public void clear() { - //It doesn't clearing anything. - } - - @Override public String getTagName() { - return null; - } - - @Override public String getAttribute(String name) { - return null; - } - - @Override public boolean isSelected() { - return false; - } - - @Override public boolean isEnabled() { - return false; - } - - @Override public String getText() { - return null; - } - - @Override public List findElements(By by) { - return createStubSubElementList(); - } - - @Override public WebElement findElement(By by) { - return new StubWebElement(); - } - - @Override public boolean isDisplayed() { - return false; - } - - @Override public Point getLocation() { - return null; - } - - @Override public Dimension getSize() { - return null; - } - - @Override public Rectangle getRect() { - throw new WebDriverException(); - } - - @Override public String getCssValue(String propertyName) { - return null; - } - - @Override public X getScreenshotAs(OutputType target) throws WebDriverException { - return target.convertFromPngBytes(new byte[]{1,2}); - } - - @Override public String toString() { - return this.getClass().getCanonicalName(); - } -} diff --git a/src/test/java/io/appium/java_client/events/StubWindow.java b/src/test/java/io/appium/java_client/events/StubWindow.java deleted file mode 100644 index 21d6580f4..000000000 --- a/src/test/java/io/appium/java_client/events/StubWindow.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.appium.java_client.events; - -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebDriver; - -public class StubWindow implements WebDriver.Window { - @Override public void setSize(Dimension targetSize) { - //STUB it does nothing - } - - @Override public void setPosition(Point targetPosition) { - //STUB it does nothing - } - - @Override public Dimension getSize() { - return null; - } - - @Override public Point getPosition() { - return null; - } - - @Override public void maximize() { - //STUB it does nothing - } - - @Override - public void minimize() { - //STUB it does nothing - } - - @Override public void fullscreen() { - //STUB it does nothing - } -} diff --git a/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java b/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java deleted file mode 100644 index aa6fd3656..000000000 --- a/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package io.appium.java_client.events; - -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsIterableContaining.hasItems; -import static org.junit.Assert.assertThat; -import static org.openqa.selenium.By.id; -import static org.openqa.selenium.By.xpath; -import static org.openqa.selenium.OutputType.BASE64; - -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; -import org.openqa.selenium.Alert; - -import io.appium.java_client.events.listeners.AppiumListener; -import io.appium.java_client.events.listeners.SingleListeners; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class WebDriverEventListenerCompatibilityTest extends BaseListenerTest { - - private static EmptyWebDriver driver; - private static AppiumListener listener; - private static final String WEBDRIVER_EVENT_LISTENER = "WebDriverEventListener: "; - - @BeforeClass public static void beforeClass() { - EmptyWebDriver emptyWebDriver = new EmptyWebDriver(); - driver = EventFiringWebDriverFactory.getEventFiringWebDriver(emptyWebDriver); - listener = (AppiumListener) SingleListeners.listeners.get(AppiumListener.class); - } - - @Test - public void searchContextEventTest() { - assertThat(super.assertThatSearchListenerWorks(driver, listener, WEBDRIVER_EVENT_LISTENER), - is(true)); - } - - - @Test - public void navigationEventTest() throws Exception { - assertThat(super.assertThatNavigationListenerWorks(driver, - listener, WEBDRIVER_EVENT_LISTENER), - is(true)); - } - - @Test - public void elementEventTest() { - assertThat(super.assertThatElementListenerWorks(driver, listener, WEBDRIVER_EVENT_LISTENER), - is(true)); - } - - @Test - public void javaScriptEventTest() { - assertThat(super.assertThatJavaScriptListenerWorks(driver, - listener, WEBDRIVER_EVENT_LISTENER), - is(true)); - } - - @Test - public void alertEventTest() { - try { - Alert alert = driver.switchTo().alert(); - alert.accept(); - alert.dismiss(); - alert.sendKeys("Keys"); - - assertThat(listener.messages, - hasItems(WEBDRIVER_EVENT_LISTENER + "Attempt to accept alert", - WEBDRIVER_EVENT_LISTENER + "The alert was accepted", - WEBDRIVER_EVENT_LISTENER + "Attempt to dismiss alert", - WEBDRIVER_EVENT_LISTENER + "The alert was dismissed")); - } finally { - listener.messages.clear(); - } - } - - @Test - public void takeScreenShotEventTest() { - try { - driver.getScreenshotAs(BASE64); - driver.findElement(xpath(".//some//path")).findElement(id("someId")).getScreenshotAs(BASE64); - - assertThat(listener.messages, - contains("WebDriverEventListener: Attempt to take screen shot. Target type is OutputType.BASE64", - "WebDriverEventListener: Screen shot was taken successfully. Target type is " - + "OutputType.BASE64, result is AQI=", - "WebDriverEventListener: Attempt to find something using By.xpath: .//some//path. " - + "The root element is null", - "WebDriverEventListener: The searching for something using " - + "By.xpath: .//some//path has beed finished. " - + "The root element was null", - "WebDriverEventListener: Attempt to find something using By.id: someId. " - + "The root element is io.appium.java_client.events.StubWebElement", - "WebDriverEventListener: The searching for something using " - + "By.id: someId has beed finished. " - + "The root element was io.appium.java_client.events.StubWebElement", - "WebDriverEventListener: Attempt to take screen shot. Target type is OutputType.BASE64", - "WebDriverEventListener: Screen shot was taken successfully. " - + "Target type is OutputType.BASE64, result is AQI=")); - } finally { - listener.messages.clear(); - } - } - - @Test - public void exceptionEventTest() { - assertThat(super.assertThatExceptionListenerWorks(driver, listener, WEBDRIVER_EVENT_LISTENER), - is(true)); - } - - @Test - public void windowListenerTest() { - try { - driver.switchTo().window("Test window"); - assertThat(listener.messages, - hasItems(WEBDRIVER_EVENT_LISTENER + "Attempt to switch to window Test window", - WEBDRIVER_EVENT_LISTENER + "driver is switched to window Test window")); - } finally { - listener.messages.clear(); - } - - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/AlertListener.java b/src/test/java/io/appium/java_client/events/listeners/AlertListener.java deleted file mode 100644 index 949431247..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/AlertListener.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.AlertEventListener; -import org.openqa.selenium.Alert; -import org.openqa.selenium.WebDriver; - -public class AlertListener extends TestListener implements AlertEventListener { - @Override public void beforeAlertAccept(WebDriver driver, Alert alert) { - messages.add("Attempt to accept alert"); - } - - @Override public void afterAlertAccept(WebDriver driver, Alert alert) { - messages.add("The alert was accepted"); - } - - @Override public void afterAlertDismiss(WebDriver driver, Alert alert) { - messages.add("The alert was dismissed"); - } - - @Override public void beforeAlertDismiss(WebDriver driver, Alert alert) { - messages.add("Attempt to dismiss alert"); - } - - @Override public void beforeAlertSendKeys(WebDriver driver, Alert alert, String keys) { - messages.add("Attempt to send keys to alert"); - } - - @Override public void afterAlertSendKeys(WebDriver driver, Alert alert, String keys) { - messages.add("Keys were sent to alert"); - } - - @Override protected void add() { - SingleListeners.listeners.put(AlertListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/AlertListener2.java b/src/test/java/io/appium/java_client/events/listeners/AlertListener2.java deleted file mode 100644 index 5d75ed58b..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/AlertListener2.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.AlertEventListener; -import org.openqa.selenium.Alert; -import org.openqa.selenium.WebDriver; - -public class AlertListener2 extends TestListener implements AlertEventListener { - @Override public void beforeAlertAccept(WebDriver driver, Alert alert) { - messages.add("Externally defined listener: Attempt to accept alert"); - } - - @Override public void afterAlertAccept(WebDriver driver, Alert alert) { - messages.add("Externally defined listener: The alert was accepted"); - } - - @Override public void afterAlertDismiss(WebDriver driver, Alert alert) { - messages.add("Externally defined listener: The alert was dismissed"); - } - - @Override public void beforeAlertDismiss(WebDriver driver, Alert alert) { - messages.add("Externally defined listener: Attempt to dismiss alert"); - } - - @Override public void beforeAlertSendKeys(WebDriver driver, Alert alert, String keys) { - messages.add("Externally defined listener: Attempt to send keys to alert"); - } - - @Override public void afterAlertSendKeys(WebDriver driver, Alert alert, String keys) { - messages.add("Externally defined listener: Keys were sent to alert"); - } - - @Override protected void add() { - SingleListeners.listeners.put(AlertListener2.class, this); - } -} 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 deleted file mode 100644 index b74cad265..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java +++ /dev/null @@ -1,147 +0,0 @@ -package io.appium.java_client.events.listeners; - -import static java.lang.String.format; - -import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; -import org.openqa.selenium.By; -import org.openqa.selenium.OutputType; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -public class AppiumListener extends TestListener implements AppiumWebDriverEventListener { - @Override protected void add() { - SingleListeners.listeners.put(AppiumListener.class, this); - } - - @Override - public void beforeAlertAccept(WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to accept alert"); - } - - @Override - public void afterAlertAccept(WebDriver driver) { - messages.add("WebDriverEventListener: The alert was accepted"); - } - - @Override - public void afterAlertDismiss(WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to dismiss alert"); - } - - @Override - public void beforeAlertDismiss(WebDriver driver) { - messages.add("WebDriverEventListener: The alert was dismissed"); - } - - @Override public void beforeNavigateTo(String url, WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to navigate to " + url); - } - - @Override public void afterNavigateTo(String url, WebDriver driver) { - messages.add("WebDriverEventListener: Navigation to " + url + " was successful"); - } - - @Override public void beforeNavigateBack(WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to navigate back"); - } - - @Override public void afterNavigateBack(WebDriver driver) { - messages.add("WebDriverEventListener: Navigation back was successful"); - } - - @Override public void beforeNavigateForward(WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to navigate forward"); - } - - @Override public void afterNavigateForward(WebDriver driver) { - messages.add("WebDriverEventListener: Navigation forward was successful"); - } - - @Override public void beforeNavigateRefresh(WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to refresh"); - } - - @Override public void afterNavigateRefresh(WebDriver driver) { - messages.add("WebDriverEventListener: The refreshing was successful"); - } - - @Override public void beforeFindBy(By by, WebElement element, WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to find something using " + by.toString() - + ". The root element is " - + String.valueOf(element)); - } - - @Override public void afterFindBy(By by, WebElement element, WebDriver driver) { - messages.add("WebDriverEventListener: The searching for something using " - + by.toString() + " has beed finished. " - + "The root element was " - + String.valueOf(element)); - } - - @Override public void beforeClickOn(WebElement element, WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to click on the element"); - } - - @Override public void afterClickOn(WebElement element, WebDriver driver) { - 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"); - } - - @Override public void afterChangeValueOf(WebElement element, WebDriver driver) { - 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); - } - - @Override public void afterScript(String script, WebDriver driver) { - messages.add("WebDriverEventListener: Java script " + script + " was performed"); - } - - @Override public void onException(Throwable throwable, WebDriver driver) { - messages.add("WebDriverEventListener: The exception was thrown: " + throwable.getClass()); - } - - @Override - public void beforeGetScreenshotAs(OutputType target) { - messages.add(format("WebDriverEventListener: Attempt to take screen shot. Target type is %s", target)); - } - - @Override - public void afterGetScreenshotAs(OutputType target, X screenshot) { - messages.add(format("WebDriverEventListener: Screen shot was taken successfully. " - + "Target type is %s, result is %s", target, screenshot)); - } - - @Override public void beforeGetText(WebElement element, WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to get text of the element"); - } - - @Override public void afterGetText(WebElement element, WebDriver driver, String text) { - messages.add("WebDriverEventListener: Got the text of an element"); - } - - @Override - public void beforeSwitchToWindow(String windowName, WebDriver driver) { - messages.add(format("WebDriverEventListener: Attempt to switch to window %s", windowName)); - } - - @Override - public void afterSwitchToWindow(String windowName, WebDriver driver) { - messages.add(format("WebDriverEventListener: driver is switched to window %s", windowName)); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/ContextListener.java b/src/test/java/io/appium/java_client/events/listeners/ContextListener.java deleted file mode 100644 index 5b97d1dd4..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/ContextListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.mobile.ContextEventListener; -import org.openqa.selenium.WebDriver; - -public class ContextListener extends TestListener implements ContextEventListener { - @Override public void beforeSwitchingToContext(WebDriver driver, String context) { - messages.add("Attempt to change current context to " + context); - } - - @Override public void afterSwitchingToContext(WebDriver driver, String context) { - messages.add("The previous context has been changed to " + context); - } - - @Override protected void add() { - SingleListeners.listeners.put(ContextListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/ContextListener2.java b/src/test/java/io/appium/java_client/events/listeners/ContextListener2.java deleted file mode 100644 index 979c19a1a..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/ContextListener2.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.mobile.ContextEventListener; -import org.openqa.selenium.WebDriver; - -public class ContextListener2 extends TestListener implements ContextEventListener { - @Override public void beforeSwitchingToContext(WebDriver driver, String context) { - messages.add("Externally defined listener: Attempt to change current context to " + context); - } - - @Override public void afterSwitchingToContext(WebDriver driver, String context) { - messages.add("Externally defined listener: The previous context has been changed to " + context); - } - - @Override protected void add() { - SingleListeners.listeners.put(ContextListener2.class, this); - } -} 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 deleted file mode 100644 index f1733aa53..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/ElementListener.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.ElementEventListener; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -public class ElementListener extends TestListener implements ElementEventListener { - - @Override public void beforeClickOn(WebElement element, WebDriver driver) { - messages.add("Attempt to click on the element"); - } - - @Override public void afterClickOn(WebElement element, WebDriver driver) { - messages.add("Thee element was clicked"); - } - - @Override public void beforeChangeValueOf(WebElement element, WebDriver driver) { - 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 public void beforeGetText(WebElement element, WebDriver driver) { - messages.add("Attempt to get text of the element"); - } - - @Override public void afterGetText(WebElement element, WebDriver driver, String text) { - messages.add("Got the text of an element"); - } - - @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 deleted file mode 100644 index 134db81e0..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/ElementListener2.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.ElementEventListener; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -public class ElementListener2 extends TestListener implements ElementEventListener { - - @Override public void beforeClickOn(WebElement element, WebDriver driver) { - messages.add("Externally defined listener: Attempt to click on the element"); - } - - @Override public void afterClickOn(WebElement element, WebDriver driver) { - messages.add("Externally defined listener: Thee element was clicked"); - } - - @Override public void beforeChangeValueOf(WebElement element, WebDriver driver) { - 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 public void beforeGetText(WebElement element, WebDriver driver) { - messages.add("WebDriverEventListener: Attempt to get text of the element"); - } - - @Override public void afterGetText(WebElement element, WebDriver driver, String text) { - messages.add("WebDriverEventListener: Got the text of an element"); - } - - @Override protected void add() { - SingleListeners.listeners.put(ElementListener2.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/ExceptionListener.java b/src/test/java/io/appium/java_client/events/listeners/ExceptionListener.java deleted file mode 100644 index 837bcce1f..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/ExceptionListener.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.ListensToException; -import org.openqa.selenium.WebDriver; - -public class ExceptionListener extends TestListener implements ListensToException { - @Override public void onException(Throwable throwable, WebDriver driver) { - messages.add("The exception was thrown: " + throwable.getClass()); - } - - @Override protected void add() { - SingleListeners.listeners.put(ExceptionListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/ExceptionListener2.java b/src/test/java/io/appium/java_client/events/listeners/ExceptionListener2.java deleted file mode 100644 index 194cad08c..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/ExceptionListener2.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.ListensToException; -import org.openqa.selenium.WebDriver; - -public class ExceptionListener2 extends TestListener implements ListensToException { - @Override public void onException(Throwable throwable, WebDriver driver) { - messages.add("Externally defined listener: The exception was thrown: " + throwable.getClass()); - } - - @Override protected void add() { - SingleListeners.listeners.put(ExceptionListener2.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/JavaScriptListener.java b/src/test/java/io/appium/java_client/events/listeners/JavaScriptListener.java deleted file mode 100644 index 09b7bad6e..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/JavaScriptListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.JavaScriptEventListener; -import org.openqa.selenium.WebDriver; - -public class JavaScriptListener extends TestListener implements JavaScriptEventListener { - @Override public void beforeScript(String script, WebDriver driver) { - messages.add("Attempt to perform java script: " + script); - } - - @Override public void afterScript(String script, WebDriver driver) { - messages.add("Java script " + script + " was performed"); - } - - @Override protected void add() { - SingleListeners.listeners.put(JavaScriptListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/JavaScriptListener2.java b/src/test/java/io/appium/java_client/events/listeners/JavaScriptListener2.java deleted file mode 100644 index 2ec869751..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/JavaScriptListener2.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.JavaScriptEventListener; -import org.openqa.selenium.WebDriver; - -public class JavaScriptListener2 extends TestListener implements JavaScriptEventListener { - @Override public void beforeScript(String script, WebDriver driver) { - messages.add("Externally defined listener: Attempt to perform java script: " + script); - } - - @Override public void afterScript(String script, WebDriver driver) { - messages.add("Externally defined listener: Java script " + script + " was performed"); - } - - @Override protected void add() { - SingleListeners.listeners.put(JavaScriptListener2.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/NavigationListener.java b/src/test/java/io/appium/java_client/events/listeners/NavigationListener.java deleted file mode 100644 index ac9cd94f0..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/NavigationListener.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.NavigationEventListener; -import org.openqa.selenium.WebDriver; - -public class NavigationListener extends TestListener implements NavigationEventListener { - - @Override public void beforeNavigateTo(String url, WebDriver driver) { - messages.add("Attempt to navigate to " + url); - } - - @Override public void afterNavigateTo(String url, WebDriver driver) { - messages.add("Navigation to " + url + " was successful"); - } - - @Override public void beforeNavigateBack(WebDriver driver) { - messages.add("Attempt to navigate back"); - } - - @Override public void afterNavigateBack(WebDriver driver) { - messages.add("Navigation back was successful"); - } - - @Override public void beforeNavigateForward(WebDriver driver) { - messages.add("Attempt to navigate forward"); - } - - @Override public void afterNavigateForward(WebDriver driver) { - messages.add("Navigation forward was successful"); - } - - @Override public void beforeNavigateRefresh(WebDriver driver) { - messages.add("Attempt to refresh"); - } - - @Override public void afterNavigateRefresh(WebDriver driver) { - messages.add("The refreshing was successful"); - } - - @Override protected void add() { - SingleListeners.listeners.put(NavigationListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/NavigationListener2.java b/src/test/java/io/appium/java_client/events/listeners/NavigationListener2.java deleted file mode 100644 index 327f05bca..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/NavigationListener2.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.NavigationEventListener; -import org.openqa.selenium.WebDriver; - -public class NavigationListener2 extends TestListener implements NavigationEventListener { - - @Override public void beforeNavigateTo(String url, WebDriver driver) { - messages.add("Externally defined listener: Attempt to navigate to " + url); - } - - @Override public void afterNavigateTo(String url, WebDriver driver) { - messages.add("Externally defined listener: Navigation to " + url + " was successful"); - } - - @Override public void beforeNavigateBack(WebDriver driver) { - messages.add("Externally defined listener: Attempt to navigate back"); - } - - @Override public void afterNavigateBack(WebDriver driver) { - messages.add("Externally defined listener: Navigation back was successful"); - } - - @Override public void beforeNavigateForward(WebDriver driver) { - messages.add("Externally defined listener: Attempt to navigate forward"); - } - - @Override public void afterNavigateForward(WebDriver driver) { - messages.add("Externally defined listener: Navigation forward was successful"); - } - - @Override public void beforeNavigateRefresh(WebDriver driver) { - messages.add("Externally defined listener: Attempt to refresh"); - } - - @Override public void afterNavigateRefresh(WebDriver driver) { - messages.add("Externally defined listener: The refreshing was successful"); - } - - @Override protected void add() { - SingleListeners.listeners.put(NavigationListener2.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/RotationListener.java b/src/test/java/io/appium/java_client/events/listeners/RotationListener.java deleted file mode 100644 index e98d274cc..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/RotationListener.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.mobile.RotationEventListener; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.WebDriver; - -public class RotationListener extends TestListener implements RotationEventListener { - - @Override public void beforeRotation(WebDriver driver, ScreenOrientation orientation) { - messages.add("Attempt to change screen orientation. The new screen orientation is " - + orientation.toString()); - } - - @Override public void afterRotation(WebDriver driver, ScreenOrientation orientation) { - messages.add("The screen orientation has been changed to " - + orientation.toString()); - } - - @Override protected void add() { - SingleListeners.listeners.put(RotationListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/RotationListener2.java b/src/test/java/io/appium/java_client/events/listeners/RotationListener2.java deleted file mode 100644 index 9e7cd27ec..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/RotationListener2.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.mobile.RotationEventListener; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.WebDriver; - -public class RotationListener2 extends TestListener implements RotationEventListener { - - @Override public void beforeRotation(WebDriver driver, ScreenOrientation orientation) { - messages.add("Externally defined listener: Attempt to change screen orientation. " - + "The new screen orientation is " - + orientation.toString()); - } - - @Override public void afterRotation(WebDriver driver, ScreenOrientation orientation) { - messages.add("Externally defined listener: The screen orientation has been changed to " - + orientation.toString()); - } - - @Override protected void add() { - SingleListeners.listeners.put(RotationListener2.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/SearchingListener.java b/src/test/java/io/appium/java_client/events/listeners/SearchingListener.java deleted file mode 100644 index 22e46257a..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/SearchingListener.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.SearchingEventListener; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -public class SearchingListener extends TestListener implements SearchingEventListener { - - @Override public void beforeFindBy(By by, WebElement element, WebDriver driver) { - messages.add("Attempt to find something using " + by.toString() + ". The root element is " - + String.valueOf(element)); - } - - @Override public void afterFindBy(By by, WebElement element, WebDriver driver) { - messages.add("The searching for something using " + by.toString() + " has beed finished. " - + "The root element was " - + String.valueOf(element)); - } - - @Override protected void add() { - SingleListeners.listeners.put(SearchingListener.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/SearchingListener2.java b/src/test/java/io/appium/java_client/events/listeners/SearchingListener2.java deleted file mode 100644 index bc3459a4d..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/SearchingListener2.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.general.SearchingEventListener; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -public class SearchingListener2 extends TestListener implements SearchingEventListener { - - @Override public void beforeFindBy(By by, WebElement element, WebDriver driver) { - messages.add("Externally defined listener: Attempt to find something using " - + by.toString() + ". The root element is " - + String.valueOf(element)); - } - - @Override public void afterFindBy(By by, WebElement element, WebDriver driver) { - messages.add("Externally defined listener: The searching for something using " - + by.toString() + " has beed finished. " - + "The root element was " - + String.valueOf(element)); - } - - @Override protected void add() { - SingleListeners.listeners.put(SearchingListener2.class, this); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/SingleListeners.java b/src/test/java/io/appium/java_client/events/listeners/SingleListeners.java deleted file mode 100644 index a61f12e56..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/SingleListeners.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.Listener; - -import java.util.HashMap; -import java.util.Map; - -public class SingleListeners { - - public static final Map, TestListener> listeners = new HashMap<>(); - -} diff --git a/src/test/java/io/appium/java_client/events/listeners/TestListener.java b/src/test/java/io/appium/java_client/events/listeners/TestListener.java deleted file mode 100644 index 21c8e9419..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/TestListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.appium.java_client.events.listeners; - -import io.appium.java_client.events.api.Listener; - -import java.util.ArrayList; -import java.util.List; - -public abstract class TestListener implements Listener { - - public final List messages = new ArrayList<>(); - - public TestListener() { - add(); - } - - protected abstract void add(); -} diff --git a/src/test/java/io/appium/java_client/events/listeners/WindowListener.java b/src/test/java/io/appium/java_client/events/listeners/WindowListener.java deleted file mode 100644 index cf8c786c0..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/WindowListener.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.appium.java_client.events.listeners; - -import static java.lang.String.format; - -import io.appium.java_client.events.api.general.WindowEventListener; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebDriver; - -public class WindowListener extends TestListener implements WindowEventListener { - - @Override protected void add() { - SingleListeners.listeners.put(WindowListener.class, this); - } - - @Override public void beforeWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize) { - messages.add("Attempt to change size of the window. The height is " + targetSize.getHeight() - + " the width is " + targetSize.getWidth()); - } - - @Override public void afterWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize) { - messages.add("Size of the window has been changed. The height is " + targetSize.getHeight() - + " the width is " + targetSize.getWidth()); - } - - @Override - public void beforeWindowIsMoved(WebDriver driver, WebDriver.Window window, Point targetPoint) { - messages.add("Attempt to change position of the window. The X is " + targetPoint.getX() - + " the Y is " + targetPoint.getY()); - } - - @Override - public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point targetPoint) { - messages.add("The position the window has been changed. The X is " + targetPoint.getX() - + " the Y is " + targetPoint.getY()); - } - - @Override public void beforeWindowIsMaximized(WebDriver driver, WebDriver.Window window) { - messages.add("Attempt to maximize the window."); - } - - @Override public void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window) { - messages.add("The window has been maximized"); - } - - @Override - public void beforeSwitchToWindow(String windowName, WebDriver driver) { - messages.add(format("Attempt to switch to window %s", windowName)); - } - - @Override - public void afterSwitchToWindow(String windowName, WebDriver driver) { - messages.add(format("driver is switched to window %s", windowName)); - } -} diff --git a/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java b/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java deleted file mode 100644 index 60a912364..000000000 --- a/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.appium.java_client.events.listeners; - -import static java.lang.String.format; - -import io.appium.java_client.events.api.general.WindowEventListener; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebDriver; - -public class WindowListener2 extends TestListener implements WindowEventListener { - - @Override protected void add() { - SingleListeners.listeners.put(WindowListener2.class, this); - } - - @Override public void beforeWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize) { - messages.add("Externally defined listener: Attempt to change size of the window. " - + "The height is " + targetSize.getHeight() - + " the width is " + targetSize.getWidth()); - } - - @Override public void afterWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize) { - messages.add("Externally defined listener: Size of the window has " - + "been changed. The height is " + targetSize.getHeight() - + " the width is " + targetSize.getWidth()); - } - - @Override - public void beforeWindowIsMoved(WebDriver driver, WebDriver.Window window, Point targetPoint) { - messages.add("Externally defined listener: Attempt to change position of the window. " - + "The X is " + targetPoint.getX() - + " the Y is " + targetPoint.getY()); - } - - @Override - public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point targetPoint) { - messages.add("Externally defined listener: The position the window has been changed. " - + "The X is " + targetPoint.getX() - + " the Y is " + targetPoint.getY()); - } - - @Override public void beforeWindowIsMaximized(WebDriver driver, WebDriver.Window window) { - messages.add("Externally defined listener: Attempt to maximize the window."); - } - - @Override public void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window) { - messages.add("Externally defined listener: The window has been maximized"); - } - - @Override - public void beforeSwitchToWindow(String windowName, WebDriver driver) { - messages.add(format("Externally defined listener: Attempt to switch to window %s", windowName)); - } - - @Override - public void afterSwitchToWindow(String windowName, WebDriver driver) { - messages.add(format("Externally defined listener: driver is switched to window %s", windowName)); - } -} diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java new file mode 100644 index 000000000..ae2e0df64 --- /dev/null +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -0,0 +1,262 @@ +/* + * 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.events.stubs; + +import com.google.common.collect.ImmutableList; +import org.openqa.selenium.Alert; +import org.openqa.selenium.By; +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; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.Rotatable; +import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.WindowType; +import org.openqa.selenium.logging.Logs; +import org.openqa.selenium.remote.DesiredCapabilities; + +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class EmptyWebDriver implements WebDriver, ContextAware, Rotatable, + JavascriptExecutor, HasCapabilities, TakesScreenshot { + public EmptyWebDriver() { + } + + private static List createStubList() { + return ImmutableList.of(new StubWebElement(), new StubWebElement()); + } + + public WebDriver context(String name) { + return null; + } + + public Set getContextHandles() { + return null; + } + + public String getContext() { + return ""; + } + + public void rotate(ScreenOrientation orientation) { + } + + public void rotate(DeviceRotation rotation) { + } + + public ScreenOrientation getOrientation() { + return null; + } + + public DeviceRotation rotation() { + return null; + } + + public void get(String url) { + } + + public String getCurrentUrl() { + return null; + } + + public String getTitle() { + return null; + } + + public StubWebElement findElement(By by) { + return new StubWebElement(); + } + + public StubWebElement findElement(String by, String using) throws WebDriverException, NoSuchElementException { + return new StubWebElement(); + } + + public List findElements(By by) { + return createStubList(); + } + + public List findElements(String by, String using) throws WebDriverException { + return createStubList(); + } + + public String getPageSource() { + throw new WebDriverException(); + } + + public void close() { + } + + public void quit() { + } + + public Set getWindowHandles() { + return null; + } + + public String getWindowHandle() { + throw new WebDriverException(); + } + + public TargetLocator switchTo() { + return new EmptyWebDriver.StubTargetLocator(this); + } + + public Navigation navigate() { + return new EmptyWebDriver.StubNavigation(); + } + + public Options manage() { + return new EmptyWebDriver.StubOptions(); + } + + public Object executeScript(String script, Object... args) { + return null; + } + + public Object executeAsyncScript(String script, Object... args) { + return null; + } + + public Capabilities getCapabilities() { + Map map = new HashMap<>(); + map.put("0", ""); + map.put("1", ""); + return new DesiredCapabilities(map); + } + + public X getScreenshotAs(OutputType target) throws WebDriverException { + return target.convertFromPngBytes(new byte[]{1, 2}); + } + + private class StubNavigation implements Navigation { + private StubNavigation() { + } + + public void back() { + } + + public void forward() { + } + + public void to(String url) { + } + + public void to(URL url) { + } + + public void refresh() { + } + } + + private class StubOptions implements Options { + private StubOptions() { + } + + public void addCookie(Cookie cookie) { + } + + public void deleteCookieNamed(String name) { + } + + public void deleteCookie(Cookie cookie) { + } + + public void deleteAllCookies() { + } + + public Set getCookies() { + return null; + } + + public Cookie getCookieNamed(String name) { + return null; + } + + public Timeouts timeouts() { + return null; + } + + public ImeHandler ime() { + return null; + } + + public Window window() { + return new StubWindow(); + } + + public Logs logs() { + return null; + } + } + + private class StubTargetLocator implements TargetLocator { + private final WebDriver driver; + + StubTargetLocator(WebDriver driver) { + this.driver = driver; + } + + public WebDriver frame(int index) { + return this.driver; + } + + public WebDriver frame(String nameOrId) { + return this.driver; + } + + public WebDriver frame(WebElement frameElement) { + return this.driver; + } + + public WebDriver parentFrame() { + return this.driver; + } + + public WebDriver window(String nameOrHandle) { + return this.driver; + } + + @Override + public WebDriver newWindow(WindowType typeHint) { + return null; + } + + public WebDriver defaultContent() { + return this.driver; + } + + public WebElement activeElement() { + return new StubWebElement(); + } + + public Alert alert() { + return new StubAlert(); + } + } +} diff --git a/src/test/java/io/appium/java_client/events/stubs/StubAlert.java b/src/test/java/io/appium/java_client/events/stubs/StubAlert.java new file mode 100644 index 000000000..c89ec4bb7 --- /dev/null +++ b/src/test/java/io/appium/java_client/events/stubs/StubAlert.java @@ -0,0 +1,37 @@ +/* + * 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.events.stubs; + +import org.openqa.selenium.Alert; + +public class StubAlert implements Alert { + public StubAlert() { + } + + public void dismiss() { + } + + public void accept() { + } + + public String getText() { + return ""; + } + + public void sendKeys(String keysToSend) { + } +} diff --git a/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java b/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java new file mode 100644 index 000000000..4be313211 --- /dev/null +++ b/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java @@ -0,0 +1,106 @@ +/* + * 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.events.stubs; + +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.Point; +import org.openqa.selenium.Rectangle; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.WebElement; + +public class StubWebElement implements WebElement { + public StubWebElement() { + } + + private static List createStubSubElementList() { + return new ArrayList<>(ImmutableList.of(new StubWebElement(), new StubWebElement())); + } + + public void click() { + } + + public void submit() { + } + + public void sendKeys(CharSequence... keysToSend) { + } + + public void clear() { + } + + public String getTagName() { + return null; + } + + public String getAttribute(String name) { + return null; + } + + public boolean isSelected() { + return false; + } + + public boolean isEnabled() { + return false; + } + + public String getText() { + return null; + } + + public List findElements(By by) { + return createStubSubElementList(); + } + + public WebElement findElement(By by) { + return new StubWebElement(); + } + + public boolean isDisplayed() { + return false; + } + + public Point getLocation() { + return null; + } + + public Dimension getSize() { + return null; + } + + public Rectangle getRect() { + throw new WebDriverException(); + } + + public String getCssValue(String propertyName) { + return null; + } + + public X getScreenshotAs(OutputType target) throws WebDriverException { + return target.convertFromPngBytes(new byte[]{1, 2}); + } + + public String toString() { + return this.getClass().getCanonicalName(); + } +} + diff --git a/src/test/java/io/appium/java_client/events/stubs/StubWindow.java b/src/test/java/io/appium/java_client/events/stubs/StubWindow.java new file mode 100644 index 000000000..d0e0fb82d --- /dev/null +++ b/src/test/java/io/appium/java_client/events/stubs/StubWindow.java @@ -0,0 +1,50 @@ +/* + * 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.events.stubs; + +import org.openqa.selenium.Dimension; +import org.openqa.selenium.Point; +import org.openqa.selenium.WebDriver.Window; + +public class StubWindow implements Window { + public StubWindow() { + } + + public void setSize(Dimension targetSize) { + } + + public void setPosition(Point targetPosition) { + } + + public Dimension getSize() { + return null; + } + + public Point getPosition() { + return null; + } + + public void maximize() { + } + + @Override + public void minimize() { + } + + public void fullscreen() { + } +} From 1bccc81296567c956815045d71877d2808bb07d4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 24 Oct 2021 13:08:37 +0200 Subject: [PATCH 002/501] refactor: Implement driver-specific W3C option classes (#1540) --- .../java_client/android/AndroidOptions.java | 5 + .../android/options/UiAutomator2Options.java | 53 ++ .../io/appium/java_client/ios/IOSOptions.java | 5 + .../ios/options/XCUITestOptions.java | 53 ++ .../java_client/remote/MobileOptions.java | 494 +----------------- .../remote/options/BaseOptions.java | 273 ++++++++++ .../remote/options/CanSetCapability.java | 34 ++ .../remote/options/SupportsAppOption.java | 59 +++ .../options/SupportsAutoWebViewOption.java | 54 ++ .../SupportsClearSystemFilesOption.java | 55 ++ .../options/SupportsDeviceNameOption.java | 44 ++ ...upportsEnablePerformanceLoggingOption.java | 55 ++ .../options/SupportsLanguageOption.java | 45 ++ .../remote/options/SupportsLocaleOption.java | 45 ++ .../options/SupportsOrientationOption.java | 46 ++ .../options/SupportsOtherAppsOption.java | 46 ++ .../remote/options/SupportsUdidOption.java | 44 ++ .../java_client/remote/MobileOptionsTest.java | 3 +- 18 files changed, 941 insertions(+), 472 deletions(-) create mode 100644 src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java create mode 100644 src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java create mode 100644 src/main/java/io/appium/java_client/remote/options/BaseOptions.java create mode 100644 src/main/java/io/appium/java_client/remote/options/CanSetCapability.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java diff --git a/src/main/java/io/appium/java_client/android/AndroidOptions.java b/src/main/java/io/appium/java_client/android/AndroidOptions.java index 780f92cd4..3841ab62c 100644 --- a/src/main/java/io/appium/java_client/android/AndroidOptions.java +++ b/src/main/java/io/appium/java_client/android/AndroidOptions.java @@ -20,6 +20,11 @@ import io.appium.java_client.remote.MobilePlatform; import org.openqa.selenium.Capabilities; +/** + * Use the specific options class for your driver, + * for example UiAutomator2Options. + */ +@Deprecated public class AndroidOptions extends MobileOptions { public AndroidOptions() { setAndroidPlatformName(); diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java new file mode 100644 index 000000000..3514db845 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -0,0 +1,53 @@ +/* + * 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.options; + +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAppOption; +import io.appium.java_client.remote.options.SupportsAutoWebViewOption; +import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; +import io.appium.java_client.remote.options.SupportsDeviceNameOption; +import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsLanguageOption; +import io.appium.java_client.remote.options.SupportsLocaleOption; +import io.appium.java_client.remote.options.SupportsOrientationOption; +import io.appium.java_client.remote.options.SupportsOtherAppsOption; +import io.appium.java_client.remote.options.SupportsUdidOption; +import org.openqa.selenium.Capabilities; + +public class UiAutomator2Options extends BaseOptions implements + SupportsAppOption, SupportsAutoWebViewOption, + SupportsClearSystemFilesOption, SupportsDeviceNameOption, + SupportsEnablePerformanceLoggingOption, SupportsLanguageOption, + SupportsLocaleOption, SupportsOrientationOption, + SupportsOtherAppsOption, SupportsUdidOption { + public UiAutomator2Options() { + setCommonOptions(); + } + + public UiAutomator2Options(Capabilities source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setPlatformName(MobilePlatform.ANDROID); + setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2); + } +} diff --git a/src/main/java/io/appium/java_client/ios/IOSOptions.java b/src/main/java/io/appium/java_client/ios/IOSOptions.java index 9d4c82b6e..9cb847d1e 100644 --- a/src/main/java/io/appium/java_client/ios/IOSOptions.java +++ b/src/main/java/io/appium/java_client/ios/IOSOptions.java @@ -20,6 +20,11 @@ import io.appium.java_client.remote.MobilePlatform; import org.openqa.selenium.Capabilities; +/** + * Use the specific options class for your driver, + * for example XCUITestOptions. + */ +@Deprecated public class IOSOptions extends MobileOptions { public IOSOptions() { setIOSPlatformName(); diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java new file mode 100644 index 000000000..8c8143da1 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -0,0 +1,53 @@ +/* + * 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.options; + +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAppOption; +import io.appium.java_client.remote.options.SupportsAutoWebViewOption; +import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; +import io.appium.java_client.remote.options.SupportsDeviceNameOption; +import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsLanguageOption; +import io.appium.java_client.remote.options.SupportsLocaleOption; +import io.appium.java_client.remote.options.SupportsOrientationOption; +import io.appium.java_client.remote.options.SupportsOtherAppsOption; +import io.appium.java_client.remote.options.SupportsUdidOption; +import org.openqa.selenium.Capabilities; + +public class XCUITestOptions extends BaseOptions implements + SupportsAppOption, SupportsAutoWebViewOption, + SupportsClearSystemFilesOption, SupportsDeviceNameOption, + SupportsEnablePerformanceLoggingOption, SupportsLanguageOption, + SupportsLocaleOption, SupportsOrientationOption, + SupportsOtherAppsOption, SupportsUdidOption { + public XCUITestOptions() { + setCommonOptions(); + } + + public XCUITestOptions(Capabilities source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setPlatformName(MobilePlatform.IOS); + setAutomationName(AutomationName.IOS_XCUI_TEST); + } +} diff --git a/src/main/java/io/appium/java_client/remote/MobileOptions.java b/src/main/java/io/appium/java_client/remote/MobileOptions.java index bf8ea1f38..fad8d5ad1 100644 --- a/src/main/java/io/appium/java_client/remote/MobileOptions.java +++ b/src/main/java/io/appium/java_client/remote/MobileOptions.java @@ -16,16 +16,32 @@ package io.appium.java_client.remote; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAppOption; +import io.appium.java_client.remote.options.SupportsAutoWebViewOption; +import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; +import io.appium.java_client.remote.options.SupportsDeviceNameOption; +import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsLanguageOption; +import io.appium.java_client.remote.options.SupportsLocaleOption; +import io.appium.java_client.remote.options.SupportsOrientationOption; +import io.appium.java_client.remote.options.SupportsOtherAppsOption; +import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.Platform; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.remote.CapabilityType; -import java.net.URL; -import java.time.Duration; - -public class MobileOptions> extends MutableCapabilities { +/** + * Use the specific options class for your driver, + * for example XCUITestOptions or UiAutomator2Options. + * + * @param The child class for a proper chaining. + */ +@Deprecated +public class MobileOptions> extends BaseOptions + implements SupportsAppOption, SupportsAutoWebViewOption, + SupportsClearSystemFilesOption, SupportsDeviceNameOption, + SupportsEnablePerformanceLoggingOption, SupportsLanguageOption, + SupportsLocaleOption, SupportsOrientationOption, SupportsOtherAppsOption, + SupportsUdidOption { /** * Creates new instance with no preset capabilities. @@ -41,466 +57,4 @@ public MobileOptions() { public MobileOptions(Capabilities source) { super(source); } - - /** - * Set the kind of mobile device or emulator to use. - * - * @param platform the kind of mobile device or emulator to use. - * @return this MobileOptions, for chaining. - * @see org.openqa.selenium.remote.CapabilityType#PLATFORM_NAME - */ - public T setPlatformName(String platform) { - return amend(CapabilityType.PLATFORM_NAME, platform); - } - - /** - * Set the absolute local path for the location of the App. - * The or remote http URL to a {@code .ipa} file (IOS), - * - * @param path is a String representing the location of the App - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#APP - */ - public T setApp(String path) { - return amend(MobileCapabilityType.APP, path); - } - - /** - * Set the remote http URL for the location of the App. - * - * @param url is the URL representing the location of the App - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#APP - */ - public T setApp(URL url) { - return setApp(url.toString()); - } - - /** - * Get the app location. - * - * @return String representing app location - * @see MobileCapabilityType#APP - */ - public String getApp() { - return (String) getCapability(MobileCapabilityType.APP); - } - - /** - * Set the automation engine to use. - * - * @param name is the name of the automation engine - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTOMATION_NAME - */ - public T setAutomationName(String name) { - return amend(MobileCapabilityType.AUTOMATION_NAME, name); - } - - /** - * Get the automation engine to use. - * - * @return String representing the name of the automation engine - * @see MobileCapabilityType#AUTOMATION_NAME - */ - public String getAutomationName() { - return (String) getCapability(MobileCapabilityType.AUTOMATION_NAME); - } - - /** - * Set the app to move directly into Webview context. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTO_WEBVIEW - */ - public T setAutoWebview() { - return setAutoWebview(true); - } - - /** - * Set whether the app moves directly into Webview context. - * - * @param bool is whether the app moves directly into Webview context. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTO_WEBVIEW - */ - public T setAutoWebview(boolean bool) { - return amend(MobileCapabilityType.AUTO_WEBVIEW, bool); - } - - /** - * Get whether the app moves directly into Webview context. - * - * @return true if app moves directly into Webview context. - * @see MobileCapabilityType#AUTO_WEBVIEW - */ - public boolean doesAutoWebview() { - return (boolean) getCapability(MobileCapabilityType.AUTO_WEBVIEW); - } - - /** - * Set the app to delete any generated files at the end of a session. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES - */ - public T setClearSystemFiles() { - return setClearSystemFiles(true); - } - - /** - * Set whether the app deletes generated files at the end of a session. - * - * @param bool is whether the app deletes generated files at the end of a session. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES - */ - public T setClearSystemFiles(boolean bool) { - return amend(MobileCapabilityType.CLEAR_SYSTEM_FILES, bool); - } - - /** - * Get whether the app deletes generated files at the end of a session. - * - * @return true if the app deletes generated files at the end of a session. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES - */ - public boolean doesClearSystemFiles() { - return (boolean) getCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES); - } - - /** - * Set the name of the device. - * - * @param deviceName is the name of the device. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#DEVICE_NAME - */ - public T setDeviceName(String deviceName) { - return amend(MobileCapabilityType.DEVICE_NAME, deviceName); - } - - /** - * Get the name of the device. - * - * @return String representing the name of the device. - * @see MobileCapabilityType#DEVICE_NAME - */ - public String getDeviceName() { - return (String) getCapability(MobileCapabilityType.DEVICE_NAME); - } - - /** - * Set the app to enable performance logging. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING - */ - public T setEnablePerformanceLogging() { - return setEnablePerformanceLogging(true); - } - - /** - * Set whether the app logs performance. - * - * @param bool is whether the app logs performance. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING - */ - public T setEnablePerformanceLogging(boolean bool) { - return amend(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING, bool); - } - - /** - * Get the app logs performance. - * - * @return true if the app logs performance. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING - */ - public boolean isEnablePerformanceLogging() { - return (boolean) getCapability(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING); - } - - /** - * Set the app to report the timings for various Appium-internal events. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public T setEventTimings() { - return setEventTimings(true); - } - - /** - * Set whether the app reports the timings for various Appium-internal events. - * - * @param bool is whether the app enables event timings. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public T setEventTimings(boolean bool) { - return amend(MobileCapabilityType.EVENT_TIMINGS, bool); - } - - /** - * Get whether the app reports the timings for various Appium-internal events. - * - * @return true if the app reports event timings. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public boolean doesEventTimings() { - return (boolean) getCapability(MobileCapabilityType.EVENT_TIMINGS); - } - - /** - * Set the app to do a full reset. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#FULL_RESET - */ - public T setFullReset() { - return setFullReset(true); - } - - /** - * Set whether the app does a full reset. - * - * @param bool is whether the app does a full reset. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#FULL_RESET - */ - public T setFullReset(boolean bool) { - return amend(MobileCapabilityType.FULL_RESET, bool); - } - - /** - * Get whether the app does a full reset. - * - * @return true if the app does a full reset. - * @see MobileCapabilityType#FULL_RESET - */ - public boolean doesFullReset() { - return (boolean) getCapability(MobileCapabilityType.FULL_RESET); - } - - /** - * Set language abbreviation for use in session. - * - * @param language is the language abbreviation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#LANGUAGE - */ - public T setLanguage(String language) { - return amend(MobileCapabilityType.LANGUAGE, language); - } - - /** - * Get language abbreviation for use in session. - * - * @return String representing the language abbreviation. - * @see MobileCapabilityType#LANGUAGE - */ - public String getLanguage() { - return (String) getCapability(MobileCapabilityType.LANGUAGE); - } - - /** - * Set locale abbreviation for use in session. - * - * @param locale is the locale abbreviation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#LOCALE - */ - public T setLocale(String locale) { - return amend(MobileCapabilityType.LOCALE, locale); - } - - /** - * Get locale abbreviation for use in session. - * - * @return String representing the locale abbreviation. - * @see MobileCapabilityType#LOCALE - */ - public String getLocale() { - return (String) getCapability(MobileCapabilityType.LOCALE); - } - - /** - * Set the timeout for new commands. - * - * @param duration is the allowed time before seeing a new command. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT - */ - public T setNewCommandTimeout(Duration duration) { - return amend(MobileCapabilityType.NEW_COMMAND_TIMEOUT, duration.getSeconds()); - } - - /** - * Get the timeout for new commands. - * - * @return allowed time before seeing a new command. - * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT - */ - public Duration getNewCommandTimeout() { - Object duration = getCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT); - return Duration.ofSeconds(Long.parseLong("" + duration)); - } - - /** - * Set the app not to do a reset. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NO_RESET - */ - public T setNoReset() { - return setNoReset(true); - } - - /** - * Set whether the app does not do a reset. - * - * @param bool is whether the app does not do a reset. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NO_RESET - */ - public T setNoReset(boolean bool) { - return amend(MobileCapabilityType.NO_RESET, bool); - } - - /** - * Get whether the app does not do a reset. - * - * @return true if the app does not do a reset. - * @see MobileCapabilityType#NO_RESET - */ - public boolean doesNoReset() { - return (boolean) getCapability(MobileCapabilityType.NO_RESET); - } - - /** - * Set the orientation of the screen. - * - * @param orientation is the screen orientation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ORIENTATION - */ - public T setOrientation(ScreenOrientation orientation) { - return amend(MobileCapabilityType.ORIENTATION, orientation); - } - - /** - * Get the orientation of the screen. - * - * @return ScreenOrientation of the app. - * @see MobileCapabilityType#ORIENTATION - */ - public ScreenOrientation getOrientation() { - return (ScreenOrientation) getCapability(MobileCapabilityType.ORIENTATION); - } - - /** - * Set the location of the app(s) to install before running a test. - * - * @param apps is the apps to install. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#OTHER_APPS - */ - public T setOtherApps(String apps) { - return amend(MobileCapabilityType.OTHER_APPS, apps); - } - - /** - * Get the list of apps to install before running a test. - * - * @return String of apps to install. - * @see MobileCapabilityType#OTHER_APPS - */ - public String getOtherApps() { - return (String) getCapability(MobileCapabilityType.OTHER_APPS); - } - - /** - * Set the version of the platform. - * - * @param version is the platform version. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PLATFORM_VERSION - */ - public T setPlatformVersion(String version) { - return amend(MobileCapabilityType.PLATFORM_VERSION, version); - } - - /** - * Get the version of the platform. - * - * @return String representing the platform version. - * @see MobileCapabilityType#PLATFORM_VERSION - */ - public String getPlatformVersion() { - return (String) getCapability(MobileCapabilityType.PLATFORM_VERSION); - } - - /** - * Set the app to print page source when a find operation fails. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public T setPrintPageSourceOnFindFailure() { - return setPrintPageSourceOnFindFailure(true); - } - - /** - * Set whether the app to print page source when a find operation fails. - * - * @param bool is whether to print page source. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public T setPrintPageSourceOnFindFailure(boolean bool) { - return amend(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE, bool); - } - - /** - * Get whether the app to print page source when a find operation fails. - * - * @return true if app prints page source. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public boolean doesPrintPageSourceOnFindFailure() { - return (boolean) getCapability(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE); - } - - /** - * Set the id of the device. - * - * @param id is the unique device identifier. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#UDID - */ - public T setUdid(String id) { - return amend(MobileCapabilityType.UDID, id); - } - - /** - * Get the id of the device. - * - * @return String representing the unique device identifier. - * @see MobileCapabilityType#UDID - */ - public String getUdid() { - return (String) getCapability(MobileCapabilityType.UDID); - } - - @Override - public T merge(Capabilities extraCapabilities) { - super.merge(extraCapabilities); - return (T) this; - } - - protected T amend(String optionName, Object value) { - setCapability(optionName, value); - return (T) this; - } } diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java new file mode 100644 index 000000000..cdfb8f168 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -0,0 +1,273 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.remote.AcceptedW3CCapabilityKeys; +import org.openqa.selenium.remote.CapabilityType; + +import java.time.Duration; +import java.util.Map; +import java.util.stream.Collectors; + +import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; +import static java.util.Collections.unmodifiableMap; + +/** + * This class represents capabilities that are available in the base driver, + * e.g. are acceptable by any Appium driver + * + * @param The child class for a proper chaining. + */ +@SuppressWarnings("unused") +public class BaseOptions> extends MutableCapabilities + implements CanSetCapability { + private static final AcceptedW3CCapabilityKeys W3C_KEY_PATTERNS = + new AcceptedW3CCapabilityKeys(); + + + /** + * Creates new instance with no preset capabilities. + */ + public BaseOptions() { + } + + /** + * Creates new instance with provided capabilities. + * + * @param source is Capabilities instance to merge into new instance + */ + public BaseOptions(Capabilities source) { + super(source); + } + + /** + * Set the kind of mobile device or emulator to use. + * + * @param platform the kind of mobile device or emulator to use. + * @return this MobileOptions, for chaining. + * @see CapabilityType#PLATFORM_NAME + */ + public T setPlatformName(String platform) { + return amend(CapabilityType.PLATFORM_NAME, platform); + } + + /** + * Set the automation engine to use. + * + * @param name is the name of the automation engine + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#AUTOMATION_NAME + */ + public T setAutomationName(String name) { + return amend(MobileCapabilityType.AUTOMATION_NAME, name); + } + + /** + * Get the automation engine to use. + * + * @return String representing the name of the automation engine + * @see MobileCapabilityType#AUTOMATION_NAME + */ + public String getAutomationName() { + return (String) getCapability(MobileCapabilityType.AUTOMATION_NAME); + } + + /** + * Set the app to report the timings for various Appium-internal events. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#EVENT_TIMINGS + */ + public T setEventTimings() { + return setEventTimings(true); + } + + /** + * Set whether the app reports the timings for various Appium-internal events. + * + * @param bool is whether the app enables event timings. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#EVENT_TIMINGS + */ + public T setEventTimings(boolean bool) { + return amend(MobileCapabilityType.EVENT_TIMINGS, bool); + } + + /** + * Get whether the app reports the timings for various Appium-internal events. + * + * @return true if the app reports event timings. + * @see MobileCapabilityType#EVENT_TIMINGS + */ + public boolean doesEventTimings() { + return (boolean) getCapability(MobileCapabilityType.EVENT_TIMINGS); + } + + /** + * Set the app to do a full reset. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#FULL_RESET + */ + public T setFullReset() { + return setFullReset(true); + } + + /** + * Set whether the app does a full reset. + * + * @param bool is whether the app does a full reset. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#FULL_RESET + */ + public T setFullReset(boolean bool) { + return amend(MobileCapabilityType.FULL_RESET, bool); + } + + /** + * Get whether the app does a full reset. + * + * @return true if the app does a full reset. + * @see MobileCapabilityType#FULL_RESET + */ + public boolean doesFullReset() { + return (boolean) getCapability(MobileCapabilityType.FULL_RESET); + } + + /** + * Set the timeout for new commands. + * + * @param duration is the allowed time before seeing a new command. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT + */ + public T setNewCommandTimeout(Duration duration) { + return amend(MobileCapabilityType.NEW_COMMAND_TIMEOUT, duration.getSeconds()); + } + + /** + * Get the timeout for new commands. + * + * @return allowed time before seeing a new command. + * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT + */ + public Duration getNewCommandTimeout() { + Object duration = getCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT); + return Duration.ofSeconds(Long.parseLong("" + duration)); + } + + /** + * Set the app not to do a reset. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#NO_RESET + */ + public T setNoReset() { + return setNoReset(true); + } + + /** + * Set whether the app does not do a reset. + * + * @param bool is whether the app does not do a reset. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#NO_RESET + */ + public T setNoReset(boolean bool) { + return amend(MobileCapabilityType.NO_RESET, bool); + } + + /** + * Get whether the app does not do a reset. + * + * @return true if the app does not do a reset. + * @see MobileCapabilityType#NO_RESET + */ + public boolean doesNoReset() { + return (boolean) getCapability(MobileCapabilityType.NO_RESET); + } + + /** + * Set the version of the platform. + * + * @param version is the platform version. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#PLATFORM_VERSION + */ + public T setPlatformVersion(String version) { + return amend(MobileCapabilityType.PLATFORM_VERSION, version); + } + + /** + * Get the version of the platform. + * + * @return String representing the platform version. + * @see MobileCapabilityType#PLATFORM_VERSION + */ + public String getPlatformVersion() { + return (String) getCapability(MobileCapabilityType.PLATFORM_VERSION); + } + + /** + * Set the app to print page source when a find operation fails. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE + */ + public T setPrintPageSourceOnFindFailure() { + return setPrintPageSourceOnFindFailure(true); + } + + /** + * Set whether the app to print page source when a find operation fails. + * + * @param bool is whether to print page source. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE + */ + public T setPrintPageSourceOnFindFailure(boolean bool) { + return amend(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE, bool); + } + + /** + * Get whether the app to print page source when a find operation fails. + * + * @return true if app prints page source. + * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE + */ + public boolean doesPrintPageSourceOnFindFailure() { + return (boolean) getCapability(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE); + } + + @Override + public Map asMap() { + return unmodifiableMap(super.asMap().entrySet().stream() + .collect(Collectors.toMap(entry -> W3C_KEY_PATTERNS.test(entry.getKey()) + ? entry.getKey() : APPIUM_PREFIX + entry.getKey(), Map.Entry::getValue) + )); + } + + @Override + public T merge(Capabilities extraCapabilities) { + super.merge(extraCapabilities); + //noinspection unchecked + return (T) this; + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/CanSetCapability.java b/src/main/java/io/appium/java_client/remote/options/CanSetCapability.java new file mode 100644 index 000000000..c992569c6 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/CanSetCapability.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.remote.options; + +public interface CanSetCapability> { + void setCapability(String key, Object value); + + /** + * Set a custom option. + * + * @param optionName Option name. + * @param value Option value. + * @return self instance for chaining. + */ + default T amend(String optionName, Object value) { + setCapability(optionName, value); + //noinspection unchecked + return (T) this; + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java new file mode 100644 index 000000000..8e112a32f --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java @@ -0,0 +1,59 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +import java.net.URL; + +public interface SupportsAppOption> extends + Capabilities, CanSetCapability { + + /** + * Set the absolute local path for the location of the App. + * The or remote http URL to a {@code .ipa} file (IOS), + * + * @param path is a String representing the location of the App + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#APP + */ + default T setApp(String path) { + return amend(MobileCapabilityType.APP, path); + } + + /** + * Set the remote http URL for the location of the App. + * + * @param url is the URL representing the location of the App + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#APP + */ + default T setApp(URL url) { + return setApp(url.toString()); + } + + /** + * Get the app location. + * + * @return String representing app location + * @see MobileCapabilityType#APP + */ + default String getApp() { + return (String) getCapability(MobileCapabilityType.APP); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java new file mode 100644 index 000000000..8c68c20bf --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java @@ -0,0 +1,54 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsAutoWebViewOption> extends + Capabilities, CanSetCapability { + /** + * Set the app to move directly into Webview context. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#AUTO_WEBVIEW + */ + default T setAutoWebview() { + return setAutoWebview(true); + } + + /** + * Set whether the app moves directly into Webview context. + * + * @param bool is whether the app moves directly into Webview context. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#AUTO_WEBVIEW + */ + default T setAutoWebview(boolean bool) { + return amend(MobileCapabilityType.AUTO_WEBVIEW, bool); + } + + /** + * Get whether the app moves directly into Webview context. + * + * @return true if app moves directly into Webview context. + * @see MobileCapabilityType#AUTO_WEBVIEW + */ + default boolean doesAutoWebview() { + return (boolean) getCapability(MobileCapabilityType.AUTO_WEBVIEW); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java new file mode 100644 index 000000000..162956fc1 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java @@ -0,0 +1,55 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsClearSystemFilesOption> extends + Capabilities, CanSetCapability { + + /** + * Set the app to delete any generated files at the end of a session. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#CLEAR_SYSTEM_FILES + */ + default T setClearSystemFiles() { + return setClearSystemFiles(true); + } + + /** + * Set whether the app deletes generated files at the end of a session. + * + * @param bool is whether the app deletes generated files at the end of a session. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#CLEAR_SYSTEM_FILES + */ + default T setClearSystemFiles(boolean bool) { + return amend(MobileCapabilityType.CLEAR_SYSTEM_FILES, bool); + } + + /** + * Get whether the app deletes generated files at the end of a session. + * + * @return true if the app deletes generated files at the end of a session. + * @see MobileCapabilityType#CLEAR_SYSTEM_FILES + */ + default boolean doesClearSystemFiles() { + return (boolean) getCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java new file mode 100644 index 000000000..91f1a8c75 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java @@ -0,0 +1,44 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsDeviceNameOption> extends + Capabilities, CanSetCapability { + /** + * Set the name of the device. + * + * @param deviceName is the name of the device. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#DEVICE_NAME + */ + default T setDeviceName(String deviceName) { + return amend(MobileCapabilityType.DEVICE_NAME, deviceName); + } + + /** + * Get the name of the device. + * + * @return String representing the name of the device. + * @see MobileCapabilityType#DEVICE_NAME + */ + default String getDeviceName() { + return (String) getCapability(MobileCapabilityType.DEVICE_NAME); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java new file mode 100644 index 000000000..82ff44573 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java @@ -0,0 +1,55 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsEnablePerformanceLoggingOption> extends + Capabilities, CanSetCapability { + + /** + * Set the app to enable performance logging. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + */ + default T setEnablePerformanceLogging() { + return setEnablePerformanceLogging(true); + } + + /** + * Set whether the app logs performance. + * + * @param bool is whether the app logs performance. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + */ + default T setEnablePerformanceLogging(boolean bool) { + return amend(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING, bool); + } + + /** + * Get the app logs performance. + * + * @return true if the app logs performance. + * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + */ + default boolean isEnablePerformanceLogging() { + return (boolean) getCapability(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java new file mode 100644 index 000000000..12e46838e --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java @@ -0,0 +1,45 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsLanguageOption> extends + Capabilities, CanSetCapability { + + /** + * Set language abbreviation for use in session. + * + * @param language is the language abbreviation. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#LANGUAGE + */ + default T setLanguage(String language) { + return amend(MobileCapabilityType.LANGUAGE, language); + } + + /** + * Get language abbreviation for use in session. + * + * @return String representing the language abbreviation. + * @see MobileCapabilityType#LANGUAGE + */ + default String getLanguage() { + return (String) getCapability(MobileCapabilityType.LANGUAGE); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java new file mode 100644 index 000000000..f2f0d26e5 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java @@ -0,0 +1,45 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsLocaleOption> extends + Capabilities, CanSetCapability { + + /** + * Set locale abbreviation for use in session. + * + * @param locale is the locale abbreviation. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#LOCALE + */ + default T setLocale(String locale) { + return amend(MobileCapabilityType.LOCALE, locale); + } + + /** + * Get locale abbreviation for use in session. + * + * @return String representing the locale abbreviation. + * @see MobileCapabilityType#LOCALE + */ + default String getLocale() { + return (String) getCapability(MobileCapabilityType.LOCALE); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java new file mode 100644 index 000000000..4bc34bb59 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java @@ -0,0 +1,46 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.ScreenOrientation; + +public interface SupportsOrientationOption> extends + Capabilities, CanSetCapability { + + /** + * Set the orientation of the screen. + * + * @param orientation is the screen orientation. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#ORIENTATION + */ + default T setOrientation(ScreenOrientation orientation) { + return amend(MobileCapabilityType.ORIENTATION, orientation); + } + + /** + * Get the orientation of the screen. + * + * @return ScreenOrientation of the app. + * @see MobileCapabilityType#ORIENTATION + */ + default ScreenOrientation getOrientation() { + return (ScreenOrientation) getCapability(MobileCapabilityType.ORIENTATION); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java new file mode 100644 index 000000000..2de4c224f --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java @@ -0,0 +1,46 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsOtherAppsOption> extends + Capabilities, CanSetCapability { + + + /** + * Set the location of the app(s) to install before running a test. + * + * @param apps is the apps to install. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#OTHER_APPS + */ + default T setOtherApps(String apps) { + return amend(MobileCapabilityType.OTHER_APPS, apps); + } + + /** + * Get the list of apps to install before running a test. + * + * @return String of apps to install. + * @see MobileCapabilityType#OTHER_APPS + */ + default String getOtherApps() { + return (String) getCapability(MobileCapabilityType.OTHER_APPS); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java new file mode 100644 index 000000000..bc6e59b37 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java @@ -0,0 +1,44 @@ +/* + * 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.remote.options; + +import io.appium.java_client.remote.MobileCapabilityType; +import org.openqa.selenium.Capabilities; + +public interface SupportsUdidOption> extends + Capabilities, CanSetCapability { + /** + * Set the id of the device. + * + * @param id is the unique device identifier. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#UDID + */ + default T setUdid(String id) { + return amend(MobileCapabilityType.UDID, id); + } + + /** + * Get the id of the device. + * + * @return String representing the unique device identifier. + * @see MobileCapabilityType#UDID + */ + default String getUdid() { + return (String) getCapability(MobileCapabilityType.UDID); + } +} diff --git a/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java b/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java index 27e1a6765..ab2b776e1 100644 --- a/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java +++ b/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java @@ -23,12 +23,11 @@ import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; -import java.util.ArrayList; import static org.junit.Assert.*; public class MobileOptionsTest { - private MobileOptions mobileOptions = new MobileOptions<>(); + private MobileOptions mobileOptions = new MobileOptions<>(); @Test public void acceptsExistingCapabilities() { From 8b6bdd66bd8692f99fce583533dcd5ee07ddb139 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 25 Oct 2021 10:28:23 +0200 Subject: [PATCH 003/501] chore: Start adding UiAutomator2 options (#1543) --- .../android/options/UiAutomator2Options.java | 76 ++- .../app/SupportsAllowTestPackagesOption.java | 61 +++ .../SupportsAndroidInstallTimeoutOption.java | 54 ++ .../app/SupportsAppActivityOption.java | 48 ++ .../app/SupportsAppDurationOption.java | 51 ++ .../options/app/SupportsAppPackageOption.java | 48 ++ .../app/SupportsAppWaitActivityOption.java | 49 ++ .../app/SupportsAppWaitForLaunchOption.java | 52 ++ .../app/SupportsAppWaitPackageOption.java | 49 ++ .../SupportsAutoGrantPermissionsOption.java | 62 +++ .../app/SupportsEnforceAppInstallOption.java | 61 +++ .../app/SupportsIntentActionOption.java | 49 ++ .../app/SupportsIntentCategoryOption.java | 49 ++ .../app/SupportsIntentFlagsOption.java | 49 ++ ...SupportsOptionalIntentArgumentsOption.java | 49 ++ .../SupportsRemoteAppsCacheLimitOption.java | 53 ++ .../SupportsUninstallOtherPackagesOption.java | 48 ++ .../SupportsDisableWindowAnimationOption.java | 60 +++ ...upportsSkipDeviceInitializationOption.java | 60 +++ .../SupportsSkipServerInstallationOption.java | 71 +++ .../server/SupportsSystemPortOption.java | 52 ++ ...iautomator2ServerInstallTimeoutOption.java | 53 ++ ...Uiautomator2ServerLaunchTimeoutOption.java | 53 ++ ...tsUiautomator2ServerReadTimeoutOption.java | 55 ++ .../internal/CapabilityHelpers.java | 83 ++- .../java_client/remote/MobileOptions.java | 486 +++++++++++++++++- .../remote/options/BaseOptions.java | 221 +------- .../remote/options/SupportsAppOption.java | 19 +- .../options/SupportsAutoWebViewOption.java | 22 +- .../options/SupportsAutomationNameOption.java | 45 ++ .../SupportsClearSystemFilesOption.java | 17 +- .../options/SupportsDeviceNameOption.java | 13 +- ...upportsEnablePerformanceLoggingOption.java | 21 +- .../options/SupportsEventTimingsOption.java | 56 ++ .../options/SupportsFullResetOption.java | 56 ++ .../options/SupportsLanguageOption.java | 12 +- .../remote/options/SupportsLocaleOption.java | 14 +- .../SupportsNewCommandTimeoutOption.java | 50 ++ .../remote/options/SupportsNoResetOption.java | 56 ++ .../options/SupportsOrientationOption.java | 18 +- .../options/SupportsOtherAppsOption.java | 15 +- .../SupportsPlatformVersionOption.java | 45 ++ ...rtsPrintPageSourceOnFindFailureOption.java | 58 +++ .../remote/options/SupportsUdidOption.java | 15 +- 44 files changed, 2336 insertions(+), 298 deletions(-) create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAllowTestPackagesOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAppActivityOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAppPackageOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitActivityOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitForLaunchOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitPackageOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsIntentActionOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsIntentCategoryOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsIntentFlagsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsOptionalIntentArgumentsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsRemoteAppsCacheLimitOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsUninstallOtherPackagesOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsDisableWindowAnimationOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsSkipDeviceInitializationOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerInstallTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerLaunchTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerReadTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsAutomationNameOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsFullResetOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsNewCommandTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsNoResetOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsPlatformVersionOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsPrintPageSourceOnFindFailureOption.java diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index 3514db845..c228e917f 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -16,6 +16,29 @@ package io.appium.java_client.android.options; +import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption; +import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption; +import io.appium.java_client.android.options.app.SupportsAppActivityOption; +import io.appium.java_client.android.options.app.SupportsAppDurationOption; +import io.appium.java_client.android.options.app.SupportsAppPackageOption; +import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption; +import io.appium.java_client.android.options.app.SupportsAppWaitForLaunchOption; +import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption; +import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption; +import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption; +import io.appium.java_client.android.options.app.SupportsIntentActionOption; +import io.appium.java_client.android.options.app.SupportsIntentCategoryOption; +import io.appium.java_client.android.options.app.SupportsIntentFlagsOption; +import io.appium.java_client.android.options.app.SupportsOptionalIntentArgumentsOption; +import io.appium.java_client.android.options.app.SupportsRemoteAppsCacheLimitOption; +import io.appium.java_client.android.options.app.SupportsUninstallOtherPackagesOption; +import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption; +import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption; +import io.appium.java_client.android.options.server.SupportsSkipServerInstallationOption; +import io.appium.java_client.android.options.server.SupportsSystemPortOption; +import io.appium.java_client.android.options.server.SupportsUiautomator2ServerInstallTimeoutOption; +import io.appium.java_client.android.options.server.SupportsUiautomator2ServerLaunchTimeoutOption; +import io.appium.java_client.android.options.server.SupportsUiautomator2ServerReadTimeoutOption; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; @@ -31,12 +54,55 @@ import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; +/** + * https://github.com/appium/appium-uiautomator2-driver#capabilities + */ public class UiAutomator2Options extends BaseOptions implements - SupportsAppOption, SupportsAutoWebViewOption, - SupportsClearSystemFilesOption, SupportsDeviceNameOption, - SupportsEnablePerformanceLoggingOption, SupportsLanguageOption, - SupportsLocaleOption, SupportsOrientationOption, - SupportsOtherAppsOption, SupportsUdidOption { + // TODO: ADB options: https://github.com/appium/appium-uiautomator2-driver#adb + // TODO: AVD options: https://github.com/appium/appium-uiautomator2-driver#emulator-android-virtual-device + // TODO: App signing options: https://github.com/appium/appium-uiautomator2-driver#app-signing + // TODO: Device locking options: https://github.com/appium/appium-uiautomator2-driver#device-locking + // TODO: MJPEG options: https://github.com/appium/appium-uiautomator2-driver#mjpeg + // TODO: Web Context options: https://github.com/appium/appium-uiautomator2-driver#web-context + // TODO: Other options: https://github.com/appium/appium-uiautomator2-driver#other + // TODO: Shared options + SupportsAutoWebViewOption, + // General options: https://github.com/appium/appium-uiautomator2-driver#general + SupportsDeviceNameOption, + SupportsUdidOption, + // Driver/Server options: https://github.com/appium/appium-uiautomator2-driver#driverserver + SupportsSystemPortOption, + SupportsSkipServerInstallationOption, + SupportsUiautomator2ServerLaunchTimeoutOption, + SupportsUiautomator2ServerInstallTimeoutOption, + SupportsUiautomator2ServerReadTimeoutOption, + SupportsDisableWindowAnimationOption, + SupportsSkipDeviceInitializationOption, + SupportsOrientationOption, + SupportsClearSystemFilesOption, + SupportsEnablePerformanceLoggingOption, + // App options: https://github.com/appium/appium-uiautomator2-driver#app + SupportsAppOption, + SupportsAppPackageOption, + SupportsAppActivityOption, + SupportsAppWaitActivityOption, + SupportsAppWaitPackageOption, + SupportsAppDurationOption, + SupportsAndroidInstallTimeoutOption, + SupportsAppWaitForLaunchOption, + SupportsIntentCategoryOption, + SupportsIntentActionOption, + SupportsIntentFlagsOption, + SupportsOptionalIntentArgumentsOption, + SupportsAutoGrantPermissionsOption, + SupportsOtherAppsOption, + SupportsUninstallOtherPackagesOption, + SupportsAllowTestPackagesOption, + SupportsRemoteAppsCacheLimitOption, + SupportsEnforceAppInstallOption, + // TODO: App localization options: https://github.com/appium/appium-uiautomator2-driver#app-localization + SupportsLanguageOption, + SupportsLocaleOption { public UiAutomator2Options() { setCommonOptions(); } diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAllowTestPackagesOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAllowTestPackagesOption.java new file mode 100644 index 000000000..2926aa932 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAllowTestPackagesOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAllowTestPackagesOption> extends + Capabilities, CanSetCapability { + String ALLOW_TEST_PACKAGES_OPTION = "allowTestPackages"; + + /** + * Enables usage of packages built with the test flag for + * the automated testing (literally adds -t flag to the adb install command). + * + * @return self instance for chaining. + */ + default T allowTestPackages() { + return amend(ALLOW_TEST_PACKAGES_OPTION, true); + } + + /** + * If set to true then it would be possible to use packages built with the test flag for + * the automated testing (literally adds -t flag to the adb install command). false by default. + * + * @param value True to allow test packages installation. + * @return self instance for chaining. + */ + default T setAllowTestPackages(boolean value) { + return amend(ALLOW_TEST_PACKAGES_OPTION, value); + } + + /** + * Get whether it is possible to use packages built with the test flag for + * the automated testing (literally adds -t flag to the adb install command). + * + * @return True or false. + */ + default Optional doesAllowTestPackages() { + return Optional.ofNullable(toSafeBoolean(getCapability(ALLOW_TEST_PACKAGES_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java new file mode 100644 index 000000000..40a588c2e --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java @@ -0,0 +1,54 @@ +/* + * 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.options.app; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsAndroidInstallTimeoutOption> extends + Capabilities, CanSetCapability { + String ANDROID_INSTALL_TIMEOUT_OPTION = "androidInstallTimeout"; + + /** + * Maximum amount of time to wait until the application under test is installed. + * 90000 ms by default + * + * @param installTimeout App install timeout. + * @return self instance for chaining. + */ + default T setAndroidInstallTimeout(Duration installTimeout) { + return amend(ANDROID_INSTALL_TIMEOUT_OPTION, installTimeout.toMillis()); + } + + /** + * Get maximum amount of time to wait until the application under test is installed. + * + * @return Timeout value. + */ + default Optional getAndroidInstallTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(ANDROID_INSTALL_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppActivityOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppActivityOption.java new file mode 100644 index 000000000..6e1e544bd --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppActivityOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppActivityOption> extends + Capabilities, CanSetCapability { + String APP_ACTIVITY_OPTION = "appActivity"; + + /** + * Main application activity identifier. If not provided then UiAutomator2 + * will try to detect it automatically from the package provided by the app capability. + * + * @param appActivity Fully qualified app activity class name. + * @return self instance for chaining. + */ + default T setAppActivity(String appActivity) { + return amend(APP_ACTIVITY_OPTION, appActivity); + } + + /** + * Get the name of the main app activity. + * + * @return Activity class name. + */ + default Optional getAppActivity() { + return Optional.ofNullable((String) getCapability(APP_ACTIVITY_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java new file mode 100644 index 000000000..3a3bce7b7 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsAppDurationOption> extends + Capabilities, CanSetCapability { + String APP_WAIT_DURATION_OPTION = "appWaitDuration"; + + /** + * Maximum amount of time to wait until the application under test is started + * (e.g. an activity returns the control to the caller). 20000 ms by default. + * + * @param appWaitDuration Package identifier to wait for. + * @return self instance for chaining. + */ + default T setAppWaitDuration(Duration appWaitDuration) { + return amend(APP_WAIT_DURATION_OPTION, appWaitDuration.toMillis()); + } + + /** + * Get the identifier of the app package to wait for. + * + * @return Package identifier. + */ + default Optional getAppWaitDuration() { + return Optional.ofNullable(toDuration(getCapability(APP_WAIT_DURATION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppPackageOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppPackageOption.java new file mode 100644 index 000000000..a82cc5dfe --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppPackageOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppPackageOption> extends + Capabilities, CanSetCapability { + String APP_PACKAGE_OPTION = "appPackage"; + + /** + * Application package identifier to be started. If not provided then UiAutomator2 will + * try to detect it automatically from the package provided by the app capability. + * + * @param appPackage App package identifier. + * @return self instance for chaining. + */ + default T setAppPackage(String appPackage) { + return amend(APP_PACKAGE_OPTION, appPackage); + } + + /** + * Get the app package identifier. + * + * @return Identifier value. + */ + default Optional getAppPackage() { + return Optional.ofNullable((String) getCapability(APP_PACKAGE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitActivityOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitActivityOption.java new file mode 100644 index 000000000..5567fbb1e --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitActivityOption.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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppWaitActivityOption> extends + Capabilities, CanSetCapability { + String APP_WAIT_ACTIVITY_OPTION = "appWaitActivity"; + + /** + * Identifier of the activity that the driver should wait for + * (not necessarily the main one). + * If not provided then defaults to appium:appActivity. + * + * @param appWaitActivity Fully qualified app activity class name. + * @return self instance for chaining. + */ + default T setAppWaitActivity(String appWaitActivity) { + return amend(APP_WAIT_ACTIVITY_OPTION, appWaitActivity); + } + + /** + * Get the name of the app activity to wait for. + * + * @return Activity class name. + */ + default Optional getAppWaitActivity() { + return Optional.ofNullable((String) getCapability(APP_WAIT_ACTIVITY_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitForLaunchOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitForLaunchOption.java new file mode 100644 index 000000000..70e440b54 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitForLaunchOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAppWaitForLaunchOption> extends + Capabilities, CanSetCapability { + String APP_WAIT_FOR_LAUNCH_OPTION = "appWaitForLaunch"; + + /** + * Whether to block until the app under test returns the control to the + * caller after its activity has been started by Activity Manager + * (true, the default value) or to continue the test without waiting for that (false). + * + * @param value Set to false if you don't want to wait for the app to finish its launch. + * @return self instance for chaining. + */ + default T setAppWaitForLaunch(boolean value) { + return amend(APP_WAIT_FOR_LAUNCH_OPTION, value); + } + + /** + * Get whether to block until the app under test returns the control to the + * caller after its activity has been started by Activity Manager. + * + * @return True if the driver should block or false otherwise. + */ + default Optional doesAppWaitForLaunch() { + return Optional.ofNullable(toSafeBoolean(getCapability(APP_WAIT_FOR_LAUNCH_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitPackageOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitPackageOption.java new file mode 100644 index 000000000..6089d9bcf --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitPackageOption.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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppWaitPackageOption> extends + Capabilities, CanSetCapability { + String APP_WAIT_PACKAGE_OPTION = "appWaitPackage"; + + /** + * Identifier of the package that the driver should wait for + * (not necessarily the main one). + * If not provided then defaults to appium:appPackage. + * + * @param appWaitPackage Package identifier to wait for. + * @return self instance for chaining. + */ + default T setAppWaitPackage(String appWaitPackage) { + return amend(APP_WAIT_PACKAGE_OPTION, appWaitPackage); + } + + /** + * Get the identifier of the app package to wait for. + * + * @return Package identifier. + */ + default Optional getAppWaitPackage() { + return Optional.ofNullable((String) getCapability(APP_WAIT_PACKAGE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java new file mode 100644 index 000000000..97402c867 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAutoGrantPermissionsOption> extends + Capabilities, CanSetCapability { + String AUTO_GRANT_PERMISSIONS_OPTION = "autoGrantPermissions"; + + /** + * Enables granting of all the requested application permissions + * automatically when a test starts. + * + * @return self instance for chaining. + */ + default T setAutoGrantPermissions() { + return amend(AUTO_GRANT_PERMISSIONS_OPTION, true); + } + + + /** + * Whether to grant all the requested application permissions + * automatically when a test starts(true). false by default. + * + * @param value Whether to enable or disable automatic permissions granting. + * @return self instance for chaining. + */ + default T setAutoGrantPermissions(boolean value) { + return amend(AUTO_GRANT_PERMISSIONS_OPTION, value); + } + + /** + * Get whether to grant all the requested application permissions + * automatically when a test starts. + * + * @return True if the permissions should be granted. + */ + default Optional doesAutoGrantPermissions() { + return Optional.ofNullable(toSafeBoolean(getCapability(AUTO_GRANT_PERMISSIONS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java new file mode 100644 index 000000000..3acc25875 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsEnforceAppInstallOption> extends + Capabilities, CanSetCapability { + String ENFORCE_APP_INSTALL_OPTION = "enforceAppInstall"; + + /** + * Sets the application under test is always reinstalled even if a newer version + * of it already exists on the device under test. + * + * @return self instance for chaining. + */ + default T enforceAppInstall() { + return amend(ENFORCE_APP_INSTALL_OPTION, true); + } + + /** + * Allows setting whether the application under test is always reinstalled even + * if a newer version of it already exists on the device under test. false by default. + * + * @param value True to allow test packages installation. + * @return self instance for chaining. + */ + default T setEnforceAppInstall(boolean value) { + return amend(ENFORCE_APP_INSTALL_OPTION, value); + } + + /** + * Get whether the application under test is always reinstalled even + * if a newer version of it already exists on the device under test. + * + * @return True or false. + */ + default Optional doesEnforceAppInstall() { + return Optional.ofNullable(toSafeBoolean(getCapability(ENFORCE_APP_INSTALL_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsIntentActionOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentActionOption.java new file mode 100644 index 000000000..7fc2afe89 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentActionOption.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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsIntentActionOption> extends + Capabilities, CanSetCapability { + String INTENT_ACTION_OPTION = "intentAction"; + + /** + * Set an optional intent action to be applied when + * starting the given appActivity by Activity Manager. + * + * @param intentAction Intent action class name. + * @return self instance for chaining. + */ + default T setIntentAction(String intentAction) { + return amend(INTENT_ACTION_OPTION, intentAction); + } + + /** + * Get intent action to be applied when + * starting the given appActivity by Activity Manager. + * + * @return Intent action class name. + */ + default Optional getIntentAction() { + return Optional.ofNullable((String) getCapability(INTENT_ACTION_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsIntentCategoryOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentCategoryOption.java new file mode 100644 index 000000000..287ac09d4 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentCategoryOption.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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsIntentCategoryOption> extends + Capabilities, CanSetCapability { + String INTENT_CATEGORY_OPTION = "intentCategory"; + + /** + * Set an optional intent category to be applied when + * starting the given appActivity by Activity Manager. + * + * @param intentCategory Intent category class name. + * @return self instance for chaining. + */ + default T setIntentCategory(String intentCategory) { + return amend(INTENT_CATEGORY_OPTION, intentCategory); + } + + /** + * Get intent category to be applied when + * starting the given appActivity by Activity Manager. + * + * @return Intent category class name. + */ + default Optional getIntentCategory() { + return Optional.ofNullable((String) getCapability(INTENT_CATEGORY_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsIntentFlagsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentFlagsOption.java new file mode 100644 index 000000000..6c9ed08a8 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentFlagsOption.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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsIntentFlagsOption> extends + Capabilities, CanSetCapability { + String INTENT_FLAGS_OPTION = "intentFlags"; + + /** + * Set an optional intent flags to be applied when + * starting the given appActivity by Activity Manager. + * + * @param intentFlags Intent flags hexadecimal string. + * @return self instance for chaining. + */ + default T setIntentFlags(String intentFlags) { + return amend(INTENT_FLAGS_OPTION, intentFlags); + } + + /** + * Get intent flags to be applied when + * starting the given appActivity by Activity Manager. + * + * @return Intent flags string. + */ + default Optional getIntentFlags() { + return Optional.ofNullable((String) getCapability(INTENT_FLAGS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsOptionalIntentArgumentsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsOptionalIntentArgumentsOption.java new file mode 100644 index 000000000..da5d5a3c7 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsOptionalIntentArgumentsOption.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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsOptionalIntentArgumentsOption> extends + Capabilities, CanSetCapability { + String OPTIONAL_INTENT_ARGUMENTS_OPTION = "optionalIntentArguments"; + + /** + * Set an optional intent arguments to be applied when + * starting the given appActivity by Activity Manager. + * + * @param arguments Intent arguments string. + * @return self instance for chaining. + */ + default T setOptionalIntentArguments(String arguments) { + return amend(OPTIONAL_INTENT_ARGUMENTS_OPTION, arguments); + } + + /** + * Get intent arguments to be applied when + * starting the given appActivity by Activity Manager. + * + * @return Intent arguments string. + */ + default Optional getOptionalIntentArguments() { + return Optional.ofNullable((String) getCapability(OPTIONAL_INTENT_ARGUMENTS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsRemoteAppsCacheLimitOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsRemoteAppsCacheLimitOption.java new file mode 100644 index 000000000..e44e8fcf4 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsRemoteAppsCacheLimitOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsRemoteAppsCacheLimitOption> extends + Capabilities, CanSetCapability { + String REMOTE_APPS_CACHE_LIMIT_OPTION = "remoteAppsCacheLimit"; + + /** + * Sets the maximum amount of application packages to be cached on the device under test. + * This is needed for devices that don't support streamed installs (Android 7 and below), + * because ADB must push app packages to the device first in order to install them, + * which takes some time. Setting this capability to zero disables apps caching. + * 10 by default. + * + * @param limit The maximum amount of cached apps. + * @return self instance for chaining. + */ + default T setRemoteAppsCacheLimit(int limit) { + return amend(REMOTE_APPS_CACHE_LIMIT_OPTION, limit); + } + + /** + * Get the maximum amount of apps that could be cached on the remote device. + * + * @return The maximum amount of cached apps. + */ + default Optional getRemoteAppsCacheLimit() { + return Optional.ofNullable(toInteger(getCapability(REMOTE_APPS_CACHE_LIMIT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsUninstallOtherPackagesOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsUninstallOtherPackagesOption.java new file mode 100644 index 000000000..fb1402d79 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsUninstallOtherPackagesOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsUninstallOtherPackagesOption> extends + Capabilities, CanSetCapability { + String UNINSTALL_OTHER_PACKAGES_OPTION = "uninstallOtherPackages"; + + /** + * Allows to set one or more comma-separated package + * identifiers to be uninstalled from the device before a test starts. + * + * @param packages one or more comma-separated package identifiers to uninstall. + * @return self instance for chaining. + */ + default T setUninstallOtherPackages(String packages) { + return amend(UNINSTALL_OTHER_PACKAGES_OPTION, packages); + } + + /** + * Get identifiers of packages to be uninstalled from the device before a test starts. + * + * @return Comma-separated package identifiers. + */ + default Optional getUninstallOtherPackages() { + return Optional.ofNullable((String) getCapability(UNINSTALL_OTHER_PACKAGES_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsDisableWindowAnimationOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsDisableWindowAnimationOption.java new file mode 100644 index 000000000..c8acbaac9 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsDisableWindowAnimationOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsDisableWindowAnimationOption> extends + Capabilities, CanSetCapability { + String DISABLE_WINDOWS_ANIMATION_OPTION = "disableWindowAnimation"; + + /** + * Disables window animations when starting the instrumentation process. + * + * @return self instance for chaining. + */ + default T disableWindowAnimation() { + return amend(DISABLE_WINDOWS_ANIMATION_OPTION, true); + } + + /** + * Set whether to disable window animations when starting the instrumentation process. + * false by default + * + * @param value True to disable window animations. + * @return self instance for chaining. + */ + default T setDisableWindowAnimation(boolean value) { + return amend(DISABLE_WINDOWS_ANIMATION_OPTION, value); + } + + /** + * Get whether window animations when starting the instrumentation process + * are disabled. + * + * @return True or false. + */ + default Optional doesDisableWindowAnimation() { + return Optional.ofNullable(toSafeBoolean(getCapability(DISABLE_WINDOWS_ANIMATION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsSkipDeviceInitializationOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsSkipDeviceInitializationOption.java new file mode 100644 index 000000000..2b42327bb --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsSkipDeviceInitializationOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSkipDeviceInitializationOption> extends + Capabilities, CanSetCapability { + String SKIP_DEVICE_INITIALIZATION_OPTION = "skipDeviceInitialization"; + + /** + * Disables initial device startup checks by the server. + * + * @return self instance for chaining. + */ + default T skipDeviceInitialization() { + return amend(SKIP_DEVICE_INITIALIZATION_OPTION, true); + } + + /** + * If set to true then device startup checks (whether it is ready and whether + * Settings app is installed) will be canceled on session creation. + * Could speed up the session creation if you know what you are doing. false by default + * + * @param value True to skip device initialization. + * @return self instance for chaining. + */ + default T setSkipDeviceInitialization(boolean value) { + return amend(SKIP_DEVICE_INITIALIZATION_OPTION, value); + } + + /** + * Get whether initial device startup checks by the server are disabled. + * + * @return True or false. + */ + default Optional doesSkipDeviceInitialization() { + return Optional.ofNullable(toSafeBoolean(getCapability(SKIP_DEVICE_INITIALIZATION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java new file mode 100644 index 000000000..088f040fc --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java @@ -0,0 +1,71 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSkipServerInstallationOption> extends + Capabilities, CanSetCapability { + String SKIP_SERVER_INSTALLATION_OPTION = "skipServerInstallation"; + + /** + * Enables skipping of the UiAutomator2 Server component installation + * on the device under test and all the related checks. + * This could help to speed up the session startup if you know for sure the + * correct server version is installed on the device. + * In case the server is not installed or an incorrect version of it is installed + * then you may get an unexpected error later. + * + * @return self instance for chaining. + */ + default T skipServerInstallation() { + return amend(SKIP_SERVER_INSTALLATION_OPTION, true); + } + + /** + * Set whether to skip the UiAutomator2 Server component installation + * on the device under test and all the related checks. + * This could help to speed up the session startup if you know for sure the + * correct server version is installed on the device. + * In case the server is not installed or an incorrect version of it is installed + * then you may get an unexpected error later. + * + * @param value True to skip the server installation. + * @return self instance for chaining. + */ + default T setSkipServerInstallation(boolean value) { + return amend(SKIP_SERVER_INSTALLATION_OPTION, value); + } + + /** + * Get whether to skip the UiAutomator2 Server component installation + * on the device under test and all the related checks. + * + * @return True or false. + */ + default Optional doesSkipServerInstallation() { + return Optional.ofNullable( + toSafeBoolean(getCapability(SKIP_SERVER_INSTALLATION_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java new file mode 100644 index 000000000..cf638ff9f --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsSystemPortOption> extends + Capabilities, CanSetCapability { + String SYSTEM_PORT_OPTION = "systemPort"; + + /** + * The number of the port the UiAutomator2 server is listening on. + * By default, the first free port from 8200..8299 range is selected. + * It is recommended to set this value if you are running parallel + * tests on the same machine. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setSystemPort(int port) { + return amend(SYSTEM_PORT_OPTION, port); + } + + /** + * Get the system port value. + * + * @return System port value + */ + default Optional getSystemPort() { + return Optional.ofNullable(toInteger(getCapability(SYSTEM_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerInstallTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerInstallTimeoutOption.java new file mode 100644 index 000000000..dac3b3b38 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerInstallTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsUiautomator2ServerInstallTimeoutOption> extends + Capabilities, CanSetCapability { + String UIAUTOMATOR2_SERVER_INSTALL_TIMEOUT_OPTION = "uiautomator2ServerInstallTimeout"; + + /** + * Set the maximum timeout to wait util UiAutomator2Server is installed on the device. + * 20000 ms by default + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setUiautomator2ServerInstallTimeout(Duration timeout) { + return amend(UIAUTOMATOR2_SERVER_INSTALL_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait until UiAutomator2Server is installed on the device. + * + * @return The timeout value. + */ + default Optional getUiautomator2ServerInstallTimeout() { + return Optional.ofNullable( + toDuration(getCapability(UIAUTOMATOR2_SERVER_INSTALL_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerLaunchTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerLaunchTimeoutOption.java new file mode 100644 index 000000000..ea12f0d09 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerLaunchTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsUiautomator2ServerLaunchTimeoutOption> extends + Capabilities, CanSetCapability { + String UIAUTOMATOR2_SERVER_LAUNCH_TIMEOUT_OPTION = "uiautomator2ServerLaunchTimeout"; + + /** + * Set the maximum timeout to wait util UiAutomator2Server is listening on + * the device. 30000 ms by default + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setUiautomator2ServerLaunchTimeout(Duration timeout) { + return amend(UIAUTOMATOR2_SERVER_LAUNCH_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait until UiAutomator2Server is listening on the device. + * + * @return The timeout value. + */ + default Optional getUiautomator2ServerLaunchTimeout() { + return Optional.ofNullable( + toDuration(getCapability(UIAUTOMATOR2_SERVER_LAUNCH_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerReadTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerReadTimeoutOption.java new file mode 100644 index 000000000..699b73c48 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsUiautomator2ServerReadTimeoutOption.java @@ -0,0 +1,55 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsUiautomator2ServerReadTimeoutOption> extends + Capabilities, CanSetCapability { + String UIAUTOMATOR2_SERVER_READ_TIMEOUT_OPTION = "uiautomator2ServerReadTimeout"; + + /** + * Set the maximum timeout to wait for a HTTP response from UiAutomator2Server. + * Only values greater than zero are accepted. If the given value is too low + * then expect driver commands to fail with timeout of Xms exceeded error. + * 240000 ms by default + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setUiautomator2ServerReadTimeout(Duration timeout) { + return amend(UIAUTOMATOR2_SERVER_READ_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait for a HTTP response from UiAutomator2Server. + * + * @return The timeout value. + */ + default Optional getUiautomator2ServerReadTimeout() { + return Optional.ofNullable( + toDuration(getCapability(UIAUTOMATOR2_SERVER_READ_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java index b97da189c..106b96c59 100644 --- a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java +++ b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java @@ -19,8 +19,10 @@ import org.openqa.selenium.Capabilities; import javax.annotation.Nullable; +import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; public class CapabilityHelpers { public static final String APPIUM_PREFIX = "appium:"; @@ -46,7 +48,7 @@ public static T getCapability(Capabilities caps, String name, Class expec if (caps.getCapability(capName) == null) { continue; } - + if (expectedType == String.class) { return expectedType.cast(String.valueOf(caps.getCapability(capName))); } @@ -56,4 +58,83 @@ public static T getCapability(Capabilities caps, String name, Class expec } return null; } + + /** + * Converts generic capability value to boolean without + * throwing exceptions. + * + * @param value The capability value. + * @return null is the passed value is null otherwise the converted value. + */ + @Nullable + public static Boolean toSafeBoolean(Object value) { + return value == null ? null : Boolean.parseBoolean(String.valueOf(value)); + } + + /** + * Converts generic capability value to integer. + * + * @param value The capability value. + * @throws NumberFormatException If the given value cannot be parsed to a valid integer. + * @return null is the passed value is null otherwise the converted value. + */ + @Nullable + public static Integer toInteger(Object value) { + if (value == null) { + return null; + } else if (value instanceof Number) { + return ((Number) value).intValue(); + } else { + return Integer.parseInt(String.valueOf(value)); + } + } + + /** + * Converts generic capability value to long without + * throwing exceptions. + * + * @param value The capability value. + * @throws NumberFormatException If the given value cannot be parsed to a valid long. + * @return null is the passed value is null otherwise the converted value. + */ + @Nullable + public static Long toLong(Object value) { + if (value == null) { + return null; + } else if (value instanceof Number) { + return ((Number) value).longValue(); + } else { + return Long.parseLong(String.valueOf(value)); + } + } + + /** + * Converts generic capability value to duration without + * throwing exceptions. The value is assumed to be + * measured in milliseconds. + * + * @param value The capability value. + * @throws NumberFormatException If the given value cannot be parsed to a valid number. + * @return null is the passed value is null otherwise the converted value. + */ + @Nullable + public static Duration toDuration(Object value) { + return toDuration(value, Duration::ofMillis); + } + + /** + * Converts generic capability value to duration without + * throwing exceptions. + * + * @param value The capability value. + * @param converter Converts the numeric value to a Duration instance. + * @throws NumberFormatException If the given value cannot be parsed to a valid number. + * @return null is the passed value is null otherwise the converted value. + */ + @Nullable + public static Duration toDuration(Object value, + Function converter) { + Long v = toLong(value); + return v == null ? null : converter.apply(v); + } } diff --git a/src/main/java/io/appium/java_client/remote/MobileOptions.java b/src/main/java/io/appium/java_client/remote/MobileOptions.java index fad8d5ad1..98bd098b7 100644 --- a/src/main/java/io/appium/java_client/remote/MobileOptions.java +++ b/src/main/java/io/appium/java_client/remote/MobileOptions.java @@ -16,18 +16,13 @@ package io.appium.java_client.remote; -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.SupportsAppOption; -import io.appium.java_client.remote.options.SupportsAutoWebViewOption; -import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; -import io.appium.java_client.remote.options.SupportsDeviceNameOption; -import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; -import io.appium.java_client.remote.options.SupportsLanguageOption; -import io.appium.java_client.remote.options.SupportsLocaleOption; -import io.appium.java_client.remote.options.SupportsOrientationOption; -import io.appium.java_client.remote.options.SupportsOtherAppsOption; -import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.remote.CapabilityType; + +import java.net.URL; +import java.time.Duration; /** * Use the specific options class for your driver, @@ -36,12 +31,7 @@ * @param The child class for a proper chaining. */ @Deprecated -public class MobileOptions> extends BaseOptions - implements SupportsAppOption, SupportsAutoWebViewOption, - SupportsClearSystemFilesOption, SupportsDeviceNameOption, - SupportsEnablePerformanceLoggingOption, SupportsLanguageOption, - SupportsLocaleOption, SupportsOrientationOption, SupportsOtherAppsOption, - SupportsUdidOption { +public class MobileOptions> extends MutableCapabilities { /** * Creates new instance with no preset capabilities. @@ -57,4 +47,466 @@ public MobileOptions() { public MobileOptions(Capabilities source) { super(source); } + + /** + * Set the kind of mobile device or emulator to use. + * + * @param platform the kind of mobile device or emulator to use. + * @return this MobileOptions, for chaining. + * @see org.openqa.selenium.remote.CapabilityType#PLATFORM_NAME + */ + public T setPlatformName(String platform) { + return amend(CapabilityType.PLATFORM_NAME, platform); + } + + /** + * Set the absolute local path for the location of the App. + * The or remote http URL to a {@code .ipa} file (IOS), + * + * @param path is a String representing the location of the App + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#APP + */ + public T setApp(String path) { + return amend(MobileCapabilityType.APP, path); + } + + /** + * Set the remote http URL for the location of the App. + * + * @param url is the URL representing the location of the App + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#APP + */ + public T setApp(URL url) { + return setApp(url.toString()); + } + + /** + * Get the app location. + * + * @return String representing app location + * @see MobileCapabilityType#APP + */ + public String getApp() { + return (String) getCapability(MobileCapabilityType.APP); + } + + /** + * Set the automation engine to use. + * + * @param name is the name of the automation engine + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#AUTOMATION_NAME + */ + public T setAutomationName(String name) { + return amend(MobileCapabilityType.AUTOMATION_NAME, name); + } + + /** + * Get the automation engine to use. + * + * @return String representing the name of the automation engine + * @see MobileCapabilityType#AUTOMATION_NAME + */ + public String getAutomationName() { + return (String) getCapability(MobileCapabilityType.AUTOMATION_NAME); + } + + /** + * Set the app to move directly into Webview context. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#AUTO_WEBVIEW + */ + public T setAutoWebview() { + return setAutoWebview(true); + } + + /** + * Set whether the app moves directly into Webview context. + * + * @param bool is whether the app moves directly into Webview context. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#AUTO_WEBVIEW + */ + public T setAutoWebview(boolean bool) { + return amend(MobileCapabilityType.AUTO_WEBVIEW, bool); + } + + /** + * Get whether the app moves directly into Webview context. + * + * @return true if app moves directly into Webview context. + * @see MobileCapabilityType#AUTO_WEBVIEW + */ + public boolean doesAutoWebview() { + return (boolean) getCapability(MobileCapabilityType.AUTO_WEBVIEW); + } + + /** + * Set the app to delete any generated files at the end of a session. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#CLEAR_SYSTEM_FILES + */ + public T setClearSystemFiles() { + return setClearSystemFiles(true); + } + + /** + * Set whether the app deletes generated files at the end of a session. + * + * @param bool is whether the app deletes generated files at the end of a session. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#CLEAR_SYSTEM_FILES + */ + public T setClearSystemFiles(boolean bool) { + return amend(MobileCapabilityType.CLEAR_SYSTEM_FILES, bool); + } + + /** + * Get whether the app deletes generated files at the end of a session. + * + * @return true if the app deletes generated files at the end of a session. + * @see MobileCapabilityType#CLEAR_SYSTEM_FILES + */ + public boolean doesClearSystemFiles() { + return (boolean) getCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES); + } + + /** + * Set the name of the device. + * + * @param deviceName is the name of the device. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#DEVICE_NAME + */ + public T setDeviceName(String deviceName) { + return amend(MobileCapabilityType.DEVICE_NAME, deviceName); + } + + /** + * Get the name of the device. + * + * @return String representing the name of the device. + * @see MobileCapabilityType#DEVICE_NAME + */ + public String getDeviceName() { + return (String) getCapability(MobileCapabilityType.DEVICE_NAME); + } + + /** + * Set the app to enable performance logging. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + */ + public T setEnablePerformanceLogging() { + return setEnablePerformanceLogging(true); + } + + /** + * Set whether the app logs performance. + * + * @param bool is whether the app logs performance. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + */ + public T setEnablePerformanceLogging(boolean bool) { + return amend(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING, bool); + } + + /** + * Get the app logs performance. + * + * @return true if the app logs performance. + * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + */ + public boolean isEnablePerformanceLogging() { + return (boolean) getCapability(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING); + } + + /** + * Set the app to report the timings for various Appium-internal events. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#EVENT_TIMINGS + */ + public T setEventTimings() { + return setEventTimings(true); + } + + /** + * Set whether the app reports the timings for various Appium-internal events. + * + * @param bool is whether the app enables event timings. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#EVENT_TIMINGS + */ + public T setEventTimings(boolean bool) { + return amend(MobileCapabilityType.EVENT_TIMINGS, bool); + } + + /** + * Get whether the app reports the timings for various Appium-internal events. + * + * @return true if the app reports event timings. + * @see MobileCapabilityType#EVENT_TIMINGS + */ + public boolean doesEventTimings() { + return (boolean) getCapability(MobileCapabilityType.EVENT_TIMINGS); + } + + /** + * Set the app to do a full reset. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#FULL_RESET + */ + public T setFullReset() { + return setFullReset(true); + } + + /** + * Set whether the app does a full reset. + * + * @param bool is whether the app does a full reset. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#FULL_RESET + */ + public T setFullReset(boolean bool) { + return amend(MobileCapabilityType.FULL_RESET, bool); + } + + /** + * Get whether the app does a full reset. + * + * @return true if the app does a full reset. + * @see MobileCapabilityType#FULL_RESET + */ + public boolean doesFullReset() { + return (boolean) getCapability(MobileCapabilityType.FULL_RESET); + } + + /** + * Set language abbreviation for use in session. + * + * @param language is the language abbreviation. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#LANGUAGE + */ + public T setLanguage(String language) { + return amend(MobileCapabilityType.LANGUAGE, language); + } + + /** + * Get language abbreviation for use in session. + * + * @return String representing the language abbreviation. + * @see MobileCapabilityType#LANGUAGE + */ + public String getLanguage() { + return (String) getCapability(MobileCapabilityType.LANGUAGE); + } + + /** + * Set locale abbreviation for use in session. + * + * @param locale is the locale abbreviation. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#LOCALE + */ + public T setLocale(String locale) { + return amend(MobileCapabilityType.LOCALE, locale); + } + + /** + * Get locale abbreviation for use in session. + * + * @return String representing the locale abbreviation. + * @see MobileCapabilityType#LOCALE + */ + public String getLocale() { + return (String) getCapability(MobileCapabilityType.LOCALE); + } + + /** + * Set the timeout for new commands. + * + * @param duration is the allowed time before seeing a new command. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT + */ + public T setNewCommandTimeout(Duration duration) { + return amend(MobileCapabilityType.NEW_COMMAND_TIMEOUT, duration.getSeconds()); + } + + /** + * Get the timeout for new commands. + * + * @return allowed time before seeing a new command. + * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT + */ + public Duration getNewCommandTimeout() { + Object duration = getCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT); + return Duration.ofSeconds(Long.parseLong("" + duration)); + } + + /** + * Set the app not to do a reset. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#NO_RESET + */ + public T setNoReset() { + return setNoReset(true); + } + + /** + * Set whether the app does not do a reset. + * + * @param bool is whether the app does not do a reset. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#NO_RESET + */ + public T setNoReset(boolean bool) { + return amend(MobileCapabilityType.NO_RESET, bool); + } + + /** + * Get whether the app does not do a reset. + * + * @return true if the app does not do a reset. + * @see MobileCapabilityType#NO_RESET + */ + public boolean doesNoReset() { + return (boolean) getCapability(MobileCapabilityType.NO_RESET); + } + + /** + * Set the orientation of the screen. + * + * @param orientation is the screen orientation. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#ORIENTATION + */ + public T setOrientation(ScreenOrientation orientation) { + return amend(MobileCapabilityType.ORIENTATION, orientation); + } + + /** + * Get the orientation of the screen. + * + * @return ScreenOrientation of the app. + * @see MobileCapabilityType#ORIENTATION + */ + public ScreenOrientation getOrientation() { + return (ScreenOrientation) getCapability(MobileCapabilityType.ORIENTATION); + } + + /** + * Set the location of the app(s) to install before running a test. + * + * @param apps is the apps to install. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#OTHER_APPS + */ + public T setOtherApps(String apps) { + return amend(MobileCapabilityType.OTHER_APPS, apps); + } + + /** + * Get the list of apps to install before running a test. + * + * @return String of apps to install. + * @see MobileCapabilityType#OTHER_APPS + */ + public String getOtherApps() { + return (String) getCapability(MobileCapabilityType.OTHER_APPS); + } + + /** + * Set the version of the platform. + * + * @param version is the platform version. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#PLATFORM_VERSION + */ + public T setPlatformVersion(String version) { + return amend(MobileCapabilityType.PLATFORM_VERSION, version); + } + + /** + * Get the version of the platform. + * + * @return String representing the platform version. + * @see MobileCapabilityType#PLATFORM_VERSION + */ + public String getPlatformVersion() { + return (String) getCapability(MobileCapabilityType.PLATFORM_VERSION); + } + + /** + * Set the app to print page source when a find operation fails. + * + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE + */ + public T setPrintPageSourceOnFindFailure() { + return setPrintPageSourceOnFindFailure(true); + } + + /** + * Set whether the app to print page source when a find operation fails. + * + * @param bool is whether to print page source. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE + */ + public T setPrintPageSourceOnFindFailure(boolean bool) { + return amend(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE, bool); + } + + /** + * Get whether the app to print page source when a find operation fails. + * + * @return true if app prints page source. + * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE + */ + public boolean doesPrintPageSourceOnFindFailure() { + return (boolean) getCapability(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE); + } + + /** + * Set the id of the device. + * + * @param id is the unique device identifier. + * @return this MobileOptions, for chaining. + * @see MobileCapabilityType#UDID + */ + public T setUdid(String id) { + return amend(MobileCapabilityType.UDID, id); + } + + /** + * Get the id of the device. + * + * @return String representing the unique device identifier. + * @see MobileCapabilityType#UDID + */ + public String getUdid() { + return (String) getCapability(MobileCapabilityType.UDID); + } + + @Override + public T merge(Capabilities extraCapabilities) { + super.merge(extraCapabilities); + return (T) this; + } + + protected T amend(String optionName, Object value) { + setCapability(optionName, value); + return (T) this; + } } diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index cdfb8f168..ff575989f 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -16,13 +16,13 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.AcceptedW3CCapabilityKeys; import org.openqa.selenium.remote.CapabilityType; -import java.time.Duration; +import javax.annotation.Nullable; import java.util.Map; import java.util.stream.Collectors; @@ -35,12 +35,13 @@ * * @param The child class for a proper chaining. */ -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "UnusedReturnValue"}) public class BaseOptions> extends MutableCapabilities - implements CanSetCapability { - private static final AcceptedW3CCapabilityKeys W3C_KEY_PATTERNS = - new AcceptedW3CCapabilityKeys(); - + implements CanSetCapability, SupportsAutomationNameOption, + SupportsEventTimingsOption, SupportsPrintPageSourceOnFindFailureOption, + SupportsNoResetOption, SupportsFullResetOption, SupportsNewCommandTimeoutOption, + SupportsPlatformVersionOption { + private static final AcceptedW3CCapabilityKeys W3C_KEY_PATTERNS = new AcceptedW3CCapabilityKeys(); /** * Creates new instance with no preset capabilities. @@ -68,194 +69,6 @@ public T setPlatformName(String platform) { return amend(CapabilityType.PLATFORM_NAME, platform); } - /** - * Set the automation engine to use. - * - * @param name is the name of the automation engine - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTOMATION_NAME - */ - public T setAutomationName(String name) { - return amend(MobileCapabilityType.AUTOMATION_NAME, name); - } - - /** - * Get the automation engine to use. - * - * @return String representing the name of the automation engine - * @see MobileCapabilityType#AUTOMATION_NAME - */ - public String getAutomationName() { - return (String) getCapability(MobileCapabilityType.AUTOMATION_NAME); - } - - /** - * Set the app to report the timings for various Appium-internal events. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public T setEventTimings() { - return setEventTimings(true); - } - - /** - * Set whether the app reports the timings for various Appium-internal events. - * - * @param bool is whether the app enables event timings. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public T setEventTimings(boolean bool) { - return amend(MobileCapabilityType.EVENT_TIMINGS, bool); - } - - /** - * Get whether the app reports the timings for various Appium-internal events. - * - * @return true if the app reports event timings. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public boolean doesEventTimings() { - return (boolean) getCapability(MobileCapabilityType.EVENT_TIMINGS); - } - - /** - * Set the app to do a full reset. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#FULL_RESET - */ - public T setFullReset() { - return setFullReset(true); - } - - /** - * Set whether the app does a full reset. - * - * @param bool is whether the app does a full reset. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#FULL_RESET - */ - public T setFullReset(boolean bool) { - return amend(MobileCapabilityType.FULL_RESET, bool); - } - - /** - * Get whether the app does a full reset. - * - * @return true if the app does a full reset. - * @see MobileCapabilityType#FULL_RESET - */ - public boolean doesFullReset() { - return (boolean) getCapability(MobileCapabilityType.FULL_RESET); - } - - /** - * Set the timeout for new commands. - * - * @param duration is the allowed time before seeing a new command. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT - */ - public T setNewCommandTimeout(Duration duration) { - return amend(MobileCapabilityType.NEW_COMMAND_TIMEOUT, duration.getSeconds()); - } - - /** - * Get the timeout for new commands. - * - * @return allowed time before seeing a new command. - * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT - */ - public Duration getNewCommandTimeout() { - Object duration = getCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT); - return Duration.ofSeconds(Long.parseLong("" + duration)); - } - - /** - * Set the app not to do a reset. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NO_RESET - */ - public T setNoReset() { - return setNoReset(true); - } - - /** - * Set whether the app does not do a reset. - * - * @param bool is whether the app does not do a reset. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NO_RESET - */ - public T setNoReset(boolean bool) { - return amend(MobileCapabilityType.NO_RESET, bool); - } - - /** - * Get whether the app does not do a reset. - * - * @return true if the app does not do a reset. - * @see MobileCapabilityType#NO_RESET - */ - public boolean doesNoReset() { - return (boolean) getCapability(MobileCapabilityType.NO_RESET); - } - - /** - * Set the version of the platform. - * - * @param version is the platform version. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PLATFORM_VERSION - */ - public T setPlatformVersion(String version) { - return amend(MobileCapabilityType.PLATFORM_VERSION, version); - } - - /** - * Get the version of the platform. - * - * @return String representing the platform version. - * @see MobileCapabilityType#PLATFORM_VERSION - */ - public String getPlatformVersion() { - return (String) getCapability(MobileCapabilityType.PLATFORM_VERSION); - } - - /** - * Set the app to print page source when a find operation fails. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public T setPrintPageSourceOnFindFailure() { - return setPrintPageSourceOnFindFailure(true); - } - - /** - * Set whether the app to print page source when a find operation fails. - * - * @param bool is whether to print page source. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public T setPrintPageSourceOnFindFailure(boolean bool) { - return amend(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE, bool); - } - - /** - * Get whether the app to print page source when a find operation fails. - * - * @return true if app prints page source. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public boolean doesPrintPageSourceOnFindFailure() { - return (boolean) getCapability(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE); - } - @Override public Map asMap() { return unmodifiableMap(super.asMap().entrySet().stream() @@ -270,4 +83,20 @@ public T merge(Capabilities extraCapabilities) { //noinspection unchecked return (T) this; } -} + + @Override + public void setCapability(String key, @Nullable Object value) { + Require.nonNull("Capability name", key); + super.setCapability(W3C_KEY_PATTERNS.test(key) ? key : APPIUM_PREFIX + key, value); + } + + @Override + @Nullable + public Object getCapability(String capabilityName) { + Object value = super.getCapability(capabilityName); + if (value == null) { + value = super.getCapability(APPIUM_PREFIX + capabilityName); + } + return value; + } +} \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java index 8e112a32f..043904fde 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAppOption.java @@ -16,32 +16,32 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; import java.net.URL; +import java.util.Optional; public interface SupportsAppOption> extends Capabilities, CanSetCapability { + String APP_OPTION = "app"; /** * Set the absolute local path for the location of the App. - * The or remote http URL to a {@code .ipa} file (IOS), + * The app must be located on the same machine where Appium + * server is running. * * @param path is a String representing the location of the App - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#APP + * @return self instance for chaining. */ default T setApp(String path) { - return amend(MobileCapabilityType.APP, path); + return amend(APP_OPTION, path); } /** * Set the remote http URL for the location of the App. * * @param url is the URL representing the location of the App - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#APP + * @return self instance for chaining. */ default T setApp(URL url) { return setApp(url.toString()); @@ -51,9 +51,8 @@ default T setApp(URL url) { * Get the app location. * * @return String representing app location - * @see MobileCapabilityType#APP */ - default String getApp() { - return (String) getCapability(MobileCapabilityType.APP); + default Optional getApp() { + return Optional.ofNullable((String) getCapability(APP_OPTION)); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java index 8c68c20bf..8a5d7e9fd 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java @@ -16,18 +16,22 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + public interface SupportsAutoWebViewOption> extends Capabilities, CanSetCapability { + String AUTO_WEB_VIEW_OPTION = "autoWebView"; + /** * Set the app to move directly into Webview context. * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTO_WEBVIEW + * @return self instance for chaining. */ - default T setAutoWebview() { + default T autoWebview() { return setAutoWebview(true); } @@ -35,20 +39,18 @@ default T setAutoWebview() { * Set whether the app moves directly into Webview context. * * @param bool is whether the app moves directly into Webview context. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTO_WEBVIEW + * @return self instance for chaining. */ default T setAutoWebview(boolean bool) { - return amend(MobileCapabilityType.AUTO_WEBVIEW, bool); + return amend(AUTO_WEB_VIEW_OPTION, bool); } /** * Get whether the app moves directly into Webview context. * * @return true if app moves directly into Webview context. - * @see MobileCapabilityType#AUTO_WEBVIEW */ - default boolean doesAutoWebview() { - return (boolean) getCapability(MobileCapabilityType.AUTO_WEBVIEW); + default Optional doesAutoWebview() { + return Optional.ofNullable(toSafeBoolean(getCapability(AUTO_WEB_VIEW_OPTION))); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAutomationNameOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAutomationNameOption.java new file mode 100644 index 000000000..2fdb5870d --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAutomationNameOption.java @@ -0,0 +1,45 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAutomationNameOption> extends + Capabilities, CanSetCapability { + String AUTOMATION_NAME_OPTION = "automationName"; + + /** + * Set the automation driver to use. + * + * @param automationName One of supported automation names. + * @return self instance for chaining. + */ + default T setAutomationName(String automationName) { + return amend(AUTOMATION_NAME_OPTION, automationName); + } + + /** + * Get the automation driver to use. + * + * @return String representing the name of the automation engine + */ + default Optional getAutomationName() { + return Optional.ofNullable((String) getCapability(AUTOMATION_NAME_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java index 162956fc1..0d652a1da 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java @@ -16,19 +16,22 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + public interface SupportsClearSystemFilesOption> extends Capabilities, CanSetCapability { + String CLEAR_SYSTEM_FILES_OPTION = "clearSystemFiles"; /** * Set the app to delete any generated files at the end of a session. * * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES */ - default T setClearSystemFiles() { + default T clearSystemFiles() { return setClearSystemFiles(true); } @@ -37,19 +40,17 @@ default T setClearSystemFiles() { * * @param bool is whether the app deletes generated files at the end of a session. * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES */ default T setClearSystemFiles(boolean bool) { - return amend(MobileCapabilityType.CLEAR_SYSTEM_FILES, bool); + return amend(CLEAR_SYSTEM_FILES_OPTION, bool); } /** * Get whether the app deletes generated files at the end of a session. * * @return true if the app deletes generated files at the end of a session. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES */ - default boolean doesClearSystemFiles() { - return (boolean) getCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES); + default Optional doesClearSystemFiles() { + return Optional.ofNullable(toSafeBoolean(getCapability(CLEAR_SYSTEM_FILES_OPTION))); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java index 91f1a8c75..729741bbc 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java @@ -16,29 +16,30 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + public interface SupportsDeviceNameOption> extends Capabilities, CanSetCapability { + String DEVICE_NAME_OPTION = "deviceName"; + /** * Set the name of the device. * * @param deviceName is the name of the device. * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#DEVICE_NAME */ default T setDeviceName(String deviceName) { - return amend(MobileCapabilityType.DEVICE_NAME, deviceName); + return amend(DEVICE_NAME_OPTION, deviceName); } /** * Get the name of the device. * * @return String representing the name of the device. - * @see MobileCapabilityType#DEVICE_NAME */ - default String getDeviceName() { - return (String) getCapability(MobileCapabilityType.DEVICE_NAME); + default Optional getDeviceName() { + return Optional.ofNullable((String) getCapability(DEVICE_NAME_OPTION)); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java index 82ff44573..cf3601925 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsEnablePerformanceLoggingOption.java @@ -16,19 +16,22 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + public interface SupportsEnablePerformanceLoggingOption> extends Capabilities, CanSetCapability { + String ENABLE_PERFORMANCE_LOGGING_OPTION = "enablePerformanceLogging"; /** * Set the app to enable performance logging. * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + * @return self instance for chaining. */ - default T setEnablePerformanceLogging() { + default T enablePerformanceLogging() { return setEnablePerformanceLogging(true); } @@ -36,20 +39,18 @@ default T setEnablePerformanceLogging() { * Set whether the app logs performance. * * @param bool is whether the app logs performance. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING + * @return self instance for chaining. */ default T setEnablePerformanceLogging(boolean bool) { - return amend(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING, bool); + return amend(ENABLE_PERFORMANCE_LOGGING_OPTION, bool); } /** * Get the app logs performance. * * @return true if the app logs performance. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING */ - default boolean isEnablePerformanceLogging() { - return (boolean) getCapability(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING); + default Optional isEnablePerformanceLogging() { + return Optional.ofNullable(toSafeBoolean(getCapability(ENABLE_PERFORMANCE_LOGGING_OPTION))); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java new file mode 100644 index 000000000..3d6bd39e6 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java @@ -0,0 +1,56 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsEventTimingsOption> extends + Capabilities, CanSetCapability { + String EVENT_TIMINGS_OPTION = "eventTimings"; + + /** + * Set the app to report the timings for various Appium-internal events. + * + * @return self instance for chaining. + */ + default T setEventTimings() { + return setEventTimings(true); + } + + /** + * Set whether the app reports the timings for various Appium-internal events. + * + * @param bool is whether the app enables event timings. + * @return self instance for chaining. + */ + default T setEventTimings(boolean bool) { + return amend(EVENT_TIMINGS_OPTION, bool); + } + + /** + * Get whether the app reports the timings for various Appium-internal events. + * + * @return true if the app reports event timings. + */ + default Optional doesEventTimings() { + return Optional.ofNullable(toSafeBoolean(getCapability(EVENT_TIMINGS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsFullResetOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsFullResetOption.java new file mode 100644 index 000000000..667bb1f3d --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsFullResetOption.java @@ -0,0 +1,56 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsFullResetOption> extends + Capabilities, CanSetCapability { + String FULL_RESET_OPTION = "fullReset"; + + /** + * Set the app to do a full reset. + * + * @return self instance for chaining. + */ + default T fullReset() { + return setFullReset(true); + } + + /** + * Set whether the app does a full reset. + * + * @param bool is whether the app does a full reset. + * @return self instance for chaining. + */ + default T setFullReset(boolean bool) { + return amend(FULL_RESET_OPTION, bool); + } + + /** + * Get whether the app does a full reset. + * + * @return true if the app does a full reset. + */ + default Optional doesFullReset() { + return Optional.ofNullable(toSafeBoolean(getCapability(FULL_RESET_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java index 12e46838e..8428d6f45 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java @@ -16,30 +16,30 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + public interface SupportsLanguageOption> extends Capabilities, CanSetCapability { + String LANGUAGE_OPTION = "language"; /** * Set language abbreviation for use in session. * * @param language is the language abbreviation. * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#LANGUAGE */ default T setLanguage(String language) { - return amend(MobileCapabilityType.LANGUAGE, language); + return amend(LANGUAGE_OPTION, language); } /** * Get language abbreviation for use in session. * * @return String representing the language abbreviation. - * @see MobileCapabilityType#LANGUAGE */ - default String getLanguage() { - return (String) getCapability(MobileCapabilityType.LANGUAGE); + default Optional getLanguage() { + return Optional.ofNullable((String) getCapability(LANGUAGE_OPTION)); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java index f2f0d26e5..37689be59 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsLocaleOption.java @@ -16,30 +16,30 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + public interface SupportsLocaleOption> extends Capabilities, CanSetCapability { + String LOCALE_OPTION = "locale"; /** * Set locale abbreviation for use in session. * * @param locale is the locale abbreviation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#LOCALE + * @return self instance for chaining. */ default T setLocale(String locale) { - return amend(MobileCapabilityType.LOCALE, locale); + return amend(LOCALE_OPTION, locale); } /** * Get locale abbreviation for use in session. * * @return String representing the locale abbreviation. - * @see MobileCapabilityType#LOCALE */ - default String getLocale() { - return (String) getCapability(MobileCapabilityType.LOCALE); + default Optional getLocale() { + return Optional.ofNullable((String) getCapability(LOCALE_OPTION)); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsNewCommandTimeoutOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsNewCommandTimeoutOption.java new file mode 100644 index 000000000..f9358fa95 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsNewCommandTimeoutOption.java @@ -0,0 +1,50 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsNewCommandTimeoutOption> extends + Capabilities, CanSetCapability { + String NEW_COMMAND_TIMEOUT_OPTION = "newCommandTimeout"; + + /** + * Set the timeout for new commands. + * + * @param duration is the allowed time before seeing a new command. + * @return self instance for chaining. + */ + default T setNewCommandTimeout(Duration duration) { + return amend(NEW_COMMAND_TIMEOUT_OPTION, duration.getSeconds()); + } + + /** + * Get the timeout for new commands. + * + * @return allowed time before seeing a new command. + */ + default Optional getNewCommandTimeout() { + return Optional.ofNullable( + toDuration(getCapability(NEW_COMMAND_TIMEOUT_OPTION), Duration::ofSeconds) + ); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsNoResetOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsNoResetOption.java new file mode 100644 index 000000000..9116cac48 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsNoResetOption.java @@ -0,0 +1,56 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsNoResetOption> extends + Capabilities, CanSetCapability { + String NO_RESET_OPTION = "noReset"; + + /** + * Set the app not to do a reset. + * + * @return self instance for chaining. + */ + default T noReset() { + return setNoReset(true); + } + + /** + * Set whether the app does not do a reset. + * + * @param bool is whether the app does not do a reset. + * @return self instance for chaining. + */ + default T setNoReset(boolean bool) { + return amend(NO_RESET_OPTION, bool); + } + + /** + * Get whether the app does not do a reset. + * + * @return true if the app does not do a reset. + */ + default Optional doesNoReset() { + return Optional.ofNullable(toSafeBoolean(getCapability(NO_RESET_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java index 4bc34bb59..e27acbdcf 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java @@ -16,31 +16,35 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ScreenOrientation; +import java.util.Optional; + public interface SupportsOrientationOption> extends Capabilities, CanSetCapability { + String ORIENTATION_OPTION = "orientation"; /** * Set the orientation of the screen. * * @param orientation is the screen orientation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ORIENTATION + * @return self instance for chaining. */ default T setOrientation(ScreenOrientation orientation) { - return amend(MobileCapabilityType.ORIENTATION, orientation); + return amend(ORIENTATION_OPTION, orientation.value()); } /** * Get the orientation of the screen. * * @return ScreenOrientation of the app. - * @see MobileCapabilityType#ORIENTATION */ - default ScreenOrientation getOrientation() { - return (ScreenOrientation) getCapability(MobileCapabilityType.ORIENTATION); + default Optional getOrientation() { + return Optional.ofNullable(getCapability(ORIENTATION_OPTION)) + .map((v) -> v instanceof ScreenOrientation + ? (ScreenOrientation) v + : ScreenOrientation.valueOf((String.valueOf(v)).toUpperCase()) + ); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java index 2de4c224f..fa08176bc 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOtherAppsOption.java @@ -16,31 +16,30 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + public interface SupportsOtherAppsOption> extends Capabilities, CanSetCapability { - + String OTHER_APPS_OPTION = "otherApps"; /** * Set the location of the app(s) to install before running a test. * * @param apps is the apps to install. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#OTHER_APPS + * @return self instance for chaining. */ default T setOtherApps(String apps) { - return amend(MobileCapabilityType.OTHER_APPS, apps); + return amend(OTHER_APPS_OPTION, apps); } /** * Get the list of apps to install before running a test. * * @return String of apps to install. - * @see MobileCapabilityType#OTHER_APPS */ - default String getOtherApps() { - return (String) getCapability(MobileCapabilityType.OTHER_APPS); + default Optional getOtherApps() { + return Optional.ofNullable((String) getCapability(OTHER_APPS_OPTION)); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsPlatformVersionOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsPlatformVersionOption.java new file mode 100644 index 000000000..fbb319f32 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsPlatformVersionOption.java @@ -0,0 +1,45 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsPlatformVersionOption> extends + Capabilities, CanSetCapability { + String PLATFORM_VERSION_OPTION = "platformVersion"; + + /** + * Set the version of the platform. + * + * @param version is the platform version. + * @return self instance for chaining. + */ + default T setPlatformVersion(String version) { + return amend(PLATFORM_VERSION_OPTION, version); + } + + /** + * Get the version of the platform. + * + * @return String representing the platform version. + */ + default Optional getPlatformVersion() { + return Optional.ofNullable((String) getCapability(PLATFORM_VERSION_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsPrintPageSourceOnFindFailureOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsPrintPageSourceOnFindFailureOption.java new file mode 100644 index 000000000..3d82738c5 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsPrintPageSourceOnFindFailureOption.java @@ -0,0 +1,58 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsPrintPageSourceOnFindFailureOption> extends + Capabilities, CanSetCapability { + String PRINT_PAGE_SOURCE_ON_FIND_FAILURE_OPTION = "printPageSourceOnFindFailure"; + + /** + * Set the app to print page source when a find operation fails. + * + * @return self instance for chaining. + */ + default T printPageSourceOnFindFailure() { + return setPrintPageSourceOnFindFailure(true); + } + + /** + * Set whether the app to print page source when a find operation fails. + * + * @param bool is whether to print page source. + * @return self instance for chaining. + */ + default T setPrintPageSourceOnFindFailure(boolean bool) { + return amend(PRINT_PAGE_SOURCE_ON_FIND_FAILURE_OPTION, bool); + } + + /** + * Get whether the app to print page source when a find operation fails. + * + * @return true if app prints page source. + */ + default Optional doesPrintPageSourceOnFindFailure() { + return Optional.ofNullable( + toSafeBoolean(getCapability(PRINT_PAGE_SOURCE_ON_FIND_FAILURE_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java index bc6e59b37..fc1364b3d 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsUdidOption.java @@ -16,29 +16,30 @@ package io.appium.java_client.remote.options; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; +import java.util.Optional; + public interface SupportsUdidOption> extends Capabilities, CanSetCapability { + String UDID_OPTION = "udid"; + /** * Set the id of the device. * * @param id is the unique device identifier. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#UDID + * @return self instance, for chaining. */ default T setUdid(String id) { - return amend(MobileCapabilityType.UDID, id); + return amend(UDID_OPTION, id); } /** * Get the id of the device. * * @return String representing the unique device identifier. - * @see MobileCapabilityType#UDID */ - default String getUdid() { - return (String) getCapability(MobileCapabilityType.UDID); + default Optional getUdid() { + return Optional.ofNullable((String) getCapability(UDID_OPTION)); } } From eafcd947e95b7a53468f6f0df4a3c46c7ce79c51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:43:08 +0300 Subject: [PATCH 004/501] build(deps): bump spring-context from 5.3.10 to 5.3.12 (#1546) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.10 to 5.3.12. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.10...v5.3.12) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 356beb536..ebc729080 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.10' + implementation 'org.springframework:spring-context:5.3.12' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.32' From 093720fd28bacf944fb16f596f58081fc3db37c8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 25 Oct 2021 17:11:15 +0200 Subject: [PATCH 005/501] chore: Add more UiAutomator2 options (#1545) --- .../android/options/UiAutomator2Options.java | 56 ++++++++++++-- .../adb/SupportsAdbExecTimeoutOption.java | 51 +++++++++++++ .../options/adb/SupportsAdbPortOption.java | 49 ++++++++++++ .../adb/SupportsAllowDelayAdbOption.java | 50 +++++++++++++ .../adb/SupportsBuildToolsVersionOption.java | 51 +++++++++++++ .../SupportsClearDeviceLogsOnStartOption.java | 62 ++++++++++++++++ ...portsIgnoreHiddenApiPolicyErrorOption.java | 60 +++++++++++++++ .../adb/SupportsLogcatFilterSpecsOption.java | 51 +++++++++++++ .../adb/SupportsLogcatFormatOption.java | 48 ++++++++++++ .../adb/SupportsMockLocationAppOption.java | 51 +++++++++++++ .../adb/SupportsRemoteAdbHostOption.java | 48 ++++++++++++ .../adb/SupportsSkipLogcatCaptureOption.java | 60 +++++++++++++++ .../adb/SupportsSuppressKillServerOption.java | 59 +++++++++++++++ .../options/avd/SupportsAvdArgsOption.java | 64 ++++++++++++++++ .../options/avd/SupportsAvdEnvOption.java | 50 +++++++++++++ .../avd/SupportsAvdLaunchTimeoutOption.java | 53 +++++++++++++ .../options/avd/SupportsAvdOption.java | 50 +++++++++++++ .../avd/SupportsAvdReadyTimeoutOption.java | 53 +++++++++++++ .../options/avd/SupportsGpsEnabledOption.java | 60 +++++++++++++++ .../options/avd/SupportsIsHeadlessOption.java | 61 +++++++++++++++ .../avd/SupportsNetworkSpeedOption.java | 50 +++++++++++++ .../SupportsLocaleScriptOption.java | 49 ++++++++++++ .../options/signing/KeystoreConfig.java | 29 ++++++++ .../signing/SupportsKeystoreOptions.java | 74 +++++++++++++++++++ .../options/signing/SupportsNoSignOption.java | 63 ++++++++++++++++ 25 files changed, 1347 insertions(+), 5 deletions(-) create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsAdbExecTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsAdbPortOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsAllowDelayAdbOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsBuildToolsVersionOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsClearDeviceLogsOnStartOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsIgnoreHiddenApiPolicyErrorOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFormatOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsMockLocationAppOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsRemoteAdbHostOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsSkipLogcatCaptureOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/adb/SupportsSuppressKillServerOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsAvdLaunchTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsAvdOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsAvdReadyTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsGpsEnabledOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/avd/SupportsNetworkSpeedOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/localization/SupportsLocaleScriptOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/signing/KeystoreConfig.java create mode 100644 src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java create mode 100644 src/main/java/io/appium/java_client/android/options/signing/SupportsNoSignOption.java diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index c228e917f..f13dda020 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -16,6 +16,18 @@ package io.appium.java_client.android.options; +import io.appium.java_client.android.options.adb.SupportsAdbExecTimeoutOption; +import io.appium.java_client.android.options.adb.SupportsAdbPortOption; +import io.appium.java_client.android.options.adb.SupportsAllowDelayAdbOption; +import io.appium.java_client.android.options.adb.SupportsBuildToolsVersionOption; +import io.appium.java_client.android.options.adb.SupportsClearDeviceLogsOnStartOption; +import io.appium.java_client.android.options.adb.SupportsIgnoreHiddenApiPolicyErrorOption; +import io.appium.java_client.android.options.adb.SupportsLogcatFilterSpecsOption; +import io.appium.java_client.android.options.adb.SupportsLogcatFormatOption; +import io.appium.java_client.android.options.adb.SupportsMockLocationAppOption; +import io.appium.java_client.android.options.adb.SupportsRemoteAdbHostOption; +import io.appium.java_client.android.options.adb.SupportsSkipLogcatCaptureOption; +import io.appium.java_client.android.options.adb.SupportsSuppressKillServerOption; import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption; import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption; import io.appium.java_client.android.options.app.SupportsAppActivityOption; @@ -32,6 +44,15 @@ import io.appium.java_client.android.options.app.SupportsOptionalIntentArgumentsOption; import io.appium.java_client.android.options.app.SupportsRemoteAppsCacheLimitOption; import io.appium.java_client.android.options.app.SupportsUninstallOtherPackagesOption; +import io.appium.java_client.android.options.avd.SupportsAvdArgsOption; +import io.appium.java_client.android.options.avd.SupportsAvdEnvOption; +import io.appium.java_client.android.options.avd.SupportsAvdLaunchTimeoutOption; +import io.appium.java_client.android.options.avd.SupportsAvdOption; +import io.appium.java_client.android.options.avd.SupportsAvdReadyTimeoutOption; +import io.appium.java_client.android.options.avd.SupportsGpsEnabledOption; +import io.appium.java_client.android.options.avd.SupportsIsHeadlessOption; +import io.appium.java_client.android.options.avd.SupportsNetworkSpeedOption; +import io.appium.java_client.android.options.localization.SupportsLocaleScriptOption; import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption; import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption; import io.appium.java_client.android.options.server.SupportsSkipServerInstallationOption; @@ -39,6 +60,8 @@ import io.appium.java_client.android.options.server.SupportsUiautomator2ServerInstallTimeoutOption; import io.appium.java_client.android.options.server.SupportsUiautomator2ServerLaunchTimeoutOption; import io.appium.java_client.android.options.server.SupportsUiautomator2ServerReadTimeoutOption; +import io.appium.java_client.android.options.signing.SupportsKeystoreOptions; +import io.appium.java_client.android.options.signing.SupportsNoSignOption; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; @@ -58,9 +81,6 @@ * https://github.com/appium/appium-uiautomator2-driver#capabilities */ public class UiAutomator2Options extends BaseOptions implements - // TODO: ADB options: https://github.com/appium/appium-uiautomator2-driver#adb - // TODO: AVD options: https://github.com/appium/appium-uiautomator2-driver#emulator-android-virtual-device - // TODO: App signing options: https://github.com/appium/appium-uiautomator2-driver#app-signing // TODO: Device locking options: https://github.com/appium/appium-uiautomator2-driver#device-locking // TODO: MJPEG options: https://github.com/appium/appium-uiautomator2-driver#mjpeg // TODO: Web Context options: https://github.com/appium/appium-uiautomator2-driver#web-context @@ -100,9 +120,35 @@ public class UiAutomator2Options extends BaseOptions implem SupportsAllowTestPackagesOption, SupportsRemoteAppsCacheLimitOption, SupportsEnforceAppInstallOption, - // TODO: App localization options: https://github.com/appium/appium-uiautomator2-driver#app-localization + // App localization options: https://github.com/appium/appium-uiautomator2-driver#app-localization + SupportsLocaleScriptOption, SupportsLanguageOption, - SupportsLocaleOption { + SupportsLocaleOption, + // ADB options: https://github.com/appium/appium-uiautomator2-driver#adb + SupportsAdbPortOption, + SupportsRemoteAdbHostOption, + SupportsAdbExecTimeoutOption, + SupportsClearDeviceLogsOnStartOption, + SupportsBuildToolsVersionOption, + SupportsSkipLogcatCaptureOption, + SupportsSuppressKillServerOption, + SupportsIgnoreHiddenApiPolicyErrorOption, + SupportsMockLocationAppOption, + SupportsLogcatFormatOption, + SupportsLogcatFilterSpecsOption, + SupportsAllowDelayAdbOption, + // AVD options: https://github.com/appium/appium-uiautomator2-driver#emulator-android-virtual-device + SupportsAvdOption, + SupportsAvdLaunchTimeoutOption, + SupportsAvdReadyTimeoutOption, + SupportsAvdArgsOption, + SupportsAvdEnvOption, + SupportsNetworkSpeedOption, + SupportsGpsEnabledOption, + SupportsIsHeadlessOption, + // App signing options: https://github.com/appium/appium-uiautomator2-driver#app-signing + SupportsKeystoreOptions, + SupportsNoSignOption { public UiAutomator2Options() { setCommonOptions(); } diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsAdbExecTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsAdbExecTimeoutOption.java new file mode 100644 index 000000000..228ab056e --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsAdbExecTimeoutOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsAdbExecTimeoutOption> extends + Capabilities, CanSetCapability { + String ADB_EXEC_TIMEOUT_OPTION = "adbExecTimeout"; + + /** + * Maximum time to wait until single ADB command is executed. + * 20000 ms by default. + * + * @param timeout ADB commands timeout. + * @return self instance for chaining. + */ + default T setAdbExecTimeout(Duration timeout) { + return amend(ADB_EXEC_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get maximum time to wait until single ADB command is executed. + * + * @return Timeout value. + */ + default Optional getAdbExecTimeout() { + return Optional.ofNullable(toDuration(getCapability(ADB_EXEC_TIMEOUT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsAdbPortOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsAdbPortOption.java new file mode 100644 index 000000000..461e609ab --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsAdbPortOption.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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsAdbPortOption> extends + Capabilities, CanSetCapability { + String ADB_PORT_OPTION = "adbPort"; + + /** + * Set number of the port where ADB is running. 5037 by default + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setAdbPort(int port) { + return amend(ADB_PORT_OPTION, port); + } + + /** + * Get number of the port where ADB is running. + * + * @return Adb port value + */ + default Optional getAdbPort() { + return Optional.ofNullable(toInteger(getCapability(ADB_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsAllowDelayAdbOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsAllowDelayAdbOption.java new file mode 100644 index 000000000..fc8ea3b80 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsAllowDelayAdbOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAllowDelayAdbOption> extends + Capabilities, CanSetCapability { + String ALLOW_DELAY_ADB_OPTION = "allowDelayAdb"; + + /** + * Being set to false prevents emulator to use -delay-adb feature to detect its startup. + * See https://github.com/appium/appium/issues/14773 for more details. + * + * @param value Set it to false in order to prevent the emulator to use -delay-adb feature. + * @return self instance for chaining. + */ + default T setAllowDelayAdb(boolean value) { + return amend(ALLOW_DELAY_ADB_OPTION, value); + } + + /** + * Get whether to prevent the emulator to use -delay-adb feature. + * + * @return True or false. + */ + default Optional doesAllowDelayAdb() { + return Optional.ofNullable(toSafeBoolean(getCapability(ALLOW_DELAY_ADB_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsBuildToolsVersionOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsBuildToolsVersionOption.java new file mode 100644 index 000000000..df5b27f5a --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsBuildToolsVersionOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsBuildToolsVersionOption> extends + Capabilities, CanSetCapability { + String BUILD_TOOLS_VERSION_OPTION = "buildToolsVersion"; + + /** + * The version of Android build tools to use. By default, UiAutomator2 + * driver uses the most recent version of build tools installed on + * the machine, but sometimes it might be necessary to give it a hint + * (let say if there is a known bug in the most recent tools version). + * Example: 28.0.3 + * + * @param version The build tools version to use. + * @return self instance for chaining. + */ + default T setBuildToolsVersion(String version) { + return amend(BUILD_TOOLS_VERSION_OPTION, version); + } + + /** + * Get the version of Android build tools to use. + * + * @return Build tools version. + */ + default Optional getBuildToolsVersion() { + return Optional.ofNullable((String) getCapability(BUILD_TOOLS_VERSION_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsClearDeviceLogsOnStartOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsClearDeviceLogsOnStartOption.java new file mode 100644 index 000000000..f48891388 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsClearDeviceLogsOnStartOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsClearDeviceLogsOnStartOption> extends + Capabilities, CanSetCapability { + String CLEAR_DEVICE_LOGS_ON_START_OPTION = "clearDeviceLogsOnStart"; + + /** + * Makes UiAutomator2 to delete all the existing logs in the + * device buffer before starting a new test. + * + * @return self instance for chaining. + */ + default T clearDeviceLogsOnStart() { + return amend(CLEAR_DEVICE_LOGS_ON_START_OPTION, true); + } + + + /** + * If set to true then UiAutomator2 deletes all the existing logs in the + * device buffer before starting a new test. + * + * @param value Set to false if you don't want to wait for the app to finish its launch. + * @return self instance for chaining. + */ + default T setClearDeviceLogsOnStart(boolean value) { + return amend(CLEAR_DEVICE_LOGS_ON_START_OPTION, value); + } + + /** + * Get whether to delete all the existing logs in the + * device buffer before starting a new test. + * + * @return True or false. + */ + default Optional doesClearDeviceLogsOnStart() { + return Optional.ofNullable(toSafeBoolean(getCapability(CLEAR_DEVICE_LOGS_ON_START_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsIgnoreHiddenApiPolicyErrorOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsIgnoreHiddenApiPolicyErrorOption.java new file mode 100644 index 000000000..29999e21d --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsIgnoreHiddenApiPolicyErrorOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsIgnoreHiddenApiPolicyErrorOption> extends + Capabilities, CanSetCapability { + String IGNORE_HIDDEN_API_POLICY_ERROR_OPTION = "ignoreHiddenApiPolicyError"; + + /** + * Prevents the driver from ever killing the ADB server explicitl. + * + * @return self instance for chaining. + */ + default T ignoreHiddenApiPolicyError() { + return amend(IGNORE_HIDDEN_API_POLICY_ERROR_OPTION, true); + } + + /** + * Being set to true ignores a failure while changing hidden API access policies. + * Could be useful on some devices, where access to these policies has been locked by its vendor. + * false by default. + * + * @param value Whether to ignore a failure while changing hidden API access policies. + * @return self instance for chaining. + */ + default T setIgnoreHiddenApiPolicyError(boolean value) { + return amend(IGNORE_HIDDEN_API_POLICY_ERROR_OPTION, value); + } + + /** + * Get whether to ignore a failure while changing hidden API access policies. + * + * @return True or false. + */ + default Optional doesIgnoreHiddenApiPolicyError() { + return Optional.ofNullable(toSafeBoolean(getCapability(IGNORE_HIDDEN_API_POLICY_ERROR_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java new file mode 100644 index 000000000..6aca7a15e --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsLogcatFilterSpecsOption> extends + Capabilities, CanSetCapability { + String LOGCAT_FILTER_SPECS_OPTION = "logcatFilterSpecs"; + + /** + * Series of tag[:priority] where tag is a log component tag (or * for all) + * and priority is: V Verbose, D Debug, I Info, W Warn, E Error, F Fatal, + * S Silent (supress all output). '' means ':d' and tag by itself means tag:v. + * If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS. + * If no filterspec is found, filter defaults to '*:I'. + * + * @param format The filter specifier. + * @return self instance for chaining. + */ + default T setLogcatFilterSpecs(String format) { + return amend(LOGCAT_FILTER_SPECS_OPTION, format); + } + + /** + * Get the logcat filter format. + * + * @return Format specifier. + */ + default Optional getLogcatFilterSpecs() { + return Optional.ofNullable((String) getCapability(LOGCAT_FILTER_SPECS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFormatOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFormatOption.java new file mode 100644 index 000000000..98302419e --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFormatOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsLogcatFormatOption> extends + Capabilities, CanSetCapability { + String LOGCAT_FORMAT_OPTION = "logcatFormat"; + + /** + * The log print format, where format is one of: brief process tag thread raw time + * threadtime long. threadtime is the default value. + * + * @param format The format specifier. + * @return self instance for chaining. + */ + default T setLogcatFormat(String format) { + return amend(LOGCAT_FORMAT_OPTION, format); + } + + /** + * Get the log print format. + * + * @return Format specifier. + */ + default Optional getLogcatFormat() { + return Optional.ofNullable((String) getCapability(LOGCAT_FORMAT_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsMockLocationAppOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsMockLocationAppOption.java new file mode 100644 index 000000000..e0b690f38 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsMockLocationAppOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsMockLocationAppOption> extends + Capabilities, CanSetCapability { + String MOCK_LOCATION_APP_OPTION = "mockLocationApp"; + + /** + * Sets the package identifier of the app, which is used as a system mock location + * provider since Appium 1.18.0+. This capability has no effect on emulators. + * If the value is set to null or an empty string, then Appium will skip the mocked + * location provider setup procedure. Defaults to Appium Setting package + * identifier (io.appium.settings). + * + * @param appIdentifier The identifier of the mock location provider app. + * @return self instance for chaining. + */ + default T setMockLocationApp(String appIdentifier) { + return amend(MOCK_LOCATION_APP_OPTION, appIdentifier); + } + + /** + * Get the identifier of the app, which is used as a system mock location provider. + * + * @return App identifier. + */ + default Optional getMockLocationApp() { + return Optional.ofNullable((String) getCapability(MOCK_LOCATION_APP_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsRemoteAdbHostOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsRemoteAdbHostOption.java new file mode 100644 index 000000000..6e8c94a1d --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsRemoteAdbHostOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsRemoteAdbHostOption> extends + Capabilities, CanSetCapability { + String REMOTE_ADB_HOST_OPTION = "remoteAdbHost"; + + /** + * Address of the host where ADB is running (the value of -H ADB command line option). + * Localhost by default. + * + * @param host The name host where ADB server is running. + * @return self instance for chaining. + */ + default T setRemoteAdbHost(String host) { + return amend(REMOTE_ADB_HOST_OPTION, host); + } + + /** + * Get the address of the host where ADB is running. + * + * @return Host name. + */ + default Optional getRemoteAdbHost() { + return Optional.ofNullable((String) getCapability(REMOTE_ADB_HOST_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsSkipLogcatCaptureOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsSkipLogcatCaptureOption.java new file mode 100644 index 000000000..1bd0f6b42 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsSkipLogcatCaptureOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSkipLogcatCaptureOption> extends + Capabilities, CanSetCapability { + String SKIP_LOGCAT_CAPTURE_OPTION = "skipLogcatCapture"; + + /** + * Disables automatic logcat output collection during the test run. + * + * @return self instance for chaining. + */ + default T skipLogcatCapture() { + return amend(SKIP_LOGCAT_CAPTURE_OPTION, true); + } + + /** + * Being set to true disables automatic logcat output collection during the test run. + * false by default + * + * @param value Whether to delete all the existing device logs before starting a new test. + * @return self instance for chaining. + */ + default T setSkipLogcatCapture(boolean value) { + return amend(SKIP_LOGCAT_CAPTURE_OPTION, value); + } + + /** + * Get whether to delete all the existing logs in the + * device buffer before starting a new test. + * + * @return True or false. + */ + default Optional doesSkipLogcatCapture() { + return Optional.ofNullable(toSafeBoolean(getCapability(SKIP_LOGCAT_CAPTURE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsSuppressKillServerOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsSuppressKillServerOption.java new file mode 100644 index 000000000..daaa9666b --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsSuppressKillServerOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.adb; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSuppressKillServerOption> extends + Capabilities, CanSetCapability { + String SUPPRESS_KILL_SERVER_OPTION = "suppressKillServer"; + + /** + * Prevents the driver from ever killing the ADB server explicitl. + * + * @return self instance for chaining. + */ + default T suppressKillServer() { + return amend(SUPPRESS_KILL_SERVER_OPTION, true); + } + + /** + * Being set to true prevents the driver from ever killing the ADB server explicitly. + * Could be useful if ADB is connected wirelessly. false by default. + * + * @param value Whether to prevent the driver from ever killing the ADB server explicitly. + * @return self instance for chaining. + */ + default T setSuppressKillServer(boolean value) { + return amend(SUPPRESS_KILL_SERVER_OPTION, value); + } + + /** + * Get whether to prevent the driver from ever killing the ADB server explicitly. + * + * @return True or false. + */ + default Optional doesSuppressKillServer() { + return Optional.ofNullable(toSafeBoolean(getCapability(SUPPRESS_KILL_SERVER_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java new file mode 100644 index 000000000..7843393e4 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.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.android.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.internal.Either; + +import java.util.List; +import java.util.Optional; + +public interface SupportsAvdArgsOption> extends + Capabilities, CanSetCapability { + String AVD_ARGS_OPTION = "avdArgs"; + + /** + * Set emulator command line arguments. + * + * @param args Emulator command line arguments. + * @return self instance for chaining. + */ + default T setAvdArgs(List args) { + return amend(AVD_ARGS_OPTION, args); + } + + /** + * Set emulator command line arguments. + * + * @param args Emulator command line arguments. + * @return self instance for chaining. + */ + default T setAvdArgs(String args) { + return amend(AVD_ARGS_OPTION, args); + } + + /** + * Get emulator command line arguments. + * + * @return Either arguments list of command line string. + */ + default Optional, String>> getAvdArgs() { + //noinspection unchecked + return Optional.ofNullable(getCapability(AVD_ARGS_OPTION)) + .map((v) -> v instanceof List + ? Either.left((List) v) + : Either.right(String.valueOf(v)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java new file mode 100644 index 000000000..e6d083aee --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsAvdEnvOption> extends + Capabilities, CanSetCapability { + String AVD_ENV_OPTION = "avdEnv"; + + /** + * Set the mapping of emulator environment variables. + * + * @param env Emulator environment variables mapping. + * @return self instance for chaining. + */ + default T setAvdEnv(Map env) { + return amend(AVD_ENV_OPTION, env); + } + + /** + * Get the mapping of emulator environment variables. + * + * @return Emulator environment variables mapping. + */ + default Optional> getAvdEnv() { + //noinspection unchecked + return Optional.ofNullable(getCapability(AVD_ENV_OPTION)) + .map((v) -> (Map) v); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdLaunchTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdLaunchTimeoutOption.java new file mode 100644 index 000000000..974b02203 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdLaunchTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsAvdLaunchTimeoutOption> extends + Capabilities, CanSetCapability { + String AVD_LAUNCH_TIMEOUT_OPTION = "avdLaunchTimeout"; + + /** + * Maximum timeout to wait until Android Emulator is started. + * 60000 ms by default. + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setAvdLaunchTimeout(Duration timeout) { + return amend(AVD_LAUNCH_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait until Android Emulator is started. + * + * @return The timeout value. + */ + default Optional getAvdLaunchTimeout() { + return Optional.ofNullable( + toDuration(getCapability(AVD_LAUNCH_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdOption.java new file mode 100644 index 000000000..8eac74bd4 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAvdOption> extends + Capabilities, CanSetCapability { + String AVD_OPTION = "avd"; + + /** + * The name of Android emulator to run the test on. + * The names of currently installed emulators could be listed using + * avdmanager list avd command. If the emulator with the given name + * is not running then it is going to be started before a test. + * + * @param avd The emulator name to use. + * @return self instance for chaining. + */ + default T setAvd(String avd) { + return amend(AVD_OPTION, avd); + } + + /** + * Get the name of Android emulator to run the test on. + * + * @return Emulator name. + */ + default Optional getAvd() { + return Optional.ofNullable((String) getCapability(AVD_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdReadyTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdReadyTimeoutOption.java new file mode 100644 index 000000000..68f1e27f2 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdReadyTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsAvdReadyTimeoutOption> extends + Capabilities, CanSetCapability { + String AVD_READY_TIMEOUT_OPTION = "avdReadyTimeout"; + + /** + * Maximum timeout to wait until Android Emulator is fully booted and is ready for usage. + * 60000 ms by default + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setAvdReadyTimeout(Duration timeout) { + return amend(AVD_READY_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait until Android Emulator is fully booted and is ready for usage. + * + * @return The timeout value. + */ + default Optional getAvdReadyTimeout() { + return Optional.ofNullable( + toDuration(getCapability(AVD_READY_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsGpsEnabledOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsGpsEnabledOption.java new file mode 100644 index 000000000..91dce65da --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsGpsEnabledOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsGpsEnabledOption> extends + Capabilities, CanSetCapability { + String GPS_ENABLED_OPTION = "gpsEnabled"; + + /** + * Enables GPS service in the Emulator. + * Unset by default, which means to not change the current value. + * + * @return self instance for chaining. + */ + default T gpsEnabled() { + return amend(GPS_ENABLED_OPTION, true); + } + + /** + * Sets whether to enable (true) or disable (false) GPS service in the Emulator. + * Unset by default, which means to not change the current value. + * + * @param value Whether to enable or disable the GPS service. + * @return self instance for chaining. + */ + default T setGpsEnabled(boolean value) { + return amend(GPS_ENABLED_OPTION, value); + } + + /** + * Get the state of GPS service on emulator. + * + * @return True or false. + */ + default Optional getGpsEnabled() { + return Optional.ofNullable(toSafeBoolean(getCapability(GPS_ENABLED_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java new file mode 100644 index 000000000..ee365c801 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsIsHeadlessOption> extends + Capabilities, CanSetCapability { + String IS_HEADLESS_OPTION = "isHeadless"; + + /** + * Set emulator to start in headless mode (e.g. no UI is shown). + * It is only applied if the emulator is not running before the test starts. + * + * @return self instance for chaining. + */ + default T headless() { + return amend(IS_HEADLESS_OPTION, true); + } + + /** + * If set to true then emulator starts in headless mode (e.g. no UI is shown). + * It is only applied if the emulator is not running before the test starts. + * false by default. + * + * @param value Whether to enable or disable headless mode. + * @return self instance for chaining. + */ + default T setIsHeadless(boolean value) { + return amend(IS_HEADLESS_OPTION, value); + } + + /** + * Get whether the emulator starts in headless mode. + * + * @return True or false. + */ + default Optional isHeadless() { + return Optional.ofNullable(toSafeBoolean(getCapability(IS_HEADLESS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsNetworkSpeedOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsNetworkSpeedOption.java new file mode 100644 index 000000000..5a3d05b47 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsNetworkSpeedOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.avd; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsNetworkSpeedOption> extends + Capabilities, CanSetCapability { + String NETWORK_SPEED_OPTION = "networkSpeed"; + + /** + * Sets the desired network speed limit for the emulator. + * It is only applied if the emulator is not running before + * the test starts. See emulator command line arguments description + * for more details. + * + * @param speed Speed value. + * @return self instance for chaining. + */ + default T setNetworkSpeed(String speed) { + return amend(NETWORK_SPEED_OPTION, speed); + } + + /** + * Get the desired network speed limit for the emulator. + * + * @return Speed value. + */ + default Optional getNetworkSpeed() { + return Optional.ofNullable((String) getCapability(NETWORK_SPEED_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/localization/SupportsLocaleScriptOption.java b/src/main/java/io/appium/java_client/android/options/localization/SupportsLocaleScriptOption.java new file mode 100644 index 000000000..835c7d41d --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/localization/SupportsLocaleScriptOption.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.options.localization; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsLocaleScriptOption> extends + Capabilities, CanSetCapability { + String LOCALE_SCRIPT_OPTION = "localeScript"; + + /** + * Set canonical name of the locale to be set for the app under test, + * for example zh-Hans-CN. + * See https://developer.android.com/reference/java/util/Locale.html for more details. + * + * @param localeScript is the language abbreviation. + * @return this MobileOptions, for chaining. + */ + default T setLocaleScript(String localeScript) { + return amend(LOCALE_SCRIPT_OPTION, localeScript); + } + + /** + * Get canonical name of the locale to be set for the app under test. + * + * @return Locale script value. + */ + default Optional getLocaleScript() { + return Optional.ofNullable((String) getCapability(LOCALE_SCRIPT_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/signing/KeystoreConfig.java b/src/main/java/io/appium/java_client/android/options/signing/KeystoreConfig.java new file mode 100644 index 000000000..5ab0d78b6 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/signing/KeystoreConfig.java @@ -0,0 +1,29 @@ +/* + * 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.options.signing; + +import lombok.Data; +import lombok.ToString; + +@ToString() +@Data() +public class KeystoreConfig { + private final String path; + private final String password; + private final String keyAlias; + private final String keyPassword; +} diff --git a/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java b/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java new file mode 100644 index 000000000..4a79dbc67 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java @@ -0,0 +1,74 @@ +/* + * 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.options.signing; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsKeystoreOptions> extends + Capabilities, CanSetCapability { + String USE_KEYSTORE_OPTION = "useKeystore"; + String KEYSTORE_PATH_OPTION = "keystorePath"; + String KEYSTORE_PASSWORD_OPTION = "keystorePassword"; + String KEY_ALIAS_OPTION = "keyAlias"; + String KEY_PASSWORD_OPTION = "keyPassword"; + + /** + * Use a custom keystore to sign the app under test. + * + * @param keystoreConfig The keystore config to use. + * @return self instance for chaining. + */ + default T useKeystore(KeystoreConfig keystoreConfig) { + return amend(USE_KEYSTORE_OPTION, true) + .amend(KEYSTORE_PATH_OPTION, keystoreConfig.getPath()) + .amend(KEYSTORE_PASSWORD_OPTION, keystoreConfig.getPassword()) + .amend(KEY_ALIAS_OPTION, keystoreConfig.getKeyAlias()) + .amend(KEY_PASSWORD_OPTION, keystoreConfig.getKeyPassword()); + } + + /** + * Get whether to use a custom keystore. + * + * @return True or false. + */ + default Optional doesUseKeystore() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_KEYSTORE_OPTION))); + } + + /** + * Get the custom keystore config. + * + * @return The keystore config. + */ + default Optional getKeystoreConfig() { + if (!doesUseKeystore().orElse(false)) { + return Optional.empty(); + } + return Optional.of(new KeystoreConfig( + (String) getCapability(KEYSTORE_PATH_OPTION), + (String) getCapability(KEYSTORE_PASSWORD_OPTION), + (String) getCapability(KEY_ALIAS_OPTION), + (String) getCapability(KEY_PASSWORD_OPTION) + )); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/signing/SupportsNoSignOption.java b/src/main/java/io/appium/java_client/android/options/signing/SupportsNoSignOption.java new file mode 100644 index 000000000..9518d7b8f --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/signing/SupportsNoSignOption.java @@ -0,0 +1,63 @@ +/* + * 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.options.signing; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsNoSignOption> extends + Capabilities, CanSetCapability { + String NO_SIGN_OPTION = "noSign"; + + /** + * Skips application signing. + * + * @return self instance for chaining. + */ + default T noSign() { + return amend(NO_SIGN_OPTION, true); + } + + /** + * Set it to true in order to skip application signing. By default, + * all apps are always signed with the default Appium debug signature + * if they don't have any. This capability cancels all the signing checks + * and makes the driver to use the application package as is. This + * capability does not affect .apks packages as these are expected to be + * already signed. + * + * @param value Whether to skip package signing. + * @return self instance for chaining. + */ + default T setNoSign(boolean value) { + return amend(NO_SIGN_OPTION, value); + } + + /** + * Get whether to skip package signing. + * + * @return True or false. + */ + default Optional doesNoSign() { + return Optional.ofNullable(toSafeBoolean(getCapability(NO_SIGN_OPTION))); + } +} From 69c7d3a0a692898f4043305697ee4257836e28e1 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 26 Oct 2021 04:42:06 +0200 Subject: [PATCH 006/501] chore: Finish creating options for UiAutomator2 driver (#1548) * chore: Finish creating options for UiAutomator2 driver * Tune caps cloning * Fix style * Update merge implementation * Simplify merge --- .../android/options/UiAutomator2Options.java | 67 ++++++++++++++++-- .../SupportsAutoWebviewTimeoutOption.java | 53 ++++++++++++++ .../SupportsChromeLoggingPrefsOption.java | 52 ++++++++++++++ .../context/SupportsChromeOptionsOption.java | 51 ++++++++++++++ .../SupportsChromedriverArgsOption.java | 52 ++++++++++++++ ...tsChromedriverChromeMappingFileOption.java | 52 ++++++++++++++ ...tsChromedriverDisableBuildCheckOption.java | 62 ++++++++++++++++ ...pportsChromedriverExecutableDirOption.java | 52 ++++++++++++++ .../SupportsChromedriverExecutableOption.java | 47 +++++++++++++ .../SupportsChromedriverPortOption.java | 50 +++++++++++++ .../SupportsChromedriverPortsOption.java | 50 +++++++++++++ ...ChromedriverUseSystemExecutableOption.java | 61 ++++++++++++++++ ...SupportsEnsureWebviewsHavePagesOption.java | 60 ++++++++++++++++ ...meAndroidPackageFromContextNameOption.java | 64 +++++++++++++++++ .../SupportsNativeWebScreenshotOption.java | 61 ++++++++++++++++ ...rtsRecreateChromeDriverSessionsOption.java | 62 ++++++++++++++++ .../SupportsShowChromedriverLogOption.java | 62 ++++++++++++++++ .../SupportsWebviewDevtoolsPortOption.java | 51 ++++++++++++++ .../locking/SupportsSkipUnlockOption.java | 62 ++++++++++++++++ .../locking/SupportsUnlockKeyOption.java | 49 +++++++++++++ .../locking/SupportsUnlockStrategyOption.java | 49 +++++++++++++ .../SupportsUnlockSuccessTimeoutOption.java | 53 ++++++++++++++ .../locking/SupportsUnlockTypeOption.java | 49 +++++++++++++ .../SupportsMjpegScreenshotUrlOption.java | 70 +++++++++++++++++++ .../mjpeg/SupportsMjpegServerPortOption.java | 52 ++++++++++++++ ...bleSuppressAccessibilityServiceOption.java | 63 +++++++++++++++++ .../other/SupportsSkipLogCaptureOption.java | 59 ++++++++++++++++ .../other/SupportsUserProfileOption.java | 53 ++++++++++++++ .../java_client/remote/MobileBrowserType.java | 2 +- .../remote/options/BaseOptions.java | 41 +++++++++-- .../service/local/AppiumServiceBuilder.java | 33 ++++----- .../java_client/android/BaseAndroidTest.java | 16 ++--- .../service/local/StartingAppLocallyTest.java | 68 +++++++++--------- 33 files changed, 1648 insertions(+), 80 deletions(-) create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsAutoWebviewTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromeLoggingPrefsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromeOptionsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverArgsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverChromeMappingFileOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverDisableBuildCheckOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableDirOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverUseSystemExecutableOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsEnsureWebviewsHavePagesOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsExtractChromeAndroidPackageFromContextNameOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsNativeWebScreenshotOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsRecreateChromeDriverSessionsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/context/SupportsWebviewDevtoolsPortOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/locking/SupportsSkipUnlockOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockKeyOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockStrategyOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockSuccessTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockTypeOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegServerPortOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/other/SupportsDisableSuppressAccessibilityServiceOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/other/SupportsUserProfileOption.java diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index f13dda020..9185994f1 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -52,7 +52,34 @@ import io.appium.java_client.android.options.avd.SupportsGpsEnabledOption; import io.appium.java_client.android.options.avd.SupportsIsHeadlessOption; import io.appium.java_client.android.options.avd.SupportsNetworkSpeedOption; +import io.appium.java_client.android.options.context.SupportsAutoWebviewTimeoutOption; +import io.appium.java_client.android.options.context.SupportsChromeLoggingPrefsOption; +import io.appium.java_client.android.options.context.SupportsChromeOptionsOption; +import io.appium.java_client.android.options.context.SupportsChromedriverArgsOption; +import io.appium.java_client.android.options.context.SupportsChromedriverChromeMappingFileOption; +import io.appium.java_client.android.options.context.SupportsChromedriverDisableBuildCheckOption; +import io.appium.java_client.android.options.context.SupportsChromedriverExecutableDirOption; +import io.appium.java_client.android.options.context.SupportsChromedriverExecutableOption; +import io.appium.java_client.android.options.context.SupportsChromedriverPortOption; +import io.appium.java_client.android.options.context.SupportsChromedriverPortsOption; +import io.appium.java_client.android.options.context.SupportsChromedriverUseSystemExecutableOption; +import io.appium.java_client.android.options.context.SupportsEnsureWebviewsHavePagesOption; +import io.appium.java_client.android.options.context.SupportsExtractChromeAndroidPackageFromContextNameOption; +import io.appium.java_client.android.options.context.SupportsNativeWebScreenshotOption; +import io.appium.java_client.android.options.context.SupportsRecreateChromeDriverSessionsOption; +import io.appium.java_client.android.options.context.SupportsShowChromedriverLogOption; +import io.appium.java_client.android.options.context.SupportsWebviewDevtoolsPortOption; import io.appium.java_client.android.options.localization.SupportsLocaleScriptOption; +import io.appium.java_client.android.options.locking.SupportsSkipUnlockOption; +import io.appium.java_client.android.options.locking.SupportsUnlockKeyOption; +import io.appium.java_client.android.options.locking.SupportsUnlockStrategyOption; +import io.appium.java_client.android.options.locking.SupportsUnlockSuccessTimeoutOption; +import io.appium.java_client.android.options.locking.SupportsUnlockTypeOption; +import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption; +import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption; +import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption; +import io.appium.java_client.android.options.other.SupportsSkipLogCaptureOption; +import io.appium.java_client.android.options.other.SupportsUserProfileOption; import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption; import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption; import io.appium.java_client.android.options.server.SupportsSkipServerInstallationOption; @@ -81,12 +108,6 @@ * https://github.com/appium/appium-uiautomator2-driver#capabilities */ public class UiAutomator2Options extends BaseOptions implements - // TODO: Device locking options: https://github.com/appium/appium-uiautomator2-driver#device-locking - // TODO: MJPEG options: https://github.com/appium/appium-uiautomator2-driver#mjpeg - // TODO: Web Context options: https://github.com/appium/appium-uiautomator2-driver#web-context - // TODO: Other options: https://github.com/appium/appium-uiautomator2-driver#other - // TODO: Shared options - SupportsAutoWebViewOption, // General options: https://github.com/appium/appium-uiautomator2-driver#general SupportsDeviceNameOption, SupportsUdidOption, @@ -148,7 +169,39 @@ public class UiAutomator2Options extends BaseOptions implem SupportsIsHeadlessOption, // App signing options: https://github.com/appium/appium-uiautomator2-driver#app-signing SupportsKeystoreOptions, - SupportsNoSignOption { + SupportsNoSignOption, + // Device locking options: https://github.com/appium/appium-uiautomator2-driver#device-locking + SupportsSkipUnlockOption, + SupportsUnlockTypeOption, + SupportsUnlockKeyOption, + SupportsUnlockStrategyOption, + SupportsUnlockSuccessTimeoutOption, + // MJPEG options: https://github.com/appium/appium-uiautomator2-driver#mjpeg + SupportsMjpegServerPortOption, + SupportsMjpegScreenshotUrlOption, + // Web Context options: https://github.com/appium/appium-uiautomator2-driver#web-context + SupportsAutoWebViewOption, + SupportsWebviewDevtoolsPortOption, + SupportsEnsureWebviewsHavePagesOption, + SupportsChromedriverPortOption, + SupportsChromedriverPortsOption, + SupportsChromedriverArgsOption, + SupportsChromedriverExecutableOption, + SupportsChromedriverExecutableDirOption, + SupportsChromedriverChromeMappingFileOption, + SupportsChromedriverUseSystemExecutableOption, + SupportsChromedriverDisableBuildCheckOption, + SupportsAutoWebviewTimeoutOption, + SupportsRecreateChromeDriverSessionsOption, + SupportsNativeWebScreenshotOption, + SupportsExtractChromeAndroidPackageFromContextNameOption, + SupportsShowChromedriverLogOption, + SupportsChromeOptionsOption, + SupportsChromeLoggingPrefsOption, + // Other options: https://github.com/appium/appium-uiautomator2-driver#other + SupportsDisableSuppressAccessibilityServiceOption, + SupportsUserProfileOption, + SupportsSkipLogCaptureOption { public UiAutomator2Options() { setCommonOptions(); } diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsAutoWebviewTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsAutoWebviewTimeoutOption.java new file mode 100644 index 000000000..0f0a07967 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsAutoWebviewTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsAutoWebviewTimeoutOption> extends + Capabilities, CanSetCapability { + String AUTO_WEBVIEW_TIMEOUT_OPTION = "autoWebviewTimeout"; + + /** + * Set the maximum timeout to wait until a web view is + * available if autoWebview capability is set to true. 2000 ms by default. + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setAutoWebviewTimeout(Duration timeout) { + return amend(AUTO_WEBVIEW_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait until a web view is available. + * + * @return The timeout value. + */ + default Optional getAutoWebviewTimeout() { + return Optional.ofNullable( + toDuration(getCapability(AUTO_WEBVIEW_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromeLoggingPrefsOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromeLoggingPrefsOption.java new file mode 100644 index 000000000..f47f4d865 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromeLoggingPrefsOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsChromeLoggingPrefsOption> extends + Capabilities, CanSetCapability { + String CHROME_LOGGING_PREFS_OPTION = "chromeLoggingPrefs"; + + /** + * Chrome logging preferences mapping. Basically the same as + * [goog:loggingPrefs](https://newbedev.com/ + * getting-console-log-output-from-chrome-with-selenium-python-api-bindings). + * It is set to {"browser": "ALL"} by default. + * + * @param opts Chrome logging preferences. + * @return self instance for chaining. + */ + default T setChromeLoggingPrefs(Map opts) { + return amend(CHROME_LOGGING_PREFS_OPTION, opts); + } + + /** + * Get chrome logging preferences. + * + * @return Chrome logging preferences. + */ + default Optional> getChromeLoggingPrefs() { + //noinspection unchecked + return Optional.ofNullable((Map) getCapability(CHROME_LOGGING_PREFS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromeOptionsOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromeOptionsOption.java new file mode 100644 index 000000000..955a6c2a7 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromeOptionsOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsChromeOptionsOption> extends + Capabilities, CanSetCapability { + String CHROME_OPTIONS_OPTION = "chromeOptions"; + + /** + * A mapping, that allows to customize chromedriver options. + * See https://chromedriver.chromium.org/capabilities for the list + * of available entries. + * + * @param opts Chrome options. + * @return self instance for chaining. + */ + default T setChromeOptions(Map opts) { + return amend(CHROME_OPTIONS_OPTION, opts); + } + + /** + * Get chrome options. + * + * @return Chrome options. + */ + default Optional> getChromeOptions() { + //noinspection unchecked + return Optional.ofNullable((Map) getCapability(CHROME_OPTIONS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverArgsOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverArgsOption.java new file mode 100644 index 000000000..227088b35 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverArgsOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.List; +import java.util.Optional; + +public interface SupportsChromedriverArgsOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_ARGS_OPTION = "chromedriverArgs"; + + /** + * Array of chromedriver [command line + * arguments](http://www.assertselenium.com/java/list-of-chrome-driver-command-line-arguments/). + * Note, that not all command line arguments that are available for the desktop + * browser are also available for the mobile one. + * + * @param args Chromedriver command line arguments. + * @return self instance for chaining. + */ + default T setChromedriverArgs(List args) { + return amend(CHROMEDRIVER_ARGS_OPTION, args); + } + + /** + * Get the array of chromedriver CLI arguments. + * + * @return Arguments list. + */ + default Optional> getChromedriverArgs() { + //noinspection unchecked + return Optional.ofNullable((List) getCapability(CHROMEDRIVER_ARGS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverChromeMappingFileOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverChromeMappingFileOption.java new file mode 100644 index 000000000..83faaef42 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverChromeMappingFileOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsChromedriverChromeMappingFileOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_CHROME_MAPPING_FILE_OPTION = "chromedriverChromeMappingFile"; + + /** + * Full path to the chromedrivers mapping file. This file is used to statically + * map webview/browser versions to the chromedriver versions that are capable + * of automating them. Read [Automatic Chromedriver Discovery](https://github.com/ + * appium/appium/blob/master/docs/en/writing-running-appium/web/ + * chromedriver.md#automatic-discovery-of-compatible-chromedriver) + * article for more details. + * + * @param path Path to chromedrivers mapping file. + * @return self instance for chaining. + */ + default T setChromedriverChromeMappingFile(String path) { + return amend(CHROMEDRIVER_CHROME_MAPPING_FILE_OPTION, path); + } + + /** + * Get full path to the chromedrivers mapping file is located. + * + * @return Path to chromedrivers mapping file. + */ + default Optional getChromedriverChromeMappingFile() { + return Optional.ofNullable((String) getCapability(CHROMEDRIVER_CHROME_MAPPING_FILE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverDisableBuildCheckOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverDisableBuildCheckOption.java new file mode 100644 index 000000000..7757b0ed3 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverDisableBuildCheckOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsChromedriverDisableBuildCheckOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_DISABLE_BUILD_CHECK_OPTION = "chromedriverDisableBuildCheck"; + + /** + * Disables the compatibility validation between the current chromedriver + * and the destination browser/web view. + * + * @return self instance for chaining. + */ + default T chromedriverDisableBuildCheck() { + return amend(CHROMEDRIVER_DISABLE_BUILD_CHECK_OPTION, true); + } + + /** + * Being set to true disables the compatibility validation between the current + * chromedriver and the destination browser/web view. Use it with care. + * false by default. + * + * @param value Whether to enable the validation. + * @return self instance for chaining. + */ + default T setChromedriverDisableBuildCheck(boolean value) { + return amend(CHROMEDRIVER_DISABLE_BUILD_CHECK_OPTION, value); + } + + /** + * Get whether to disable the compatibility validation between the current + * chromedriver and the destination browser/web view. + * + * @return True or false. + */ + default Optional doesChromedriverDisableBuildCheck() { + return Optional.ofNullable(toSafeBoolean(getCapability(CHROMEDRIVER_DISABLE_BUILD_CHECK_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableDirOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableDirOption.java new file mode 100644 index 000000000..994021a5f --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableDirOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsChromedriverExecutableDirOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_EXECUTABLE_DIR_OPTION = "chromedriverExecutableDir"; + + /** + * Full path to the folder where chromedriver executables are located. + * This folder is used then to store the downloaded chromedriver executables + * if automatic download is enabled. Read [Automatic Chromedriver + * Discovery](https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ + * web/chromedriver.md#automatic-discovery-of-compatible-chromedriver) + * article for more details. + * + * @param path Path to chromedriver executable. + * @return self instance for chaining. + */ + default T setChromedriverExecutableDir(String path) { + return amend(CHROMEDRIVER_EXECUTABLE_DIR_OPTION, path); + } + + /** + * Get full path to the folder where chromedriver executables are located. + * + * @return Path to chromedriver executable dir. + */ + default Optional getChromedriverExecutableDir() { + return Optional.ofNullable((String) getCapability(CHROMEDRIVER_EXECUTABLE_DIR_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableOption.java new file mode 100644 index 000000000..4f73b42a2 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverExecutableOption.java @@ -0,0 +1,47 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsChromedriverExecutableOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_EXECUTABLE_OPTION = "chromedriverExecutable"; + + /** + * Full path to the chromedriver executable on the server file system. + * + * @param path Path to chromedriver executable. + * @return self instance for chaining. + */ + default T setChromedriverExecutable(String path) { + return amend(CHROMEDRIVER_EXECUTABLE_OPTION, path); + } + + /** + * Get the path to the chromedriver executable on the server file system.. + * + * @return Path to chromedriver executable. + */ + default Optional getChromedriverExecutable() { + return Optional.ofNullable((String) getCapability(CHROMEDRIVER_EXECUTABLE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortOption.java new file mode 100644 index 000000000..fa6cc1f5a --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsChromedriverPortOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_PORT_OPTION = "chromedriverPort"; + + /** + * The port number to use for Chromedriver communication. + * Any free port number is selected by default if unset. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setChromedriverPort(int port) { + return amend(CHROMEDRIVER_PORT_OPTION, port); + } + + /** + * Get the local port number to use for Chromedriver communication. + * + * @return Port number. + */ + default Optional getChromedriverPort() { + return Optional.ofNullable(toInteger(getCapability(CHROMEDRIVER_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortsOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortsOption.java new file mode 100644 index 000000000..eb0a4630c --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverPortsOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.List; +import java.util.Optional; + +public interface SupportsChromedriverPortsOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_PORTS_OPTION = "chromedriverPorts"; + + /** + * Array of possible port numbers to assign for Chromedriver communication. + * If none of the port in this array is free then a server error is thrown. + * + * @param ports one or more port numbers in range 0..65535 + * @return self instance for chaining. + */ + default T setChromedriverPorts(List ports) { + return amend(CHROMEDRIVER_PORTS_OPTION, ports); + } + + /** + * Get the local port number to use for Chromedriver communication. + * + * @return Port number. + */ + default Optional> getChromedriverPorts() { + //noinspection unchecked + return Optional.ofNullable((List) getCapability(CHROMEDRIVER_PORTS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverUseSystemExecutableOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverUseSystemExecutableOption.java new file mode 100644 index 000000000..62e653cb0 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsChromedriverUseSystemExecutableOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsChromedriverUseSystemExecutableOption> extends + Capabilities, CanSetCapability { + String CHROMEDRIVER_USE_SYSTEM_EXECUTABLE_OPTION = "chromedriverUseSystemExecutable"; + + /** + * Enforce the usage of chromedriver, + * which gets downloaded by Appium automatically upon installation. + * + * @return self instance for chaining. + */ + default T chromedriverUseSystemExecutable() { + return amend(CHROMEDRIVER_USE_SYSTEM_EXECUTABLE_OPTION, true); + } + + /** + * Set it to true in order to enforce the usage of chromedriver, which gets + * downloaded by Appium automatically upon installation. This driver might not + * be compatible with the destination browser or a web view. false by default. + * + * @param value Whether to use the system chromedriver. + * @return self instance for chaining. + */ + default T setChromedriverUseSystemExecutable(boolean value) { + return amend(CHROMEDRIVER_USE_SYSTEM_EXECUTABLE_OPTION, value); + } + + /** + * Get whether to use the system chromedriver. + * + * @return True or false. + */ + default Optional doesChromedriverUseSystemExecutable() { + return Optional.ofNullable(toSafeBoolean(getCapability(CHROMEDRIVER_USE_SYSTEM_EXECUTABLE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsEnsureWebviewsHavePagesOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsEnsureWebviewsHavePagesOption.java new file mode 100644 index 000000000..d72cbe066 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsEnsureWebviewsHavePagesOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsEnsureWebviewsHavePagesOption> extends + Capabilities, CanSetCapability { + String ENSURE_WEBVIEWS_HAVE_PAGES_OPTION = "ensureWebviewsHavePages"; + + /** + * Set to skip web views that have no pages from being shown in getContexts output. + * + * @return self instance for chaining. + */ + default T ensureWebviewsHavePages() { + return amend(ENSURE_WEBVIEWS_HAVE_PAGES_OPTION, true); + } + + /** + * Whether to skip web views that have no pages from being shown in getContexts + * output. The driver uses devtools connection to retrieve the information about + * existing pages. true by default since Appium 1.19.0, false if lower than 1.19.0. + * + * @param value Whether to ensure if web views have pages. + * @return self instance for chaining. + */ + default T setEnsureWebviewsHavePages(boolean value) { + return amend(ENSURE_WEBVIEWS_HAVE_PAGES_OPTION, value); + } + + /** + * Get whether to ensure if web views have pages. + * + * @return True or false. + */ + default Optional doesEnsureWebviewsHavePages() { + return Optional.ofNullable(toSafeBoolean(getCapability(ENSURE_WEBVIEWS_HAVE_PAGES_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsExtractChromeAndroidPackageFromContextNameOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsExtractChromeAndroidPackageFromContextNameOption.java new file mode 100644 index 000000000..447a1f2f4 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsExtractChromeAndroidPackageFromContextNameOption.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.android.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsExtractChromeAndroidPackageFromContextNameOption + > extends Capabilities, CanSetCapability { + String EXTRACT_CHROME_ANDROID_PACKAGE_FROM_CONTEXT_NAME_OPTION = + "extractChromeAndroidPackageFromContextName"; + + /** + * Tell chromedriver to attach to the android package we have associated + * with the context name, rather than the package of the application under test. + * + * @return self instance for chaining. + */ + default T extractChromeAndroidPackageFromContextName() { + return amend(EXTRACT_CHROME_ANDROID_PACKAGE_FROM_CONTEXT_NAME_OPTION, true); + } + + /** + * If set to true, tell chromedriver to attach to the android package we have associated + * with the context name, rather than the package of the application under test. + * false by default. + * + * @param value Whether to use the android package identifier associated with the context name. + * @return self instance for chaining. + */ + default T setExtractChromeAndroidPackageFromContextName(boolean value) { + return amend(EXTRACT_CHROME_ANDROID_PACKAGE_FROM_CONTEXT_NAME_OPTION, value); + } + + /** + * Get whether to use the android package identifier associated with the context name. + * + * @return True or false. + */ + default Optional doesExtractChromeAndroidPackageFromContextName() { + return Optional.ofNullable( + toSafeBoolean(getCapability(EXTRACT_CHROME_ANDROID_PACKAGE_FROM_CONTEXT_NAME_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsNativeWebScreenshotOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsNativeWebScreenshotOption.java new file mode 100644 index 000000000..71e5934ff --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsNativeWebScreenshotOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsNativeWebScreenshotOption> extends + Capabilities, CanSetCapability { + String NATIVE_WEB_SCREENSHOT_OPTION = "nativeWebScreenshot"; + + /** + * Enforce to use screenshoting endpoint provided by UiAutomator framework + * rather than the one provided by chromedriver. + * + * @return self instance for chaining. + */ + default T nativeWebScreenshot() { + return amend(NATIVE_WEB_SCREENSHOT_OPTION, true); + } + + /** + * Whether to use screenshoting endpoint provided by UiAutomator framework (true) + * rather than the one provided by chromedriver (false, the default value). + * Use it when you experience issues with the latter. + * + * @param value Whether to use native screenshots in web view context. + * @return self instance for chaining. + */ + default T setNativeWebScreenshot(boolean value) { + return amend(NATIVE_WEB_SCREENSHOT_OPTION, value); + } + + /** + * Get whether to use native screenshots in web view context. + * + * @return True or false. + */ + default Optional doesNativeWebScreenshot() { + return Optional.ofNullable(toSafeBoolean(getCapability(NATIVE_WEB_SCREENSHOT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsRecreateChromeDriverSessionsOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsRecreateChromeDriverSessionsOption.java new file mode 100644 index 000000000..a47ade424 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsRecreateChromeDriverSessionsOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsRecreateChromeDriverSessionsOption> extends + Capabilities, CanSetCapability { + String RECREATE_CHROME_DRIVER_SESSIONS = "recreateChromeDriverSessions"; + + /** + * Enforce chromedriver sessions to be killed and then recreated instead + * of just suspending it on context switch. + * + * @return self instance for chaining. + */ + default T recreateChromeDriverSessions() { + return amend(RECREATE_CHROME_DRIVER_SESSIONS, true); + } + + /** + * If this capability is set to true then chromedriver session is always going + * to be killed and then recreated instead of just suspending it on context + * switching. false by default. + * + * @param value Whether to recreate chromedriver sessions. + * @return self instance for chaining. + */ + default T setRecreateChromeDriverSessions(boolean value) { + return amend(RECREATE_CHROME_DRIVER_SESSIONS, value); + } + + /** + * Get whether chromedriver sessions should be killed and then recreated instead + * of just suspending it on context switch. + * + * @return True or false. + */ + default Optional doesRecreateChromeDriverSessions() { + return Optional.ofNullable(toSafeBoolean(getCapability(RECREATE_CHROME_DRIVER_SESSIONS))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java new file mode 100644 index 000000000..d201069e5 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShowChromedriverLogOption> + extends Capabilities, CanSetCapability { + String SHOW_CHROMEDRIVER_LOG_OPTION = "showChromedriverLog"; + + /** + * Enforces all the output from chromedriver binary to be + * forwarded to the Appium server log. + * + * @return self instance for chaining. + */ + default T showChromedriverLog() { + return amend(SHOW_CHROMEDRIVER_LOG_OPTION, true); + } + + /** + * If set to true then all the output from chromedriver binary will be + * forwarded to the Appium server log. false by default. + * + * @param value Whether to forward chromedriver output to the Appium server log. + * @return self instance for chaining. + */ + default T setDhowChromedriverLog(boolean value) { + return amend(SHOW_CHROMEDRIVER_LOG_OPTION, value); + } + + /** + * Get whether to forward chromedriver output to the Appium server log. + * + * @return True or false. + */ + default Optional doesDhowChromedriverLog() { + return Optional.ofNullable( + toSafeBoolean(getCapability(SHOW_CHROMEDRIVER_LOG_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsWebviewDevtoolsPortOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsWebviewDevtoolsPortOption.java new file mode 100644 index 000000000..e48e73fad --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsWebviewDevtoolsPortOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.context; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsWebviewDevtoolsPortOption> extends + Capabilities, CanSetCapability { + String WEBVIEW_DEVTOOLS_PORT_OPTION = "webviewDevtoolsPort"; + + /** + * The local port number to use for devtools communication. By default, the first + * free port from 10900..11000 range is selected. Consider setting the custom + * value if you are running parallel tests. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setWebviewDevtoolsPort(int port) { + return amend(WEBVIEW_DEVTOOLS_PORT_OPTION, port); + } + + /** + * Get the local port number to use for devtools communication. + * + * @return Port number. + */ + default Optional getWebviewDevtoolsPort() { + return Optional.ofNullable(toInteger(getCapability(WEBVIEW_DEVTOOLS_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/locking/SupportsSkipUnlockOption.java b/src/main/java/io/appium/java_client/android/options/locking/SupportsSkipUnlockOption.java new file mode 100644 index 000000000..0846dddfe --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/locking/SupportsSkipUnlockOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.locking; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSkipUnlockOption> extends + Capabilities, CanSetCapability { + String SKIP_UNLOCK_OPTION = "skipUnlock"; + + /** + * Skip the check for lock screen presence. + * + * @return self instance for chaining. + */ + default T skipUnlock() { + return amend(SKIP_UNLOCK_OPTION, true); + } + + /** + * Whether to skip the check for lock screen presence (true). By default, + * UiAutomator2 driver tries to detect if the device's screen is locked + * before starting the test and to unlock that (which sometimes might be unstable). + * Note, that this operation takes some time, so it is highly recommended to set + * this capability to true and disable screen locking on devices under test. + * + * @param value Set it to true in order to skip screen unlock checks. + * @return self instance for chaining. + */ + default T setSkipUnlock(boolean value) { + return amend(SKIP_UNLOCK_OPTION, value); + } + + /** + * Get whether to skip the check for lock screen presence. + * + * @return True or false. + */ + default Optional doesSkipUnlock() { + return Optional.ofNullable(toSafeBoolean(getCapability(SKIP_UNLOCK_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockKeyOption.java b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockKeyOption.java new file mode 100644 index 000000000..011ca2c87 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockKeyOption.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.options.locking; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsUnlockKeyOption> extends + Capabilities, CanSetCapability { + String UNLOCK_KEY_OPTION = "unlockKey"; + + /** + * Allows to set an unlock key. + * Read [Unlock tutorial](https://github.com/appium/appium-android-driver/blob/master/docs/UNLOCK.md) + * for more details. + * + * @param unlockKey The unlock key. + * @return self instance for chaining. + */ + default T setUnlockKey(String unlockKey) { + return amend(UNLOCK_KEY_OPTION, unlockKey); + } + + /** + * Get the unlock key. + * + * @return Unlock key. + */ + default Optional getUnlockKey() { + return Optional.ofNullable((String) getCapability(UNLOCK_KEY_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockStrategyOption.java b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockStrategyOption.java new file mode 100644 index 000000000..6329d6861 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockStrategyOption.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.options.locking; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsUnlockStrategyOption> extends + Capabilities, CanSetCapability { + String UNLOCK_STRATEGY_OPTION = "unlockStrategy"; + + /** + * Either 'locksettings' (default) or 'uiautomator'. + * Setting it to 'uiautomator' will enforce the driver to avoid using special + * ADB shortcuts in order to speed up the unlock procedure. + * + * @param strategy The unlock strategy. + * @return self instance for chaining. + */ + default T setUnlockStrategy(String strategy) { + return amend(UNLOCK_STRATEGY_OPTION, strategy); + } + + /** + * Get the strategy key. + * + * @return Unlock strategy. + */ + default Optional getUnlockStrategy() { + return Optional.ofNullable((String) getCapability(UNLOCK_STRATEGY_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockSuccessTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockSuccessTimeoutOption.java new file mode 100644 index 000000000..487fbbdca --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockSuccessTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.locking; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsUnlockSuccessTimeoutOption> extends + Capabilities, CanSetCapability { + String UNLOCK_SUCCESS_TIMEOUT_OPTION = "unlockSuccessTimeout"; + + /** + * Maximum timeout to wait until the device is unlocked. + * 2000 ms by default. + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setUnlockSuccessTimeout(Duration timeout) { + return amend(UNLOCK_SUCCESS_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait until the device is unlocked. + * + * @return The timeout value. + */ + default Optional getUnlockSuccessTimeout() { + return Optional.ofNullable( + toDuration(getCapability(UNLOCK_SUCCESS_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockTypeOption.java b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockTypeOption.java new file mode 100644 index 000000000..76b749fef --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/locking/SupportsUnlockTypeOption.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.options.locking; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsUnlockTypeOption> extends + Capabilities, CanSetCapability { + String UNLOCK_TYPE_OPTION = "unlockType"; + + /** + * Set one of the possible types of Android lock screens to unlock. + * Read the [Unlock tutorial](https://github.com/appium/appium-android-driver/blob/master/docs/UNLOCK.md) + * for more details. + * + * @param unlockType One of possible unlock types. + * @return self instance for chaining. + */ + default T setUnlockType(String unlockType) { + return amend(UNLOCK_TYPE_OPTION, unlockType); + } + + /** + * Get the unlock type. + * + * @return Unlock type. + */ + default Optional getUnlockType() { + return Optional.ofNullable((String) getCapability(UNLOCK_TYPE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java b/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java new file mode 100644 index 000000000..bb78ed30a --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java @@ -0,0 +1,70 @@ +/* + * 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.options.mjpeg; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Optional; + +public interface SupportsMjpegScreenshotUrlOption> extends + Capabilities, CanSetCapability { + String MJPEG_SCREENSHOT_URL_OPTION = "mjpegScreenshotUrl"; + + /** + * The URL of a service that provides realtime device screenshots in MJPEG format. + * If provided then the actual command to retrieve a screenshot will be + * requesting pictures from this service rather than directly from the server. + * + * @param url URL value. + * @return self instance for chaining. + */ + default T setMjpegScreenshotUrl(URL url) { + return amend(MJPEG_SCREENSHOT_URL_OPTION, url.toString()); + } + + /** + * The URL of a service that provides realtime device screenshots in MJPEG format. + * If provided then the actual command to retrieve a screenshot will be + * requesting pictures from this service rather than directly from the server. + * + * @param url URL value. + * @return self instance for chaining. + */ + default T setMjpegScreenshotUrl(String url) { + return amend(MJPEG_SCREENSHOT_URL_OPTION, url); + } + + /** + * Get URL of a service that provides realtime device screenshots in MJPEG format. + * + * @return URL value. + */ + default Optional getMjpegScreenshotUrl() { + return Optional.ofNullable(getCapability(MJPEG_SCREENSHOT_URL_OPTION)) + .map((v) -> { + try { + return new URL(String.valueOf(v)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + }); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegServerPortOption.java b/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegServerPortOption.java new file mode 100644 index 000000000..2649a5eb0 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegServerPortOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.mjpeg; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsMjpegServerPortOption> extends + Capabilities, CanSetCapability { + String MJPEG_SERVER_PORT_OPTION = "mjpegServerPort"; + + /** + * The number of the port UiAutomator2 server starts the MJPEG server on. + * If not provided then the screenshots broadcasting service on the remote + * device does not get exposed to a local port (e.g. no adb port forwarding + * is happening). + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setMjpegServerPort(int port) { + return amend(MJPEG_SERVER_PORT_OPTION, port); + } + + /** + * Get the number of the port UiAutomator2 server starts the MJPEG server on. + * + * @return Port number. + */ + default Optional getMjpegServerPort() { + return Optional.ofNullable(toInteger(getCapability(MJPEG_SERVER_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/other/SupportsDisableSuppressAccessibilityServiceOption.java b/src/main/java/io/appium/java_client/android/options/other/SupportsDisableSuppressAccessibilityServiceOption.java new file mode 100644 index 000000000..eab017873 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/other/SupportsDisableSuppressAccessibilityServiceOption.java @@ -0,0 +1,63 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsDisableSuppressAccessibilityServiceOption> extends + Capabilities, CanSetCapability { + String DISABLE_SUPPRESS_ACCESSIBILITY_SERVICE_OPTION = "disableSuppressAccessibilityService"; + + /** + * Tells the instrumentation process to not suppress accessibility services + * during the automated test. + * + * @return self instance for chaining. + */ + default T disableSuppressAccessibilityService() { + return amend(DISABLE_SUPPRESS_ACCESSIBILITY_SERVICE_OPTION, true); + } + + /** + * Being set to true tells the instrumentation process to not suppress + * accessibility services during the automated test. This might be useful + * if your automated test needs these services. false by default. + * + * @param value Set it to true in order to suppress accessibility services. + * @return self instance for chaining. + */ + default T setDisableSuppressAccessibilityService(boolean value) { + return amend(DISABLE_SUPPRESS_ACCESSIBILITY_SERVICE_OPTION, value); + } + + /** + * Get whether to suppress accessibility services. + * + * @return True or false. + */ + default Optional doesDisableSuppressAccessibilityService() { + return Optional.ofNullable( + toSafeBoolean(getCapability(DISABLE_SUPPRESS_ACCESSIBILITY_SERVICE_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java b/src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java new file mode 100644 index 000000000..79c48e2a2 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSkipLogCaptureOption> extends + Capabilities, CanSetCapability { + String SKIP_LOG_CAPTURE_OPTION = "skipLogCapture"; + + /** + * Skips capturing logs such as logcat. + * + * @return self instance for chaining. + */ + default T skipLogCapture() { + return amend(SKIP_LOG_CAPTURE_OPTION, true); + } + + /** + * Skips to start capturing logs such as logcat. It might improve network performance. + * Log-related commands won't work if the capability is enabled. Defaults to false. + * + * @param value Set it to true in order to skip logcat capture. + * @return self instance for chaining. + */ + default T setSkipLogCapture(boolean value) { + return amend(SKIP_LOG_CAPTURE_OPTION, value); + } + + /** + * Get whether to skip capturing logs such as logcat. + * + * @return True or false. + */ + default Optional doesSkipLogCapture() { + return Optional.ofNullable(toSafeBoolean(getCapability(SKIP_LOG_CAPTURE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/other/SupportsUserProfileOption.java b/src/main/java/io/appium/java_client/android/options/other/SupportsUserProfileOption.java new file mode 100644 index 000000000..0408abb1c --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/other/SupportsUserProfileOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsUserProfileOption> extends + Capabilities, CanSetCapability { + String USER_PROFILE_OPTION = "userProfile"; + + /** + * Integer identifier of a user profile. By default, the app under test is + * installed for the currently active user, but in case it is necessary to + * test how the app performs while being installed for a user profile, + * which is different from the current one, then this capability might + * come in handy. + * + * @param profileId User profile identifier. + * @return self instance for chaining. + */ + default T setUserProfile(int profileId) { + return amend(USER_PROFILE_OPTION, profileId); + } + + /** + * Get the integer identifier of a user profile. + * + * @return User profile id. + */ + default Optional getUserProfile() { + return Optional.ofNullable(toInteger(getCapability(USER_PROFILE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/MobileBrowserType.java b/src/main/java/io/appium/java_client/remote/MobileBrowserType.java index 9ca3c79ed..bcd0382a2 100644 --- a/src/main/java/io/appium/java_client/remote/MobileBrowserType.java +++ b/src/main/java/io/appium/java_client/remote/MobileBrowserType.java @@ -17,7 +17,7 @@ package io.appium.java_client.remote; public interface MobileBrowserType { - + String ANDROID = "Android"; String SAFARI = "Safari"; String BROWSER = "Browser"; String CHROMIUM = "Chromium"; diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index ff575989f..bb597d195 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -23,6 +23,8 @@ import org.openqa.selenium.remote.CapabilityType; import javax.annotation.Nullable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.stream.Collectors; @@ -36,10 +38,14 @@ * @param The child class for a proper chaining. */ @SuppressWarnings({"unused", "UnusedReturnValue"}) -public class BaseOptions> extends MutableCapabilities - implements CanSetCapability, SupportsAutomationNameOption, - SupportsEventTimingsOption, SupportsPrintPageSourceOnFindFailureOption, - SupportsNoResetOption, SupportsFullResetOption, SupportsNewCommandTimeoutOption, +public class BaseOptions> extends MutableCapabilities implements + CanSetCapability, + SupportsAutomationNameOption, + SupportsEventTimingsOption, + SupportsPrintPageSourceOnFindFailureOption, + SupportsNoResetOption, + SupportsFullResetOption, + SupportsNewCommandTimeoutOption, SupportsPlatformVersionOption { private static final AcceptedW3CCapabilityKeys W3C_KEY_PATTERNS = new AcceptedW3CCapabilityKeys(); @@ -79,9 +85,30 @@ public Map asMap() { @Override public T merge(Capabilities extraCapabilities) { - super.merge(extraCapabilities); - //noinspection unchecked - return (T) this; + T result = this.clone(); + extraCapabilities.asMap().forEach((key, value) -> { + if (value != null) { + result.setCapability(key, value); + } + }); + return result; + } + + /** + * Makes a deep clone of the current Options instance. + * + * @return A deep instance clone. + */ + @SuppressWarnings("MethodDoesntCallSuperMethod") + public T clone() { + try { + Constructor constructor = getClass().getConstructor(Capabilities.class); + //noinspection unchecked + return (T) constructor.newInstance(this); + } catch (InvocationTargetException | NoSuchMethodException + | InstantiationException | IllegalAccessException e) { + throw new IllegalStateException(e); + } } @Override diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 30147838e..93124226a 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -16,8 +16,6 @@ package io.appium.java_client.service.local; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; import com.google.common.collect.ImmutableList; @@ -25,6 +23,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.appium.java_client.remote.AndroidMobileCapabilityType; +import io.appium.java_client.remote.MobileBrowserType; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.flags.ServerArgument; @@ -36,8 +35,6 @@ import org.openqa.selenium.Platform; import org.openqa.selenium.os.ExecutableFinder; import org.openqa.selenium.remote.Browser; -import org.openqa.selenium.remote.BrowserType; -import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.service.DriverService; import javax.annotation.Nullable; @@ -54,7 +51,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.function.Function; public final class AppiumServiceBuilder @@ -81,7 +77,7 @@ public final class AppiumServiceBuilder private File appiumJS; private File node; private String ipAddress = BROADCAST_IP_ADDRESS; - private DesiredCapabilities capabilities; + private Capabilities capabilities; private boolean autoQuoteCapabilitiesOnWindows = false; private static final Function APPIUM_JS_NOT_EXIST_ERROR = (fullPath) -> String.format( "The main Appium script does not exist at '%s'", fullPath.getAbsolutePath()); @@ -114,7 +110,7 @@ public int score(Capabilities capabilities) { } String browserName = capabilities.getBrowserName(); - if (Browser.CHROME.is(browserName) || browserName.equals(BrowserType.ANDROID) + if (Browser.CHROME.is(browserName) || browserName.equalsIgnoreCase(MobileBrowserType.ANDROID) || Browser.SAFARI.is(browserName)) { score++; } @@ -227,32 +223,27 @@ public AppiumServiceBuilder withArgument(ServerArgument argument, String value) } /** - * Adds a desired capabilities. + * Adds capabilities. * - * @param capabilities is an instance of {@link DesiredCapabilities}. + * @param capabilities is an instance of {@link Capabilities}. * @return the self-reference. */ - public AppiumServiceBuilder withCapabilities(DesiredCapabilities capabilities) { - if (this.capabilities == null) { - this.capabilities = capabilities; - } else { - DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); - desiredCapabilities.merge(this.capabilities).merge(capabilities); - this.capabilities = desiredCapabilities; - } + public AppiumServiceBuilder withCapabilities(Capabilities capabilities) { + this.capabilities = (this.capabilities == null ? capabilities : this.capabilities) + .merge(capabilities); return this; } /** - * Adds a desired capabilities. + * Adds capabilities. * - * @param capabilities is an instance of {@link DesiredCapabilities}. + * @param capabilities is an instance of {@link Capabilities}. * @param autoQuoteCapabilitiesOnWindows automatically escape quote all * capabilities when calling appium. * This is required on windows systems only. * @return the self-reference. */ - public AppiumServiceBuilder withCapabilities(DesiredCapabilities capabilities, + public AppiumServiceBuilder withCapabilities(Capabilities capabilities, boolean autoQuoteCapabilitiesOnWindows) { this.autoQuoteCapabilitiesOnWindows = autoQuoteCapabilitiesOnWindows; return withCapabilities(capabilities); @@ -333,7 +324,7 @@ private String capabilitiesToQuotedCmdlineArg() { result.append(key).append(": ").append(value); } - return "{" + result.toString() + "}"; + return "{" + result + "}"; } private String capabilitiesToCmdlineArg() { diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 3ebaa5dbf..5108c98ac 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -16,16 +16,13 @@ package io.appium.java_client.android; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.openqa.selenium.remote.DesiredCapabilities; - import static io.appium.java_client.TestResources.apiDemosApk; public class BaseAndroidTest { @@ -44,12 +41,11 @@ public class BaseAndroidTest { "An appium server node is not started!"); } - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - capabilities.setCapability("eventTimings", true); - driver = new AndroidDriver<>(service.getUrl(), capabilities); + UiAutomator2Options options = new UiAutomator2Options() + .setDeviceName("Android Emulator") + .setApp(apiDemosApk().toAbsolutePath().toString()) + .setEventTimings(); + driver = new AndroidDriver<>(service.getUrl(), options); } /** diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java index a3d1d0e60..e4db8038b 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java @@ -26,9 +26,9 @@ import static org.junit.Assert.assertTrue; import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.remote.AndroidMobileCapabilityType; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.IOSMobileCapabilityType; import io.appium.java_client.remote.MobileCapabilityType; @@ -39,21 +39,22 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.remote.DesiredCapabilities; +import java.time.Duration; + public class StartingAppLocallyTest { @Test public void startingAndroidAppWithCapabilitiesOnlyTest() { - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2); - - AndroidDriver driver = new AndroidDriver<>(capabilities); + AndroidDriver driver = new AndroidDriver<>(new UiAutomator2Options() + .setDeviceName("Android Emulator") + .setApp(apiDemosApk().toAbsolutePath().toString())); try { Capabilities caps = driver.getCapabilities(); - assertEquals(AutomationName.APPIUM, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); - assertEquals(MobilePlatform.ANDROID, caps.getCapability(MobileCapabilityType.PLATFORM_NAME)); - assertNotEquals(null, caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( + (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) + ); + assertNotNull(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); assertEquals(apiDemosApk().toAbsolutePath().toString(), caps.getCapability(MobileCapabilityType.APP)); } finally { driver.quit(); @@ -61,54 +62,53 @@ public class StartingAppLocallyTest { } @Test public void startingAndroidAppWithCapabilitiesAndServiceTest() { - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); - AndroidDriver driver = new AndroidDriver<>(builder, capabilities); + AndroidDriver driver = new AndroidDriver<>(builder, new UiAutomator2Options() + .setDeviceName("Android Emulator") + .setApp(apiDemosApk().toAbsolutePath().toString())); try { Capabilities caps = driver.getCapabilities(); - assertEquals(MobilePlatform.ANDROID, caps.getCapability(MobileCapabilityType.PLATFORM_NAME)); - assertNotEquals(null, caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( + (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) + ); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); } finally { driver.quit(); } } @Test public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android"); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - serverCapabilities.setCapability(MobileCapabilityType.FULL_RESET, true); - serverCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60); - serverCapabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); + UiAutomator2Options serverOptions = new UiAutomator2Options() + .setDeviceName("Android Emulator") + .fullReset() + .setNewCommandTimeout(Duration.ofSeconds(60)) + .setApp(apiDemosApk().toAbsolutePath().toString()); WebDriverManager chromeManager = chromedriver(); chromeManager.setup(); - serverCapabilities.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, - chromeManager.getDownloadedDriverPath()); + serverOptions.setChromedriverExecutable(chromeManager.getDownloadedDriverPath()); AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) - .withArgument(GeneralServerFlag.STRICT_CAPS).withCapabilities(serverCapabilities); + .withArgument(GeneralServerFlag.STRICT_CAPS) + .withCapabilities(serverOptions); - DesiredCapabilities clientCapabilities = new DesiredCapabilities(); - clientCapabilities - .setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "io.appium.android.apis"); - clientCapabilities - .setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".view.WebView1"); + UiAutomator2Options clientOptions = new UiAutomator2Options() + .setAppPackage("io.appium.android.apis") + .setAppActivity(".view.WebView1"); - AndroidDriver driver = new AndroidDriver<>(builder, clientCapabilities); + AndroidDriver driver = new AndroidDriver<>(builder, clientOptions); try { Capabilities caps = driver.getCapabilities(); - assertEquals(MobilePlatform.ANDROID, caps.getCapability(MobileCapabilityType.PLATFORM_NAME)); - assertNotEquals(null, caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( + (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) + ); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); } finally { driver.quit(); } From 4d944ae7d4f43e43d4389cfe9ee96b6d86ca136c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 26 Oct 2021 09:13:08 +0200 Subject: [PATCH 007/501] fix: Update Service to properly work with options (#1550) --- .../SupportsAutoGrantPermissionsOption.java | 2 +- .../service/local/StartingAppLocallyTest.java | 32 ++++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java index 97402c867..7a7d6cde1 100644 --- a/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAutoGrantPermissionsOption.java @@ -34,7 +34,7 @@ public interface SupportsAutoGrantPermissionsOption> ex * * @return self instance for chaining. */ - default T setAutoGrantPermissions() { + default T autoGrantPermissions() { return amend(AUTO_GRANT_PERMISSIONS_OPTION, true); } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java index e4db8038b..612db0aed 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java @@ -21,7 +21,6 @@ import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -43,9 +42,11 @@ public class StartingAppLocallyTest { - @Test public void startingAndroidAppWithCapabilitiesOnlyTest() { + @Test + public void startingAndroidAppWithCapabilitiesOnlyTest() { AndroidDriver driver = new AndroidDriver<>(new UiAutomator2Options() .setDeviceName("Android Emulator") + .autoGrantPermissions() .setApp(apiDemosApk().toAbsolutePath().toString())); try { Capabilities caps = driver.getCapabilities(); @@ -53,7 +54,7 @@ public class StartingAppLocallyTest { assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) ); - assertNotNull(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); + assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); assertEquals(apiDemosApk().toAbsolutePath().toString(), caps.getCapability(MobileCapabilityType.APP)); } finally { @@ -61,13 +62,15 @@ public class StartingAppLocallyTest { } } - @Test public void startingAndroidAppWithCapabilitiesAndServiceTest() { + @Test + public void startingAndroidAppWithCapabilitiesAndServiceTest() { AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); AndroidDriver driver = new AndroidDriver<>(builder, new UiAutomator2Options() .setDeviceName("Android Emulator") + .autoGrantPermissions() .setApp(apiDemosApk().toAbsolutePath().toString())); try { Capabilities caps = driver.getCapabilities(); @@ -81,10 +84,12 @@ public class StartingAppLocallyTest { } } - @Test public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { + @Test + public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { UiAutomator2Options serverOptions = new UiAutomator2Options() .setDeviceName("Android Emulator") .fullReset() + .autoGrantPermissions() .setNewCommandTimeout(Duration.ofSeconds(60)) .setApp(apiDemosApk().toAbsolutePath().toString()); @@ -114,7 +119,8 @@ public class StartingAppLocallyTest { } } - @Test public void startingIOSAppWithCapabilitiesOnlyTest() { + @Test + public void startingIOSAppWithCapabilitiesOnlyTest() { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); //sometimes environment has performance problems @@ -130,7 +136,7 @@ public class StartingAppLocallyTest { assertEquals(AutomationName.IOS_XCUI_TEST, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); assertEquals(MobilePlatform.IOS, caps.getCapability(MobileCapabilityType.PLATFORM_NAME)); - assertNotEquals(null, caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); assertEquals(BaseIOSTest.PLATFORM_VERSION, caps.getCapability(MobileCapabilityType.PLATFORM_VERSION)); assertEquals(uiCatalogAppZip().toAbsolutePath().toString(), caps.getCapability(MobileCapabilityType.APP)); } finally { @@ -139,7 +145,8 @@ public class StartingAppLocallyTest { } - @Test public void startingIOSAppWithCapabilitiesAndServiceTest() { + @Test + public void startingIOSAppWithCapabilitiesAndServiceTest() { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); @@ -158,18 +165,19 @@ public class StartingAppLocallyTest { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) .toString().equalsIgnoreCase(MobilePlatform.IOS)); - assertNotNull(null, caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); } finally { driver.quit(); } } - @Test public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { + @Test + public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { DesiredCapabilities serverCapabilities = new DesiredCapabilities(); serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); serverCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); serverCapabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); //some environment is too slow + BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); //some environment is too slow serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); @@ -185,7 +193,7 @@ public class StartingAppLocallyTest { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) .toString().equalsIgnoreCase(MobilePlatform.IOS)); - assertNotEquals(null, caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); assertFalse(driver.isBrowser()); } finally { driver.quit(); From 8d99d4ca427578c312391bdeb52a2098e10db2ff Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 26 Oct 2021 10:20:42 +0200 Subject: [PATCH 008/501] chore: Start adding XCUITest driver options (#1551) --- .../ios/options/XCUITestOptions.java | 38 ++++++++++-- .../app/SupportsAppInstallStrategyOption.java | 58 ++++++++++++++++++ .../app/SupportsAppPushTimeoutOption.java | 52 ++++++++++++++++ .../options/app/SupportsBundleIdOption.java | 50 ++++++++++++++++ .../SupportsLocalizableStringsDirOption.java | 48 +++++++++++++++ ...sIncludeDeviceCapsToSessionInfoOption.java | 52 ++++++++++++++++ .../SupportsResetLocationServiceOption.java | 59 +++++++++++++++++++ .../java_client/remote/AutomationName.java | 18 +++++- 8 files changed, 368 insertions(+), 7 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/app/SupportsAppPushTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/app/SupportsBundleIdOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/app/SupportsLocalizableStringsDirOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/general/SupportsIncludeDeviceCapsToSessionInfoOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/general/SupportsResetLocationServiceOption.java diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index 8c8143da1..6a2542fc4 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -16,6 +16,12 @@ package io.appium.java_client.ios.options; +import io.appium.java_client.ios.options.app.SupportsAppInstallStrategyOption; +import io.appium.java_client.ios.options.app.SupportsAppPushTimeoutOption; +import io.appium.java_client.ios.options.app.SupportsBundleIdOption; +import io.appium.java_client.ios.options.app.SupportsLocalizableStringsDirOption; +import io.appium.java_client.ios.options.general.SupportsIncludeDeviceCapsToSessionInfoOption; +import io.appium.java_client.ios.options.general.SupportsResetLocationServiceOption; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; @@ -31,12 +37,34 @@ import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; +/** + * https://github.com/appium/appium-xcuitest-driver#capabilities + */ public class XCUITestOptions extends BaseOptions implements - SupportsAppOption, SupportsAutoWebViewOption, - SupportsClearSystemFilesOption, SupportsDeviceNameOption, - SupportsEnablePerformanceLoggingOption, SupportsLanguageOption, - SupportsLocaleOption, SupportsOrientationOption, - SupportsOtherAppsOption, SupportsUdidOption { + // General options: https://github.com/appium/appium-xcuitest-driver#general + SupportsDeviceNameOption, + SupportsUdidOption, + SupportsIncludeDeviceCapsToSessionInfoOption, + SupportsResetLocationServiceOption, + // Localization Options + SupportsLocalizableStringsDirOption, + SupportsLanguageOption, + SupportsLocaleOption, + // App Options: https://github.com/appium/appium-xcuitest-driver#app + SupportsAppOption, + SupportsBundleIdOption, + SupportsOtherAppsOption, + SupportsAppPushTimeoutOption, + SupportsAppInstallStrategyOption, + // TODO: WebDriverAgent options: https://github.com/appium/appium-xcuitest-driver#webdriveragent + // TODO: Simulator options: https://github.com/appium/appium-xcuitest-driver#simulator + SupportsOrientationOption, + // TODO: Web context options: https://github.com/appium/appium-xcuitest-driver#web-context + SupportsAutoWebViewOption, + // TODO: Other options: https://github.com/appium/appium-xcuitest-driver#other + SupportsClearSystemFilesOption, + SupportsEnablePerformanceLoggingOption { + public XCUITestOptions() { setCommonOptions(); } diff --git a/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java b/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java new file mode 100644 index 000000000..313253491 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java @@ -0,0 +1,58 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppInstallStrategyOption> extends + Capabilities, CanSetCapability { + String APP_INSTALL_STRATEGY_OPTION = "appInstallStrategy"; + + /** + * Select application installation strategy for real devices. The following + * strategies are supported: + * + * serial (default) - pushes app files to the device in a sequential order; + * this is the least performant strategy, although the most reliable; + * + * parallel - pushes app files simultaneously; this is usually the + * most performant strategy, but sometimes could not be very stable; + * + * ios-deploy - tells the driver to use a third-party tool ios-deploy to + * install the app; obviously the tool must be installed separately + * first and must be present in PATH before it could be used. + * + * @param strategy App installation strategy. + * @return self instance for chaining. + */ + default T setAppInstallStrategy(String strategy) { + return amend(APP_INSTALL_STRATEGY_OPTION, strategy); + } + + /** + * Get the app install strategy. + * + * @return App installation strategy. + */ + default Optional getAppInstallStrategy() { + return Optional.ofNullable((String) getCapability(APP_INSTALL_STRATEGY_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/app/SupportsAppPushTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/app/SupportsAppPushTimeoutOption.java new file mode 100644 index 000000000..1e3d54aeb --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/app/SupportsAppPushTimeoutOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.app; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsAppPushTimeoutOption> extends + Capabilities, CanSetCapability { + String APP_PUSH_TIMEOUT_OPTION = "appPushTimeout"; + + /** + * The timeout for application upload. + * Works for real devices only. The default value is 30000ms. + * + * @param timeout App push timeout. + * @return self instance for chaining. + */ + default T setAppPushTimeout(Duration timeout) { + return amend(APP_PUSH_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get maximum timeout for application upload. + * + * @return Timeout value. + */ + default Optional getAppPushTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(APP_PUSH_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/app/SupportsBundleIdOption.java b/src/main/java/io/appium/java_client/ios/options/app/SupportsBundleIdOption.java new file mode 100644 index 000000000..97e53d2f4 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/app/SupportsBundleIdOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsBundleIdOption> extends + Capabilities, CanSetCapability { + String BUNDLE_ID_OPTION = "bundleId"; + + /** + * Bundle identifier of the app under test, for example com.mycompany.myapp. + * The capability value is calculated automatically if app is provided. + * If neither app nor bundleId capability is provided then XCUITest driver + * starts from the Home screen. + * + * @param identifier App identifier. + * @return self instance for chaining. + */ + default T setBundleId(String identifier) { + return amend(BUNDLE_ID_OPTION, identifier); + } + + /** + * Get the app bundle identifier. + * + * @return Identifier value. + */ + default Optional getBundleId() { + return Optional.ofNullable((String) getCapability(BUNDLE_ID_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/app/SupportsLocalizableStringsDirOption.java b/src/main/java/io/appium/java_client/ios/options/app/SupportsLocalizableStringsDirOption.java new file mode 100644 index 000000000..f02635bf6 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/app/SupportsLocalizableStringsDirOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsLocalizableStringsDirOption> extends + Capabilities, CanSetCapability { + String LOCALIZABLE_STRINGS_DIR_OPTION = "localizableStringsDir"; + + /** + * Where to look for localizable strings in the application bundle. + * Defaults to en.lproj. + * + * @param folder The resource folder name where the main locale strings are stored. + * @return self instance for chaining. + */ + default T setLocalizableStringsDir(String folder) { + return amend(LOCALIZABLE_STRINGS_DIR_OPTION, folder); + } + + /** + * Get the resource folder name where the main locale strings are stored. + * + * @return Folder name. + */ + default Optional getLocalizableStringsDir() { + return Optional.ofNullable((String) getCapability(LOCALIZABLE_STRINGS_DIR_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/general/SupportsIncludeDeviceCapsToSessionInfoOption.java b/src/main/java/io/appium/java_client/ios/options/general/SupportsIncludeDeviceCapsToSessionInfoOption.java new file mode 100644 index 000000000..9760cbdf5 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/general/SupportsIncludeDeviceCapsToSessionInfoOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.general; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsIncludeDeviceCapsToSessionInfoOption> extends + Capabilities, CanSetCapability { + String INCLUDE_DEVICE_CAPS_TO_SESSION_INFO_OPTION = "includeDeviceCapsToSessionInfo"; + + /** + * Whether to include screen information as the result of Get Session Capabilities. + * It includes pixelRatio, statBarHeight and viewportRect, but + * it causes an extra API call to WDA which may increase the response time. + * Defaults to true. + * + * @param value Whether to include screen information as the result of Get Session Capabilities. + * @return self instance for chaining. + */ + default T setIncludeDeviceCapsToSessionInfo(boolean value) { + return amend(INCLUDE_DEVICE_CAPS_TO_SESSION_INFO_OPTION, value); + } + + /** + * Get whether to include screen information as the result of Get Session Capabilities. + * + * @return True or false. + */ + default Optional doesIncludeDeviceCapsToSessionInfo() { + return Optional.ofNullable(toSafeBoolean(getCapability(INCLUDE_DEVICE_CAPS_TO_SESSION_INFO_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/general/SupportsResetLocationServiceOption.java b/src/main/java/io/appium/java_client/ios/options/general/SupportsResetLocationServiceOption.java new file mode 100644 index 000000000..5bd8da1d7 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/general/SupportsResetLocationServiceOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.general; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsResetLocationServiceOption> extends + Capabilities, CanSetCapability { + String RESET_LOCATION_SERVICE_OPTION = "resetLocationService"; + + /** + * Set to reset the location service in the session deletion on real device. + * + * @return self instance for chaining. + */ + default T resetLocationService() { + return amend(RESET_LOCATION_SERVICE_OPTION, true); + } + + /** + * Whether reset the location service in the session deletion on real device. + * Defaults to false. + * + * @param value Whether to reset the location service in the session deletion on real device. + * @return self instance for chaining. + */ + default T setResetLocationService(boolean value) { + return amend(RESET_LOCATION_SERVICE_OPTION, value); + } + + /** + * Get whether to reset the location service in the session deletion on real device. + * + * @return True or false. + */ + default Optional doesResetLocationService() { + return Optional.ofNullable(toSafeBoolean(getCapability(RESET_LOCATION_SERVICE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/AutomationName.java b/src/main/java/io/appium/java_client/remote/AutomationName.java index 2f9cdf11f..5be0849a9 100644 --- a/src/main/java/io/appium/java_client/remote/AutomationName.java +++ b/src/main/java/io/appium/java_client/remote/AutomationName.java @@ -16,14 +16,28 @@ package io.appium.java_client.remote; - public interface AutomationName { + // Officially supported drivers + @Deprecated String APPIUM = "Appium"; @Deprecated String SELENDROID = "Selendroid"; + // https://github.com/appium/appium-xcuitest-driver String IOS_XCUI_TEST = "XCuiTest"; + // https://github.com/appium/appium-uiautomator2-driver String ANDROID_UIAUTOMATOR2 = "UIAutomator2"; - String YOUI_ENGINE = "youiengine"; + // https://github.com/appium/appium-espresso-driver String ESPRESSO = "Espresso"; + // https://github.com/appium/appium-mac2-driver String MAC2 = "Mac2"; + // https://github.com/appium/appium-windows-driver + String WINDOWS = "Windows"; + // https://github.com/appium/appium-safari-driver + String SAFARI = "Safari"; + // https://github.com/appium/appium-geckodriver + String GECKO = "Gecko"; + + // Third-party drivers + // https://github.com/YOU-i-Labs/appium-youiengine-driver + String YOUI_ENGINE = "youiengine"; } From 523d6433a52f022c9c76c1626b51ddc928fbe3b3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 26 Oct 2021 20:32:08 +0200 Subject: [PATCH 009/501] chore: Add WDA-related XCUITestOptions (#1552) --- .../SupportsMjpegScreenshotUrlOption.java | 10 +-- .../internal/CapabilityHelpers.java | 58 ++++++++++++--- .../ios/options/XCUITestOptions.java | 68 +++++++++++++++++- .../app/SupportsAppInstallStrategyOption.java | 10 +-- .../java_client/ios/options/wda/Keychain.java | 27 +++++++ .../ios/options/wda/ProcessArguments.java | 56 +++++++++++++++ ...wProvisioningDeviceRegistrationOption.java | 60 ++++++++++++++++ .../wda/SupportsAutoAcceptAlertsOption.java | 59 ++++++++++++++++ .../wda/SupportsAutoDismissAlertsOption.java | 59 ++++++++++++++++ .../wda/SupportsDerivedDataPathOption.java | 49 +++++++++++++ ...ortsDisableAutomaticScreenshotsOption.java | 51 ++++++++++++++ .../wda/SupportsForceAppLaunchOption.java | 53 ++++++++++++++ .../options/wda/SupportsKeychainOptions.java | 54 ++++++++++++++ .../wda/SupportsMaxTypingFrequencyOption.java | 51 ++++++++++++++ .../wda/SupportsMjpegServerPortOption.java | 53 ++++++++++++++ .../wda/SupportsProcessArgumentsOption.java | 56 +++++++++++++++ .../wda/SupportsResultBundlePathOption.java | 51 ++++++++++++++ .../wda/SupportsScreenshotQualityOption.java | 53 ++++++++++++++ .../wda/SupportsShouldTerminateAppOption.java | 53 ++++++++++++++ ...tsShouldUseSingletonTestManagerOption.java | 59 ++++++++++++++++ .../wda/SupportsShowXcodeLogOption.java | 61 ++++++++++++++++ .../SupportsSimpleIsVisibleCheckOption.java | 62 ++++++++++++++++ .../wda/SupportsUpdatedWdaBundleIdOption.java | 48 +++++++++++++ ...upportsUseNativeCachingStrategyOption.java | 52 ++++++++++++++ .../options/wda/SupportsUseNewWdaOption.java | 70 +++++++++++++++++++ .../wda/SupportsUsePrebuiltWdaOption.java | 59 ++++++++++++++++ .../wda/SupportsUseSimpleBuildTestOption.java | 60 ++++++++++++++++ .../wda/SupportsUseXctestrunFileOption.java | 69 ++++++++++++++++++ .../wda/SupportsWaitForIdleTimeoutOption.java | 58 +++++++++++++++ .../wda/SupportsWaitForQuiescenceOption.java | 52 ++++++++++++++ .../options/wda/SupportsWdaBaseUrlOption.java | 66 +++++++++++++++++ .../SupportsWdaConnectionTimeoutOption.java | 52 ++++++++++++++ .../SupportsWdaEventloopIdleDelayOption.java | 59 ++++++++++++++++ .../wda/SupportsWdaLaunchTimeoutOption.java | 52 ++++++++++++++ .../wda/SupportsWdaLocalPortOption.java | 52 ++++++++++++++ .../wda/SupportsWdaStartupRetriesOption.java | 50 +++++++++++++ ...SupportsWdaStartupRetryIntervalOption.java | 52 ++++++++++++++ .../wda/SupportsWebDriverAgentUrlOption.java | 62 ++++++++++++++++ .../wda/SupportsXcodeCertificateOptions.java | 56 +++++++++++++++ .../ios/options/wda/XcodeCertificate.java | 36 ++++++++++ 40 files changed, 2092 insertions(+), 26 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/Keychain.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsAllowProvisioningDeviceRegistrationOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoAcceptAlertsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoDismissAlertsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsDerivedDataPathOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsDisableAutomaticScreenshotsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsForceAppLaunchOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsKeychainOptions.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsMaxTypingFrequencyOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsMjpegServerPortOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsProcessArgumentsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsResultBundlePathOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsScreenshotQualityOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldTerminateAppOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldUseSingletonTestManagerOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsShowXcodeLogOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsSimpleIsVisibleCheckOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUpdatedWdaBundleIdOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNativeCachingStrategyOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNewWdaOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePrebuiltWdaOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUseSimpleBuildTestOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUseXctestrunFileOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForQuiescenceOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaBaseUrlOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaConnectionTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLaunchTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLocalPortOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetriesOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetryIntervalOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsWebDriverAgentUrlOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/XcodeCertificate.java diff --git a/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java b/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java index bb78ed30a..bd8111c94 100644 --- a/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java +++ b/src/main/java/io/appium/java_client/android/options/mjpeg/SupportsMjpegScreenshotUrlOption.java @@ -16,11 +16,11 @@ package io.appium.java_client.android.options.mjpeg; +import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; -import java.net.MalformedURLException; import java.net.URL; import java.util.Optional; @@ -59,12 +59,6 @@ default T setMjpegScreenshotUrl(String url) { */ default Optional getMjpegScreenshotUrl() { return Optional.ofNullable(getCapability(MJPEG_SCREENSHOT_URL_OPTION)) - .map((v) -> { - try { - return new URL(String.valueOf(v)); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); - } - }); + .map(CapabilityHelpers::toUrl); } } diff --git a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java index 106b96c59..995385b4b 100644 --- a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java +++ b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java @@ -19,6 +19,8 @@ import org.openqa.selenium.Capabilities; import javax.annotation.Nullable; +import java.net.MalformedURLException; +import java.net.URL; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -75,8 +77,8 @@ public static Boolean toSafeBoolean(Object value) { * Converts generic capability value to integer. * * @param value The capability value. - * @throws NumberFormatException If the given value cannot be parsed to a valid integer. * @return null is the passed value is null otherwise the converted value. + * @throws NumberFormatException If the given value cannot be parsed to a valid integer. */ @Nullable public static Integer toInteger(Object value) { @@ -90,12 +92,11 @@ public static Integer toInteger(Object value) { } /** - * Converts generic capability value to long without - * throwing exceptions. + * Converts generic capability value to long. * * @param value The capability value. - * @throws NumberFormatException If the given value cannot be parsed to a valid long. * @return null is the passed value is null otherwise the converted value. + * @throws NumberFormatException If the given value cannot be parsed to a valid long. */ @Nullable public static Long toLong(Object value) { @@ -109,13 +110,30 @@ public static Long toLong(Object value) { } /** - * Converts generic capability value to duration without - * throwing exceptions. The value is assumed to be + * Converts generic capability value to double. + * + * @param value The capability value. + * @return null is the passed value is null otherwise the converted value. + * @throws NumberFormatException If the given value cannot be parsed to a valid long. + */ + @Nullable + public static Double toDouble(Object value) { + if (value == null) { + return null; + } else if (value instanceof Number) { + return ((Number) value).doubleValue(); + } else { + return Double.parseDouble(String.valueOf(value)); + } + } + + /** + * Converts generic capability value to duration. The value is assumed to be * measured in milliseconds. * * @param value The capability value. - * @throws NumberFormatException If the given value cannot be parsed to a valid number. * @return null is the passed value is null otherwise the converted value. + * @throws NumberFormatException If the given value cannot be parsed to a valid number. */ @Nullable public static Duration toDuration(Object value) { @@ -123,13 +141,12 @@ public static Duration toDuration(Object value) { } /** - * Converts generic capability value to duration without - * throwing exceptions. + * Converts generic capability value to duration. * * @param value The capability value. * @param converter Converts the numeric value to a Duration instance. - * @throws NumberFormatException If the given value cannot be parsed to a valid number. * @return null is the passed value is null otherwise the converted value. + * @throws NumberFormatException If the given value cannot be parsed to a valid number. */ @Nullable public static Duration toDuration(Object value, @@ -137,4 +154,25 @@ public static Duration toDuration(Object value, Long v = toLong(value); return v == null ? null : converter.apply(v); } + + /** + * Converts generic capability value to a url. + * + * @param value The capability value. + * @throws IllegalArgumentException If the given value cannot be parsed to a valid url. + * @return null is the passed value is null otherwise the converted value. + */ + @Nullable + public static URL toUrl(Object value) { + if (value == null) { + return null; + } + try { + return (value instanceof URL) + ? (URL) value : + new URL(String.valueOf(value)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } } diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index 6a2542fc4..be0bd03be 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -22,6 +22,39 @@ import io.appium.java_client.ios.options.app.SupportsLocalizableStringsDirOption; import io.appium.java_client.ios.options.general.SupportsIncludeDeviceCapsToSessionInfoOption; import io.appium.java_client.ios.options.general.SupportsResetLocationServiceOption; +import io.appium.java_client.ios.options.wda.SupportsAllowProvisioningDeviceRegistrationOption; +import io.appium.java_client.ios.options.wda.SupportsAutoAcceptAlertsOption; +import io.appium.java_client.ios.options.wda.SupportsAutoDismissAlertsOption; +import io.appium.java_client.ios.options.wda.SupportsDerivedDataPathOption; +import io.appium.java_client.ios.options.wda.SupportsDisableAutomaticScreenshotsOption; +import io.appium.java_client.ios.options.wda.SupportsForceAppLaunchOption; +import io.appium.java_client.ios.options.wda.SupportsKeychainOptions; +import io.appium.java_client.ios.options.wda.SupportsMaxTypingFrequencyOption; +import io.appium.java_client.ios.options.wda.SupportsMjpegServerPortOption; +import io.appium.java_client.ios.options.wda.SupportsProcessArgumentsOption; +import io.appium.java_client.ios.options.wda.SupportsResultBundlePathOption; +import io.appium.java_client.ios.options.wda.SupportsScreenshotQualityOption; +import io.appium.java_client.ios.options.wda.SupportsShouldTerminateAppOption; +import io.appium.java_client.ios.options.wda.SupportsShouldUseSingletonTestManagerOption; +import io.appium.java_client.ios.options.wda.SupportsShowXcodeLogOption; +import io.appium.java_client.ios.options.wda.SupportsSimpleIsVisibleCheckOption; +import io.appium.java_client.ios.options.wda.SupportsUpdatedWdaBundleIdOption; +import io.appium.java_client.ios.options.wda.SupportsUseNativeCachingStrategyOption; +import io.appium.java_client.ios.options.wda.SupportsUseNewWdaOption; +import io.appium.java_client.ios.options.wda.SupportsUsePrebuiltWdaOption; +import io.appium.java_client.ios.options.wda.SupportsUseSimpleBuildTestOption; +import io.appium.java_client.ios.options.wda.SupportsUseXctestrunFileOption; +import io.appium.java_client.ios.options.wda.SupportsWaitForIdleTimeoutOption; +import io.appium.java_client.ios.options.wda.SupportsWaitForQuiescenceOption; +import io.appium.java_client.ios.options.wda.SupportsWdaBaseUrlOption; +import io.appium.java_client.ios.options.wda.SupportsWdaConnectionTimeoutOption; +import io.appium.java_client.ios.options.wda.SupportsWdaEventloopIdleDelayOption; +import io.appium.java_client.ios.options.wda.SupportsWdaLaunchTimeoutOption; +import io.appium.java_client.ios.options.wda.SupportsWdaLocalPortOption; +import io.appium.java_client.ios.options.wda.SupportsWdaStartupRetriesOption; +import io.appium.java_client.ios.options.wda.SupportsWdaStartupRetryIntervalOption; +import io.appium.java_client.ios.options.wda.SupportsWebDriverAgentUrlOption; +import io.appium.java_client.ios.options.wda.SupportsXcodeCertificateOptions; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; @@ -56,7 +89,40 @@ public class XCUITestOptions extends BaseOptions implements SupportsOtherAppsOption, SupportsAppPushTimeoutOption, SupportsAppInstallStrategyOption, - // TODO: WebDriverAgent options: https://github.com/appium/appium-xcuitest-driver#webdriveragent + // WebDriverAgent options: https://github.com/appium/appium-xcuitest-driver#webdriveragent + SupportsXcodeCertificateOptions, + SupportsKeychainOptions, + SupportsUpdatedWdaBundleIdOption, + SupportsDerivedDataPathOption, + SupportsWebDriverAgentUrlOption, + SupportsUseNewWdaOption, + SupportsWdaLaunchTimeoutOption, + SupportsWdaConnectionTimeoutOption, + SupportsWdaStartupRetriesOption, + SupportsWdaStartupRetryIntervalOption, + SupportsWdaLocalPortOption, + SupportsWdaBaseUrlOption, + SupportsShowXcodeLogOption, + SupportsUsePrebuiltWdaOption, + SupportsShouldUseSingletonTestManagerOption, + SupportsWaitForIdleTimeoutOption, + SupportsUseXctestrunFileOption, + SupportsUseSimpleBuildTestOption, + SupportsWdaEventloopIdleDelayOption, + SupportsProcessArgumentsOption, + SupportsAllowProvisioningDeviceRegistrationOption, + SupportsResultBundlePathOption, + SupportsMaxTypingFrequencyOption, + SupportsSimpleIsVisibleCheckOption, + SupportsWaitForQuiescenceOption, + SupportsMjpegServerPortOption, + SupportsScreenshotQualityOption, + SupportsAutoAcceptAlertsOption, + SupportsAutoDismissAlertsOption, + SupportsDisableAutomaticScreenshotsOption, + SupportsShouldTerminateAppOption, + SupportsForceAppLaunchOption, + SupportsUseNativeCachingStrategyOption, // TODO: Simulator options: https://github.com/appium/appium-xcuitest-driver#simulator SupportsOrientationOption, // TODO: Web context options: https://github.com/appium/appium-xcuitest-driver#web-context diff --git a/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java b/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java index 313253491..f74d1db15 100644 --- a/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java +++ b/src/main/java/io/appium/java_client/ios/options/app/SupportsAppInstallStrategyOption.java @@ -29,17 +29,13 @@ public interface SupportsAppInstallStrategyOption> exte /** * Select application installation strategy for real devices. The following * strategies are supported: - * - * serial (default) - pushes app files to the device in a sequential order; + * * serial (default) - pushes app files to the device in a sequential order; * this is the least performant strategy, although the most reliable; - * - * parallel - pushes app files simultaneously; this is usually the + * * parallel - pushes app files simultaneously; this is usually the * most performant strategy, but sometimes could not be very stable; - * - * ios-deploy - tells the driver to use a third-party tool ios-deploy to + * * ios-deploy - tells the driver to use a third-party tool ios-deploy to * install the app; obviously the tool must be installed separately * first and must be present in PATH before it could be used. - * * @param strategy App installation strategy. * @return self instance for chaining. */ diff --git a/src/main/java/io/appium/java_client/ios/options/wda/Keychain.java b/src/main/java/io/appium/java_client/ios/options/wda/Keychain.java new file mode 100644 index 000000000..8a2e69891 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/Keychain.java @@ -0,0 +1,27 @@ +/* + * 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.options.wda; + +import lombok.Data; +import lombok.ToString; + +@ToString() +@Data() +public class Keychain { + private final String path; + private final String password; +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java b/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java new file mode 100644 index 000000000..c5ed74d22 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java @@ -0,0 +1,56 @@ +/* + * 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.options.wda; + +import lombok.ToString; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@ToString() +public class ProcessArguments { + private final List args; + private final Map env; + + public ProcessArguments(List args, Map env) { + this.args = args; + this.env = env; + } + + public ProcessArguments(List args) { + this(args, null); + } + + public ProcessArguments(Map env) { + this(null, env); + } + + /** + * Returns the data object content as a map. + * + * @return Properties as a map. + */ + public Map toMap() { + Map result = new HashMap<>(); + Optional.ofNullable(args).ifPresent((v) -> result.put("args", v)); + Optional.ofNullable(env).ifPresent((v) -> result.put("env", v)); + return Collections.unmodifiableMap(result); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsAllowProvisioningDeviceRegistrationOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsAllowProvisioningDeviceRegistrationOption.java new file mode 100644 index 000000000..0ddf36ddb --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsAllowProvisioningDeviceRegistrationOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAllowProvisioningDeviceRegistrationOption> extends + Capabilities, CanSetCapability { + String ALLOW_PROVISIONING_DEVICE_REGISTRATION_OPTION = "allowProvisioningDeviceRegistration"; + + /** + * Allows xcodebuild to register your destination device on the developer portal. + * + * @return self instance for chaining. + */ + default T allowProvisioningDeviceRegistration() { + return amend(ALLOW_PROVISIONING_DEVICE_REGISTRATION_OPTION, true); + } + + /** + * Allow xcodebuild to register your destination device on the developer portal + * if necessary. Requires a developer account to have been added in Xcode's Accounts + * preference pane. Defaults to false. + * + * @param value Whether to allow xcodebuild to register your destination device on the developer portal. + * @return self instance for chaining. + */ + default T setAllowProvisioningDeviceRegistration(boolean value) { + return amend(ALLOW_PROVISIONING_DEVICE_REGISTRATION_OPTION, value); + } + + /** + * Get whether to allow xcodebuild to register your destination device on the developer portal. + * + * @return True or false. + */ + default Optional doesAllowProvisioningDeviceRegistration() { + return Optional.ofNullable(toSafeBoolean(getCapability(ALLOW_PROVISIONING_DEVICE_REGISTRATION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoAcceptAlertsOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoAcceptAlertsOption.java new file mode 100644 index 000000000..1a3a86347 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoAcceptAlertsOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAutoAcceptAlertsOption> extends + Capabilities, CanSetCapability { + String AUTO_ACCEPT_ALERTS_OPTION = "autoAcceptAlerts"; + + /** + * Enforce to accept all alerts automatically. + * + * @return self instance for chaining. + */ + default T autoAcceptAlerts() { + return amend(AUTO_ACCEPT_ALERTS_OPTION, true); + } + + /** + * Accept all iOS alerts automatically if they pop up. This includes privacy + * access permission alerts (e.g., location, contacts, photos). Default is false. + * + * @param value Whether to accepts alerts automatically. + * @return self instance for chaining. + */ + default T setAutoAcceptAlerts(boolean value) { + return amend(AUTO_ACCEPT_ALERTS_OPTION, value); + } + + /** + * Get whether to accept all alerts automatically. + * + * @return True or false. + */ + default Optional doesAutoAcceptAlerts() { + return Optional.ofNullable(toSafeBoolean(getCapability(AUTO_ACCEPT_ALERTS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoDismissAlertsOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoDismissAlertsOption.java new file mode 100644 index 000000000..82a85754e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsAutoDismissAlertsOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAutoDismissAlertsOption> extends + Capabilities, CanSetCapability { + String AUTO_DISMISS_ALERTS_OPTION = "autoDismissAlerts"; + + /** + * Enforce to dismiss all alerts automatically. + * + * @return self instance for chaining. + */ + default T autoDismissAlerts() { + return amend(AUTO_DISMISS_ALERTS_OPTION, true); + } + + /** + * Dismiss all iOS alerts automatically if they pop up. This includes privacy + * access permission alerts (e.g., location, contacts, photos). Default is false. + * + * @param value Whether to dismiss alerts automatically. + * @return self instance for chaining. + */ + default T setAutoDismissAlerts(boolean value) { + return amend(AUTO_DISMISS_ALERTS_OPTION, value); + } + + /** + * Get whether to dismiss all alerts automatically. + * + * @return True or false. + */ + default Optional doesAutoDismissAlerts() { + return Optional.ofNullable(toSafeBoolean(getCapability(AUTO_DISMISS_ALERTS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsDerivedDataPathOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsDerivedDataPathOption.java new file mode 100644 index 000000000..e3bfc1f2f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsDerivedDataPathOption.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.ios.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsDerivedDataPathOption> extends + Capabilities, CanSetCapability { + String DERIVED_DATA_PATH_OPTION = "derivedDataPath"; + + /** + * Use along with usePrebuiltWDA capability and choose where to search for the existing WDA app. If the capability + * is not set then Xcode will store the derived data in the default root taken from preferences. + * It also makes sense to choose different folders for parallel WDA sessions. + * + * @param path Derived data folder path. + * @return self instance for chaining. + */ + default T setDerivedDataPath(String path) { + return amend(DERIVED_DATA_PATH_OPTION, path); + } + + /** + * Get the path to the derived data WDA folder. + * + * @return Derived data folder path. + */ + default Optional getDerivedDataPath() { + return Optional.ofNullable((String) getCapability(DERIVED_DATA_PATH_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsDisableAutomaticScreenshotsOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsDisableAutomaticScreenshotsOption.java new file mode 100644 index 000000000..90c0b2683 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsDisableAutomaticScreenshotsOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsDisableAutomaticScreenshotsOption> extends + Capabilities, CanSetCapability { + String DISABLE_AUTOMATIC_SCREENSHOTS_OPTION = "disableAutomaticScreenshots"; + + /** + * Disable automatic screenshots taken by XCTest at every interaction. + * Default is up to WebDriverAgent's config to decide, which currently + * defaults to true. + * + * @param value Whether to disable automatic XCTest screenshots. + * @return self instance for chaining. + */ + default T setDisableAutomaticScreenshots(boolean value) { + return amend(DISABLE_AUTOMATIC_SCREENSHOTS_OPTION, value); + } + + /** + * Get whether to disable automatic XCTest screenshots. + * + * @return True or false. + */ + default Optional doesDisableAutomaticScreenshots() { + return Optional.ofNullable(toSafeBoolean(getCapability(DISABLE_AUTOMATIC_SCREENSHOTS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsForceAppLaunchOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsForceAppLaunchOption.java new file mode 100644 index 000000000..4c2ab4780 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsForceAppLaunchOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsForceAppLaunchOption> extends + Capabilities, CanSetCapability { + String FORCE_APP_LAUNCH_OPTION = "forceAppLaunch"; + + /** + * Specify if the app should be forcefully restarted if it is already + * running on session startup. This capability only has an effect if an + * application identifier has been passed to the test session (either + * explicitly, by setting bundleId, or implicitly, by providing app). + * Default is true unless noReset capability is set to true. + * + * @param value Whether to enforce app restart on session startup. + * @return self instance for chaining. + */ + default T setForceAppLaunch(boolean value) { + return amend(FORCE_APP_LAUNCH_OPTION, value); + } + + /** + * Get whether to enforce app restart on session startup. + * + * @return True or false. + */ + default Optional doesForceAppLaunch() { + return Optional.ofNullable(toSafeBoolean(getCapability(FORCE_APP_LAUNCH_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsKeychainOptions.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsKeychainOptions.java new file mode 100644 index 000000000..92e7a33bf --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsKeychainOptions.java @@ -0,0 +1,54 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsKeychainOptions> extends + Capabilities, CanSetCapability { + String KEYCHAIN_PATH_OPTION = "keychainPath"; + String KEYCHAIN_PASSWORD_OPTION = "keychainPassword"; + + /** + * Provides details to access custom keychain, which + * contains the private development key exported from the system keychain. + * + * @param keychain Keychain access properties. + * @return self instance for chaining. + */ + default T setKeychain(Keychain keychain) { + return amend(KEYCHAIN_PATH_OPTION, keychain.getPath()) + .amend(KEYCHAIN_PASSWORD_OPTION, keychain.getPassword()); + } + + /** + * Get details to access custom keychain. + * + * @return Keychain access properties + */ + default Optional getKeychain() { + String path = (String) getCapability(KEYCHAIN_PATH_OPTION); + String password = (String) getCapability(KEYCHAIN_PASSWORD_OPTION); + return path == null || password == null + ? Optional.empty() + : Optional.of(new Keychain(path, password)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsMaxTypingFrequencyOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsMaxTypingFrequencyOption.java new file mode 100644 index 000000000..bbc434838 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsMaxTypingFrequencyOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsMaxTypingFrequencyOption> extends + Capabilities, CanSetCapability { + String MAX_TYPING_FREQUENCY_OPTION = "maxTypingFrequency"; + + /** + * Maximum frequency of keystrokes for typing and clear. If your tests + * are failing because of typing errors, you may want to adjust this. + * Defaults to 60 keystrokes per minute. + * + * @param frequency The number of keystrokes per minute. + * @return self instance for chaining. + */ + default T setMaxTypingFrequency(int frequency) { + return amend(MAX_TYPING_FREQUENCY_OPTION, frequency); + } + + /** + * Get the number of keystrokes per minute. + * + * @return The number of keystrokes per minute. + */ + default Optional getMaxTypingFrequency() { + return Optional.ofNullable(toInteger(getCapability(MAX_TYPING_FREQUENCY_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsMjpegServerPortOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsMjpegServerPortOption.java new file mode 100644 index 000000000..6b14fab5e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsMjpegServerPortOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsMjpegServerPortOption> extends + Capabilities, CanSetCapability { + String MJPEG_SERVER_PORT_OPTION = "mjpegServerPort"; + + /** + * The port number on which WDA broadcasts screenshots stream encoded into MJPEG + * format from the device under test. It might be necessary to change this value + * if the default port is busy because of other tests running in parallel. + * Default value: 9100. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setMjpegServerPort(int port) { + return amend(MJPEG_SERVER_PORT_OPTION, port); + } + + /** + * Get the port number on which WDA broadcasts screenshots stream encoded into MJPEG + * format from the device under test. + * + * @return The port number. + */ + default Optional getMjpegServerPort() { + return Optional.ofNullable(toInteger(getCapability(MJPEG_SERVER_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsProcessArgumentsOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsProcessArgumentsOption.java new file mode 100644 index 000000000..2f30a6e1d --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsProcessArgumentsOption.java @@ -0,0 +1,56 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface SupportsProcessArgumentsOption> extends + Capabilities, CanSetCapability { + String PROCESS_ARGUMENTS_OPTION = "processArguments"; + + /** + * Provides process arguments and environment which will be sent + * to the WebDriverAgent server. + * + * @param pa Process arguments. + * @return self instance for chaining. + */ + default T setProcessArguments(ProcessArguments pa) { + return amend(PROCESS_ARGUMENTS_OPTION, pa.toMap()); + } + + /** + * Get process arguments of the app under test. + * + * @return Process arguments. + */ + @SuppressWarnings("unchecked") + default Optional getProcessArguments() { + Map pa = (Map) getCapability(PROCESS_ARGUMENTS_OPTION); + return pa == null || !(pa.containsKey("args") || pa.containsKey("env")) + ? Optional.empty() + : Optional.of(new ProcessArguments( + (List) pa.getOrDefault("args", null), + (Map) pa.getOrDefault("env", null))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsResultBundlePathOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsResultBundlePathOption.java new file mode 100644 index 000000000..01156e770 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsResultBundlePathOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsResultBundlePathOption> extends + Capabilities, CanSetCapability { + String RESULT_BUNDLE_PATH_OPTION = "resultBundlePath"; + + /** + * Specify the path to the result bundle path as xcodebuild argument for + * WebDriverAgent build under a security flag. WebDriverAgent process must + * start/stop every time to pick up changed value of this property. + * Specifying useNewWDA to true may help there. Please read man xcodebuild + * for more details. + * + * @param path The path where the resulting XCTest bundle should be stored. + * @return self instance for chaining. + */ + default T setResultBundlePath(String path) { + return amend(RESULT_BUNDLE_PATH_OPTION, path); + } + + /** + * Get the path where the resulting XCTest bundle should be stored. + * + * @return XCTest result bundle path. + */ + default Optional getResultBundlePath() { + return Optional.ofNullable((String) getCapability(RESULT_BUNDLE_PATH_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsScreenshotQualityOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsScreenshotQualityOption.java new file mode 100644 index 000000000..0eb3481f7 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsScreenshotQualityOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsScreenshotQualityOption> extends + Capabilities, CanSetCapability { + String SCREENSHOT_QUALITY_OPTION = "screenshotQuality"; + + /** + * Changes the quality of phone display screenshots following + * xctest/xctimagequality Default value is 1. 0 is the highest and + * 2 is the lowest quality. You can also change it via settings + * command. 0 might cause OutOfMemory crash on high-resolution + * devices like iPad Pro. + * + * @param quality Quality value in range 0..2. + * @return self instance for chaining. + */ + default T setScreenshotQuality(int quality) { + return amend(SCREENSHOT_QUALITY_OPTION, quality); + } + + /** + * Get the screenshot quality value. + * + * @return The screenshot quality value. + */ + default Optional getScreenshotQuality() { + return Optional.ofNullable(toInteger(getCapability(SCREENSHOT_QUALITY_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldTerminateAppOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldTerminateAppOption.java new file mode 100644 index 000000000..4c92b812f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldTerminateAppOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShouldTerminateAppOption> extends + Capabilities, CanSetCapability { + String SHOULD_TERMINATE_APP_OPTION = "shouldTerminateApp"; + + /** + * Specify if the app should be terminated on session end. + * This capability only has an effect if an application identifier + * has been passed to the test session (either explicitly, + * by setting bundleId, or implicitly, by providing app). + * Default is true unless noReset capability is set to true. + * + * @param value Whether to enforce app termination on session quit. + * @return self instance for chaining. + */ + default T setShouldTerminateApp(boolean value) { + return amend(SHOULD_TERMINATE_APP_OPTION, value); + } + + /** + * Get whether to enforce app termination on session quit. + * + * @return True or false. + */ + default Optional doesTerminateApp() { + return Optional.ofNullable(toSafeBoolean(getCapability(SHOULD_TERMINATE_APP_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldUseSingletonTestManagerOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldUseSingletonTestManagerOption.java new file mode 100644 index 000000000..16ee1d2cd --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsShouldUseSingletonTestManagerOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShouldUseSingletonTestManagerOption> extends + Capabilities, CanSetCapability { + String SHOULD_USE_SINGLETON_TEST_MANAGER_OPTION = "shouldUseSingletonTestManager"; + + /** + * Enforce usage of the default proxy for test management within WebDriverAgent. + * + * @return self instance for chaining. + */ + default T shouldUseSingletonTestManager() { + return amend(SHOULD_USE_SINGLETON_TEST_MANAGER_OPTION, true); + } + + /** + * Use default proxy for test management within WebDriverAgent. Setting this to false + * sometimes helps with socket hangup problems. Defaults to true. + * + * @param value Whether to use the default proxy for test management within WebDriverAgent. + * @return self instance for chaining. + */ + default T setShouldUseSingletonTestManager(boolean value) { + return amend(SHOULD_USE_SINGLETON_TEST_MANAGER_OPTION, value); + } + + /** + * Get whether to use the default proxy for test management within WebDriverAgent. + * + * @return True or false. + */ + default Optional doesUseSingletonTestManager() { + return Optional.ofNullable(toSafeBoolean(getCapability(SHOULD_USE_SINGLETON_TEST_MANAGER_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsShowXcodeLogOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsShowXcodeLogOption.java new file mode 100644 index 000000000..902b67ced --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsShowXcodeLogOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShowXcodeLogOption> extends + Capabilities, CanSetCapability { + String SHOW_XCODE_LOG_OPTION = "showXcodeLog"; + + /** + * Enforce to display the output of the Xcode command used to run the tests + * in Appium logs. + * + * @return self instance for chaining. + */ + default T showXcodeLog() { + return amend(SHOW_XCODE_LOG_OPTION, true); + } + + /** + * Whether to display the output of the Xcode command used to run the tests in + * Appium logs. If this is true, there will be lots of extra logging at startup. + * Defaults to false. + * + * @param value Whether to display the output of the Xcode command used to run the tests. + * @return self instance for chaining. + */ + default T setShowXcodeLog(boolean value) { + return amend(SHOW_XCODE_LOG_OPTION, value); + } + + /** + * Get whether to display the output of the Xcode command used to run the tests. + * + * @return True or false. + */ + default Optional doesShowXcodeLog() { + return Optional.ofNullable(toSafeBoolean(getCapability(SHOW_XCODE_LOG_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsSimpleIsVisibleCheckOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsSimpleIsVisibleCheckOption.java new file mode 100644 index 000000000..72bebc33a --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsSimpleIsVisibleCheckOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSimpleIsVisibleCheckOption> extends + Capabilities, CanSetCapability { + String SIMPLE_IS_VISIBLE_CHECK_OPTION = "simpleIsVisibleCheck"; + + /** + * Enforce usage of native methods for determining visibility of elements. + * + * @return self instance for chaining. + */ + default T simpleIsVisibleCheck() { + return amend(SIMPLE_IS_VISIBLE_CHECK_OPTION, true); + } + + /** + * Use native methods for determining visibility of elements. + * In some cases this takes a long time. Setting this capability to false will + * cause the system to use the position and size of elements to make sure they + * are visible on the screen. This can, however, lead to false results in some + * situations. Defaults to false, except iOS 9.3, where it defaults to true. + * + * @param value Whether to use native methods for determining visibility of elements + * @return self instance for chaining. + */ + default T setSimpleIsVisibleCheck(boolean value) { + return amend(SIMPLE_IS_VISIBLE_CHECK_OPTION, value); + } + + /** + * Get whether to use native methods for determining visibility of elements. + * + * @return True or false. + */ + default Optional doesSimpleIsVisibleCheck() { + return Optional.ofNullable(toSafeBoolean(getCapability(SIMPLE_IS_VISIBLE_CHECK_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUpdatedWdaBundleIdOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUpdatedWdaBundleIdOption.java new file mode 100644 index 000000000..2e4da983f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUpdatedWdaBundleIdOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsUpdatedWdaBundleIdOption> extends + Capabilities, CanSetCapability { + String UPDATED_WDA_BUNDLE_ID_OPTION = "updatedWDABundleId"; + + /** + * Bundle id to update WDA to before building and launching on real devices. + * This bundle id must be associated with a valid provisioning profile. + * + * @param identifier Bundle identifier. + * @return self instance for chaining. + */ + default T setUpdatedWdaBundleId(String identifier) { + return amend(UPDATED_WDA_BUNDLE_ID_OPTION, identifier); + } + + /** + * Get the WDA bundle identifier. + * + * @return Identifier value. + */ + default Optional getUpdatedWdaBundleId() { + return Optional.ofNullable((String) getCapability(UPDATED_WDA_BUNDLE_ID_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNativeCachingStrategyOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNativeCachingStrategyOption.java new file mode 100644 index 000000000..10f394aee --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNativeCachingStrategyOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUseNativeCachingStrategyOption> extends + Capabilities, CanSetCapability { + String USE_NATIVE_CACHING_STRATEGY_OPTION = "useNativeCachingStrategy"; + + /** + * Set this capability to false in order to use the custom elements caching + * strategy. This might help to avoid stale element exception on property + * change. By default, the native XCTest cache resolution is used (true) + * for all native locators (e.g. all, but xpath). + * + * @param value Whether to use the native caching strategy. + * @return self instance for chaining. + */ + default T setUseNativeCachingStrategy(boolean value) { + return amend(USE_NATIVE_CACHING_STRATEGY_OPTION, value); + } + + /** + * Get whether to use the native caching strategy. + * + * @return True or false. + */ + default Optional doesUseNativeCachingStrategy() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_NATIVE_CACHING_STRATEGY_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNewWdaOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNewWdaOption.java new file mode 100644 index 000000000..2422c078c --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseNewWdaOption.java @@ -0,0 +1,70 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUseNewWdaOption> extends + Capabilities, CanSetCapability { + String USE_NEW_WDA_OPTION = "useNewWDA"; + + /** + * Enforce uninstall of any existing WebDriverAgent app on the device under test. + * + * @return self instance for chaining. + */ + default T useNewWDA() { + return amend(USE_NEW_WDA_OPTION, true); + } + + /** + * If true, forces uninstall of any existing WebDriverAgent app on device. + * Set it to true if you want to apply different startup options for WebDriverAgent + * for each session. Although, it is only guaranteed to work stable on Simulator. + * Real devices require WebDriverAgent client to run for as long as possible without + * reinstall/restart to avoid issues like + * https://github.com/facebook/WebDriverAgent/issues/507. The false value + * (the default behaviour since driver version 2.35.0) will try to + * detect currently running WDA listener executed by previous testing session(s) + * and reuse it if possible, which is highly recommended for real device testing + * and to speed up suites of multiple tests in general. A new WDA session will be + * triggered at the default URL (http://localhost:8100) if WDA is not listening and + * webDriverAgentUrl capability is not set. The negative/unset value of useNewWDA + * capability has no effect prior to xcuitest driver version 2.35.0. + * + * @param value Whether to force uninstall of any existing WebDriverAgent app on device. + * @return self instance for chaining. + */ + default T setUseNewWDA(boolean value) { + return amend(USE_NEW_WDA_OPTION, value); + } + + /** + * Get whether to uninstall of any existing WebDriverAgent app on the device under test. + * + * @return True or false. + */ + default Optional doesUseNewWDA() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_NEW_WDA_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePrebuiltWdaOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePrebuiltWdaOption.java new file mode 100644 index 000000000..bf4ce84ff --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePrebuiltWdaOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUsePrebuiltWdaOption> extends + Capabilities, CanSetCapability { + String USE_PREBUILT_WDA_OPTION = "usePrebuiltWDA"; + + /** + * Enforce to skip the build phase of running the WDA app. + * + * @return self instance for chaining. + */ + default T usePrebuiltWda() { + return amend(USE_PREBUILT_WDA_OPTION, true); + } + + /** + * Skips the build phase of running the WDA app. Building is then the responsibility + * of the user. Only works for Xcode 8+. Defaults to false. + * + * @param value Whether to skip the build phase of running the WDA app. + * @return self instance for chaining. + */ + default T setUsePrebuiltWda(boolean value) { + return amend(USE_PREBUILT_WDA_OPTION, value); + } + + /** + * Get whether to skip the build phase of running the WDA app. + * + * @return True or false. + */ + default Optional doesUsePrebuiltWda() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_PREBUILT_WDA_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseSimpleBuildTestOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseSimpleBuildTestOption.java new file mode 100644 index 000000000..8b455e629 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseSimpleBuildTestOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUseSimpleBuildTestOption> extends + Capabilities, CanSetCapability { + String USE_SIMPLE_BUILD_TEST_OPTION = "useSimpleBuildTest"; + + /** + * Enforce usage of simple build test. + * + * @return self instance for chaining. + */ + default T useSimpleBuildTest() { + return amend(USE_SIMPLE_BUILD_TEST_OPTION, true); + } + + /** + * Build with build and run test with test in xcodebuild for all Xcode versions if + * this is true, or build with build-for-testing and run tests with + * test-without-building for over Xcode 8 if this is false. Defaults to false. + * + * @param value Whether to use simple build test. + * @return self instance for chaining. + */ + default T setUseSimpleBuildTest(boolean value) { + return amend(USE_SIMPLE_BUILD_TEST_OPTION, value); + } + + /** + * Get whether to use simple build test. + * + * @return True or false. + */ + default Optional doesUseSimpleBuildTest() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_SIMPLE_BUILD_TEST_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseXctestrunFileOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseXctestrunFileOption.java new file mode 100644 index 000000000..f29c55a77 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUseXctestrunFileOption.java @@ -0,0 +1,69 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUseXctestrunFileOption> extends + Capabilities, CanSetCapability { + String USE_XCTESTRUN_FILE_OPTION = "useXctestrunFile"; + + /** + * Enforce usage of .xctestrun file to launch WDA. + * + * @return self instance for chaining. + */ + default T useXctestrunFile() { + return amend(USE_XCTESTRUN_FILE_OPTION, true); + } + + /** + * Use Xctestrun file to launch WDA. It will search for such file in bootstrapPath. + * Expected name of file is WebDriverAgentRunner_iphoneos<sdkVersion>-arm64.xctestrun for + * real device and WebDriverAgentRunner_iphonesimulator<sdkVersion>-x86_64.xctestrun for + * simulator. One can do build-for-testing for WebDriverAgent project for simulator and + * real device and then you will see Product Folder like this and you need to copy content + * of this folder at bootstrapPath location. Since this capability expects that you have + * already built WDA project, it neither checks whether you have necessary dependencies to + * build WDA nor will it try to build project. Defaults to false. Tips: Xcodebuild builds for the + * target platform version. We'd recommend you to build with minimal OS version which you'd + * like to run as the original WDA module. e.g. If you build WDA for 12.2, the module cannot + * run on iOS 11.4 because of loading some module error on simulator. A module built with 11.4 + * can work on iOS 12.2. (This is xcodebuild's expected behaviour.) + * + * @param value Whether to use .xctestrun file to launch WDA. + * @return self instance for chaining. + */ + default T setUseXctestrunFile(boolean value) { + return amend(USE_XCTESTRUN_FILE_OPTION, value); + } + + /** + * Get whether to use of .xctestrun file to launch WDA + * + * @return True or false. + */ + default Optional doesUseXctestrunFile() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_XCTESTRUN_FILE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java new file mode 100644 index 000000000..0d9ffda35 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java @@ -0,0 +1,58 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsWaitForIdleTimeoutOption> extends + Capabilities, CanSetCapability { + String WAIT_FOR_IDLE_TIMEOUT_OPTION = "waitForIdleTimeout"; + + /** + * The time to wait until the application under test is idling. + * XCTest requires the app's main thread to be idling in order to execute any action on it, + * so WDA might not even start/freeze if the app under test is constantly hogging the main + * thread. The default value is 10 (seconds). Setting it to zero disables idling checks completely + * (not recommended) and has the same effect as setting waitForQuiescence to false. + * Available since Appium 1.20.0. + * + * @param timeout Idle timeout. + * @return self instance for chaining. + */ + default T setWaitForIdleTimeout(Duration timeout) { + return amend(WAIT_FOR_IDLE_TIMEOUT_OPTION, timeout.toMillis() / 1000.0); + } + + /** + * Get the maximum timeout to wait until WDA responds to HTTP requests. + * + * @return Timeout value. + */ + default Optional getWaitForIdleTimeout() { + return Optional.ofNullable(getCapability(WAIT_FOR_IDLE_TIMEOUT_OPTION)) + .map(CapabilityHelpers::toDouble) + .map((d) -> toDuration((long) (d * 1000.0))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForQuiescenceOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForQuiescenceOption.java new file mode 100644 index 000000000..9c49e469a --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForQuiescenceOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsWaitForQuiescenceOption> extends + Capabilities, CanSetCapability { + String WAIT_FOR_QUIESCENCE_OPTION = "waitForQuiescence"; + + /** + * It allows to turn on/off waiting for application quiescence in WebDriverAgent, + * while performing queries. The default value is true. You can avoid this kind + * of issues if you turn it off. Consider using waitForIdleTimeout capability + * instead for this purpose since Appium 1.20.0. + * + * @param value Whether to wait for application quiescence. + * @return self instance for chaining. + */ + default T setWaitForQuiescence(boolean value) { + return amend(WAIT_FOR_QUIESCENCE_OPTION, value); + } + + /** + * Get whether to wait for application quiescence. + * + * @return True or false. + */ + default Optional doesWaitForQuiescence() { + return Optional.ofNullable(toSafeBoolean(getCapability(WAIT_FOR_QUIESCENCE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaBaseUrlOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaBaseUrlOption.java new file mode 100644 index 000000000..2404aa5ef --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaBaseUrlOption.java @@ -0,0 +1,66 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.net.URL; +import java.util.Optional; + +public interface SupportsWdaBaseUrlOption> extends + Capabilities, CanSetCapability { + String WDA_BASE_URL_OPTION = "wdaBaseUrl"; + + /** + * This value, if specified, will be used as a prefix to build a custom + * WebDriverAgent url. It is different from webDriverAgentUrl, because + * if the latter is set then it expects WebDriverAgent to be already + * listening and skips the building phase. Defaults to http://localhost. + * + * @param url The URL prefix. + * @return self instance for chaining. + */ + default T setWdaBaseUrl(URL url) { + return amend(WDA_BASE_URL_OPTION, url.toString()); + } + + /** + * This value, if specified, will be used as a prefix to build a custom + * WebDriverAgent url. It is different from webDriverAgentUrl, because + * if the latter is set then it expects WebDriverAgent to be already + * listening and skips the building phase. Defaults to http://localhost. + * + * @param url The URL prefix. + * @return self instance for chaining. + */ + default T setWdaBaseUrl(String url) { + return amend(WDA_BASE_URL_OPTION, url); + } + + /** + * Get a prefix to build a custom WebDriverAgent URL. + * + * @return The URL prefix. + */ + default Optional getWdaBaseUrl() { + return Optional.ofNullable(getCapability(WDA_BASE_URL_OPTION)) + .map(CapabilityHelpers::toUrl); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaConnectionTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaConnectionTimeoutOption.java new file mode 100644 index 000000000..8885b8c3e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaConnectionTimeoutOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsWdaConnectionTimeoutOption> extends + Capabilities, CanSetCapability { + String WDA_CONNECTION_TIMEOUT_OPTION = "wdaConnectionTimeout"; + + /** + * Connection timeout to wait for a response from WebDriverAgent. + * Defaults to 240000ms. + * + * @param timeout WDA connection timeout. + * @return self instance for chaining. + */ + default T setWdaConnectionTimeout(Duration timeout) { + return amend(WDA_CONNECTION_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait until WDA responds to HTTP requests. + * + * @return Timeout value. + */ + default Optional getWdaConnectionTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(WDA_CONNECTION_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java new file mode 100644 index 000000000..4d35bb5c4 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsWdaEventloopIdleDelayOption> extends + Capabilities, CanSetCapability { + String WDA_EVENTLOOP_IDLE_DELAY_OPTION = "wdaEventloopIdleDelay"; + + /** + * Delays the invocation of -[XCUIApplicationProcess setEventLoopHasIdled:] by the + * duration specified with this capability. This can help quiescence apps + * that fail to do so for no obvious reason (and creating a session fails for + * that reason). This increases the time for session creation + * because -[XCUIApplicationProcess setEventLoopHasIdled:] is called multiple times. + * If you enable this capability start with at least 3 seconds and try increasing it, + * if creating the session still fails. Defaults to 0. + * + * @param duration Idle duration. + * @return self instance for chaining. + */ + default T setWdaEventloopIdleDelay(Duration duration) { + return amend(WDA_EVENTLOOP_IDLE_DELAY_OPTION, duration.toMillis() / 1000.0); + } + + /** + * Get the event loop idle delay. + * + * @return Idle duration. + */ + default Optional getWdaEventloopIdleDelay() { + return Optional.ofNullable(getCapability(WDA_EVENTLOOP_IDLE_DELAY_OPTION)) + .map(CapabilityHelpers::toDouble) + .map((d) -> toDuration((long) (d * 1000.0))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLaunchTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLaunchTimeoutOption.java new file mode 100644 index 000000000..96ec72521 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLaunchTimeoutOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsWdaLaunchTimeoutOption> extends + Capabilities, CanSetCapability { + String WDA_LAUNCH_TIMEOUT_OPTION = "wdaLaunchTimeout"; + + /** + * Timeout to wait for WebDriverAgent to be pingable, + * e.g. finishes building. Defaults to 60000ms. + * + * @param timeout Timeout to wait until WDA is listening. + * @return self instance for chaining. + */ + default T setWdaLaunchTimeout(Duration timeout) { + return amend(WDA_LAUNCH_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait until WDA is listening. + * + * @return Timeout value. + */ + default Optional getWdaLaunchTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(WDA_LAUNCH_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLocalPortOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLocalPortOption.java new file mode 100644 index 000000000..a011edeac --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaLocalPortOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsWdaLocalPortOption> extends + Capabilities, CanSetCapability { + String WDA_LOCAL_PORT_OPTION = "wdaLocalPort"; + + /** + * This value, if specified, will be used to forward traffic from + * Mac host to real ios devices over USB. + * Default value is the same as the port number used by WDA on + * the device under test (8100). + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setWdaLocalPort(int port) { + return amend(WDA_LOCAL_PORT_OPTION, port); + } + + /** + * Get the local port number where the WDA traffic is being forwarded. + * + * @return The port number. + */ + default Optional getWdaLocalPort() { + return Optional.ofNullable(toInteger(getCapability(WDA_LOCAL_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetriesOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetriesOption.java new file mode 100644 index 000000000..e69a52d42 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetriesOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsWdaStartupRetriesOption> extends + Capabilities, CanSetCapability { + String WDA_STARTUP_RETRIES_OPTION = "wdaStartupRetries"; + + /** + * Number of times to try to build and launch WebDriverAgent onto the device. + * Defaults to 2. + * + * @param count Retries count. + * @return self instance for chaining. + */ + default T setWdaStartupRetries(int count) { + return amend(WDA_STARTUP_RETRIES_OPTION, count); + } + + /** + * Get number of retries before to fail WDA deployment. + * + * @return Retries count. + */ + default Optional getWdaStartupRetries() { + return Optional.ofNullable(toInteger(getCapability(WDA_STARTUP_RETRIES_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetryIntervalOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetryIntervalOption.java new file mode 100644 index 000000000..c1fe04a35 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaStartupRetryIntervalOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsWdaStartupRetryIntervalOption> extends + Capabilities, CanSetCapability { + String WDA_STARTUP_RETRY_INTERVAL_OPTION = "wdaStartupRetryInterval"; + + /** + * Time interval to wait between tries to build and launch WebDriverAgent. + * Defaults to 10000ms. + * + * @param interval Interval value. + * @return self instance for chaining. + */ + default T setWdaStartupRetryInterval(Duration interval) { + return amend(WDA_STARTUP_RETRY_INTERVAL_OPTION, interval.toMillis()); + } + + /** + * Get the interval to wait between tries to build and launch WebDriverAgent. + * + * @return Interval value. + */ + default Optional getWdaStartupRetryInterval() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(WDA_STARTUP_RETRY_INTERVAL_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWebDriverAgentUrlOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWebDriverAgentUrlOption.java new file mode 100644 index 000000000..a985e280b --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWebDriverAgentUrlOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.wda; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.net.URL; +import java.util.Optional; + +public interface SupportsWebDriverAgentUrlOption> extends + Capabilities, CanSetCapability { + String WEB_DRIVER_AGENT_URL_OPTION = "webDriverAgentUrl"; + + /** + * If provided, Appium will connect to an existing WebDriverAgent + * instance at this URL instead of starting a new one. + * + * @param url The URL where WDA is listening. + * @return self instance for chaining. + */ + default T setWebDriverAgentUrl(URL url) { + return amend(WEB_DRIVER_AGENT_URL_OPTION, url.toString()); + } + + /** + * If provided, Appium will connect to an existing WebDriverAgent + * instance at this URL instead of starting a new one. + * + * @param url The URL where WDA is listening. + * @return self instance for chaining. + */ + default T setWebDriverAgentUrl(String url) { + return amend(WEB_DRIVER_AGENT_URL_OPTION, url); + } + + /** + * Get the WDA URL. + * + * @return The URL where WDA is listening. + */ + default Optional getWebDriverAgentUrl() { + return Optional.ofNullable(getCapability(WEB_DRIVER_AGENT_URL_OPTION)) + .map(CapabilityHelpers::toUrl); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java new file mode 100644 index 000000000..fcecbab8c --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java @@ -0,0 +1,56 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsXcodeCertificateOptions> extends + Capabilities, CanSetCapability { + String XCODE_ORG_ID_OPTION = "xcodeOrgId"; + String XCODE_SIGNING_ID_OPTION = "xcodeSigningId"; + String DEFAULT_XCODE_SIGNING_ID = "iPhone Developer"; + + /** + * Provides a signing certificate for WebDriverAgent compilation. + * If signing id is not provided/null then it defaults to "iPhone Developer" + * + * @param cert Certificate credentials. + * @return self instance for chaining. + */ + default T setXcodeCertificate(XcodeCertificate cert) { + String signingId = Optional.ofNullable(cert.getXcodeSigningId()) + .orElse(DEFAULT_XCODE_SIGNING_ID); + return amend(XCODE_ORG_ID_OPTION, cert.getXcodeOrgId()) + .amend(XCODE_SIGNING_ID_OPTION, signingId); + } + + /** + * Get a signing certificate for WebDriverAgent compilation. + * + * @return Certificate value. + */ + default Optional getXcodeCertificate() { + String orgId = (String) getCapability(XCODE_ORG_ID_OPTION); + String signingId = (String) getCapability(XCODE_SIGNING_ID_OPTION); + return Optional.ofNullable(orgId) + .map((x) -> new XcodeCertificate(orgId, signingId)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/XcodeCertificate.java b/src/main/java/io/appium/java_client/ios/options/wda/XcodeCertificate.java new file mode 100644 index 000000000..49d2d4639 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/XcodeCertificate.java @@ -0,0 +1,36 @@ +/* + * 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.options.wda; + +import lombok.Data; +import lombok.ToString; + +@ToString() +@Data() +public class XcodeCertificate { + private final String xcodeOrgId; + private final String xcodeSigningId; + + public XcodeCertificate(String xcodeOrgId, String xcodeSigningId) { + this.xcodeOrgId = xcodeOrgId; + this.xcodeSigningId = xcodeSigningId; + } + + public XcodeCertificate(String xcodeOrgId) { + this(xcodeOrgId, null); + } +} From 29797ceeab77e121eaaf7077895e6ec17a1f736a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 08:58:27 +0200 Subject: [PATCH 010/501] feat: Add WebDriverAgent-related options of XCUITest driver (#1554) --- .../android/options/UiAutomator2Options.java | 2 +- .../ios/options/XCUITestOptions.java | 42 +++++++++- .../simulator/PasteboardSyncState.java | 5 ++ ...upportsCalendarAccessAuthorizedOption.java | 61 +++++++++++++++ .../SupportsCalendarFormatOption.java | 47 ++++++++++++ ...SupportsConnectHardwareKeyboardOption.java | 63 +++++++++++++++ .../SupportsCustomSslCertOption.java | 48 ++++++++++++ ...tsEnforceFreshSimulatorCreationOption.java | 59 ++++++++++++++ ...mulatorSoftwareKeyboardPresenceOption.java | 65 ++++++++++++++++ ...pportsIosSimulatorLogsPredicateOption.java | 47 ++++++++++++ .../SupportsKeepKeyChainsOption.java | 59 ++++++++++++++ ...upportsKeychainsExcludePatternsOption.java | 53 +++++++++++++ .../simulator/SupportsPermissionsOption.java | 76 +++++++++++++++++++ .../simulator/SupportsReduceMotionOption.java | 60 +++++++++++++++ .../simulator/SupportsScaleFactorOption.java | 53 +++++++++++++ ...SupportsShutdownOtherSimulatorsOption.java | 64 ++++++++++++++++ ...SupportsSimulatorDevicesSetPathOption.java | 50 ++++++++++++ ...imulatorPasteboardAutomaticSyncOption.java | 52 +++++++++++++ ...SupportsSimulatorStartupTimeoutOption.java | 55 ++++++++++++++ .../SupportsSimulatorTracePointerOption.java | 61 +++++++++++++++ .../SupportsSimulatorWindowCenterOption.java | 50 ++++++++++++ .../SupportsWebkitResponseTimeoutOption.java | 52 +++++++++++++ .../options}/SupportsIsHeadlessOption.java | 10 +-- 23 files changed, 1126 insertions(+), 8 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarAccessAuthorizedOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarFormatOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsConnectHardwareKeyboardOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsEnforceFreshSimulatorCreationOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsForceSimulatorSoftwareKeyboardPresenceOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsIosSimulatorLogsPredicateOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeepKeyChainsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeychainsExcludePatternsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsReduceMotionOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsScaleFactorOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsShutdownOtherSimulatorsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorDevicesSetPathOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorStartupTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorWindowCenterOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/SupportsWebkitResponseTimeoutOption.java rename src/main/java/io/appium/java_client/{android/options/avd => remote/options}/SupportsIsHeadlessOption.java (82%) diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index 9185994f1..ee9ae2755 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -50,7 +50,7 @@ import io.appium.java_client.android.options.avd.SupportsAvdOption; import io.appium.java_client.android.options.avd.SupportsAvdReadyTimeoutOption; import io.appium.java_client.android.options.avd.SupportsGpsEnabledOption; -import io.appium.java_client.android.options.avd.SupportsIsHeadlessOption; +import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.android.options.avd.SupportsNetworkSpeedOption; import io.appium.java_client.android.options.context.SupportsAutoWebviewTimeoutOption; import io.appium.java_client.android.options.context.SupportsChromeLoggingPrefsOption; diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index be0bd03be..f06086820 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -22,6 +22,25 @@ import io.appium.java_client.ios.options.app.SupportsLocalizableStringsDirOption; import io.appium.java_client.ios.options.general.SupportsIncludeDeviceCapsToSessionInfoOption; import io.appium.java_client.ios.options.general.SupportsResetLocationServiceOption; +import io.appium.java_client.ios.options.simulator.SupportsCalendarAccessAuthorizedOption; +import io.appium.java_client.ios.options.simulator.SupportsCalendarFormatOption; +import io.appium.java_client.ios.options.simulator.SupportsConnectHardwareKeyboardOption; +import io.appium.java_client.ios.options.simulator.SupportsCustomSslCertOption; +import io.appium.java_client.ios.options.simulator.SupportsEnforceFreshSimulatorCreationOption; +import io.appium.java_client.ios.options.simulator.SupportsForceSimulatorSoftwareKeyboardPresenceOption; +import io.appium.java_client.ios.options.simulator.SupportsIosSimulatorLogsPredicateOption; +import io.appium.java_client.ios.options.simulator.SupportsKeepKeyChainsOption; +import io.appium.java_client.ios.options.simulator.SupportsKeychainsExcludePatternsOption; +import io.appium.java_client.ios.options.simulator.SupportsPermissionsOption; +import io.appium.java_client.ios.options.simulator.SupportsReduceMotionOption; +import io.appium.java_client.ios.options.simulator.SupportsScaleFactorOption; +import io.appium.java_client.ios.options.simulator.SupportsShutdownOtherSimulatorsOption; +import io.appium.java_client.ios.options.simulator.SupportsSimulatorDevicesSetPathOption; +import io.appium.java_client.ios.options.simulator.SupportsSimulatorPasteboardAutomaticSyncOption; +import io.appium.java_client.ios.options.simulator.SupportsSimulatorStartupTimeoutOption; +import io.appium.java_client.ios.options.simulator.SupportsSimulatorTracePointerOption; +import io.appium.java_client.ios.options.simulator.SupportsSimulatorWindowCenterOption; +import io.appium.java_client.ios.options.simulator.SupportsWebkitResponseTimeoutOption; import io.appium.java_client.ios.options.wda.SupportsAllowProvisioningDeviceRegistrationOption; import io.appium.java_client.ios.options.wda.SupportsAutoAcceptAlertsOption; import io.appium.java_client.ios.options.wda.SupportsAutoDismissAlertsOption; @@ -63,6 +82,7 @@ import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; import io.appium.java_client.remote.options.SupportsDeviceNameOption; import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.remote.options.SupportsLanguageOption; import io.appium.java_client.remote.options.SupportsLocaleOption; import io.appium.java_client.remote.options.SupportsOrientationOption; @@ -123,8 +143,28 @@ public class XCUITestOptions extends BaseOptions implements SupportsShouldTerminateAppOption, SupportsForceAppLaunchOption, SupportsUseNativeCachingStrategyOption, - // TODO: Simulator options: https://github.com/appium/appium-xcuitest-driver#simulator + // Simulator options: https://github.com/appium/appium-xcuitest-driver#simulator SupportsOrientationOption, + SupportsScaleFactorOption, + SupportsConnectHardwareKeyboardOption, + SupportsForceSimulatorSoftwareKeyboardPresenceOption, + SupportsCalendarAccessAuthorizedOption, + SupportsCalendarFormatOption, + SupportsIsHeadlessOption, + SupportsSimulatorWindowCenterOption, + SupportsSimulatorStartupTimeoutOption, + SupportsSimulatorTracePointerOption, + SupportsShutdownOtherSimulatorsOption, + SupportsEnforceFreshSimulatorCreationOption, + SupportsKeepKeyChainsOption, + SupportsKeychainsExcludePatternsOption, + SupportsReduceMotionOption, + SupportsPermissionsOption, + SupportsIosSimulatorLogsPredicateOption, + SupportsSimulatorPasteboardAutomaticSyncOption, + SupportsSimulatorDevicesSetPathOption, + SupportsCustomSslCertOption, + SupportsWebkitResponseTimeoutOption, // TODO: Web context options: https://github.com/appium/appium-xcuitest-driver#web-context SupportsAutoWebViewOption, // TODO: Other options: https://github.com/appium/appium-xcuitest-driver#other diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java b/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java new file mode 100644 index 000000000..2252a37bf --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java @@ -0,0 +1,5 @@ +package io.appium.java_client.ios.options.simulator; + +public enum PasteboardSyncState { + ON, OFF, SYSTEM +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarAccessAuthorizedOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarAccessAuthorizedOption.java new file mode 100644 index 000000000..800bac79e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarAccessAuthorizedOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsCalendarAccessAuthorizedOption> extends + Capabilities, CanSetCapability { + String CALENDAR_ACCESS_AUTHORIZED_OPTION = "calendarAccessAuthorized"; + + /** + * Enable calendar access on IOS Simulator. + * + * @return self instance for chaining. + */ + default T calendarAccessAuthorized() { + return amend(CALENDAR_ACCESS_AUTHORIZED_OPTION, true); + } + + /** + * Set this to true if you want to enable calendar access on IOS Simulator + * with given bundleId. Set to false, if you want to disable calendar access + * on IOS Simulator with given bundleId. If not set, the calendar + * authorization status will not be set. + * + * @param value Whether to enable calendar access on IOS Simulator. + * @return self instance for chaining. + */ + default T setCalendarAccessAuthorized(boolean value) { + return amend(CALENDAR_ACCESS_AUTHORIZED_OPTION, value); + } + + /** + * Get whether to enable calendar access on IOS Simulator. + * + * @return True or false. + */ + default Optional doesCalendarAccessAuthorized() { + return Optional.ofNullable(toSafeBoolean(getCapability(CALENDAR_ACCESS_AUTHORIZED_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarFormatOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarFormatOption.java new file mode 100644 index 000000000..f38a31bd2 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCalendarFormatOption.java @@ -0,0 +1,47 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsCalendarFormatOption> extends + Capabilities, CanSetCapability { + String CALENDAR_FORMAT_OPTION = "calendarFormat"; + + /** + * Set calendar format for the iOS Simulator. + * + * @param format Calendar format to set for the iOS Simulator. + * @return self instance for chaining. + */ + default T setCalendarFormat(String format) { + return amend(CALENDAR_FORMAT_OPTION, format); + } + + /** + * Get calendar format to set for the iOS Simulator. + * + * @return Calendar format. + */ + default Optional getCalendarFormat() { + return Optional.ofNullable((String) getCapability(CALENDAR_FORMAT_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsConnectHardwareKeyboardOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsConnectHardwareKeyboardOption.java new file mode 100644 index 000000000..3eed21650 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsConnectHardwareKeyboardOption.java @@ -0,0 +1,63 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsConnectHardwareKeyboardOption> extends + Capabilities, CanSetCapability { + String CONNECT_HARDWARE_KEYBOARD_OPTION = "connectHardwareKeyboard"; + + /** + * Enforce connecting of hardware keyboard to Simulator. + * + * @return self instance for chaining. + */ + default T connectHardwareKeyboard() { + return amend(CONNECT_HARDWARE_KEYBOARD_OPTION, true); + } + + /** + * Set this option to true in order to enable hardware keyboard in Simulator. + * The preference works only when Appium launches a simulator instance with + * this value. It is set to false by default, because this helps to workaround + * some XCTest bugs. connectHardwareKeyboard: true makes + * forceSimulatorSoftwareKeyboardPresence: false if no explicit value is set + * for forceSimulatorSoftwareKeyboardPresence capability since Appium 1.22.0. + * + * @param value Whether to connect hardware keyboard to Simulator. + * @return self instance for chaining. + */ + default T setConnectHardwareKeyboard(boolean value) { + return amend(CONNECT_HARDWARE_KEYBOARD_OPTION, value); + } + + /** + * Get whether to connect hardware keyboard to Simulator. + * + * @return True or false. + */ + default Optional doesConnectHardwareKeyboard() { + return Optional.ofNullable(toSafeBoolean(getCapability(CONNECT_HARDWARE_KEYBOARD_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java new file mode 100644 index 000000000..93611eec1 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java @@ -0,0 +1,48 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsCustomSslCertOption> extends + Capabilities, CanSetCapability { + String CUSTOM_SSLCERT_OPTION = "customSSLCert"; + + /** + * Adds a root SSL certificate to IOS Simulator. + * The certificate content must be provided in PEM format. + * + * @param cert Certificate content in PEM format. + * @return self instance for chaining. + */ + default T setCustomSSLCert(String cert) { + return amend(CUSTOM_SSLCERT_OPTION, cert); + } + + /** + * Get the SSL certificate content. + * + * @return Certificate content. + */ + default Optional setCustomSSLCert() { + return Optional.ofNullable((String) getCapability(CUSTOM_SSLCERT_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsEnforceFreshSimulatorCreationOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsEnforceFreshSimulatorCreationOption.java new file mode 100644 index 000000000..010049af9 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsEnforceFreshSimulatorCreationOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsEnforceFreshSimulatorCreationOption> extends + Capabilities, CanSetCapability { + String ENFORCE_FRESH_SIMULATOR_CREATION_OPTION = "enforceFreshSimulatorCreation"; + + /** + * Enforce creation of a new simulator for each new test session. + * + * @return self instance for chaining. + */ + default T enforceFreshSimulatorCreation() { + return amend(ENFORCE_FRESH_SIMULATOR_CREATION_OPTION, true); + } + + /** + * Creates a new simulator in session creation and deletes it in session deletion. + * Defaults to false. + * + * @param value Whether to create a new simulator for each new test session. + * @return self instance for chaining. + */ + default T setEnforceFreshSimulatorCreation(boolean value) { + return amend(ENFORCE_FRESH_SIMULATOR_CREATION_OPTION, value); + } + + /** + * Get whether to create a new simulator for each new test session. + * + * @return True or false. + */ + default Optional doesEnforceFreshSimulatorCreation() { + return Optional.ofNullable(toSafeBoolean(getCapability(ENFORCE_FRESH_SIMULATOR_CREATION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsForceSimulatorSoftwareKeyboardPresenceOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsForceSimulatorSoftwareKeyboardPresenceOption.java new file mode 100644 index 000000000..ba30bdcaa --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsForceSimulatorSoftwareKeyboardPresenceOption.java @@ -0,0 +1,65 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsForceSimulatorSoftwareKeyboardPresenceOption> extends + Capabilities, CanSetCapability { + String FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE_OPTION = "forceSimulatorSoftwareKeyboardPresence"; + + /** + * Enforce software keyboard presence. + * + * @return self instance for chaining. + */ + default T forceSimulatorSoftwareKeyboardPresence() { + return amend(FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE_OPTION, true); + } + + /** + * Set this option to true in order to turn software keyboard on and turn + * hardware keyboard off in Simulator since Appium 1.22.0. This option helps + * to avoid Keyboard is not present error. It is set to true by default. + * Appium respects preset simulator software/hardware keyboard preference + * when this value is false, so connectHardwareKeyboard: false and + * forceSimulatorSoftwareKeyboardPresence: false means for Appium to keep + * the current Simulator keyboard preferences. This option has priority + * over connectHardwareKeyboard. + * + * @param value Whether to enforce software keyboard presence. + * @return self instance for chaining. + */ + default T setForceSimulatorSoftwareKeyboardPresence(boolean value) { + return amend(FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE_OPTION, value); + } + + /** + * Get to enforce software keyboard presence. + * + * @return True or false. + */ + default Optional doesForceSimulatorSoftwareKeyboardPresence() { + return Optional.ofNullable(toSafeBoolean(getCapability(FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsIosSimulatorLogsPredicateOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsIosSimulatorLogsPredicateOption.java new file mode 100644 index 000000000..da69dc30b --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsIosSimulatorLogsPredicateOption.java @@ -0,0 +1,47 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsIosSimulatorLogsPredicateOption> extends + Capabilities, CanSetCapability { + String IOS_SIMULATOR_LOGS_PREDICATE_OPTION = "iosSimulatorLogsPredicate"; + + /** + * Set the --predicate flag in the ios simulator logs. + * + * @param predicate Predicate value, e.g. 'process != "locationd" AND process != "DTServiceHub"'. + * @return self instance for chaining. + */ + default T setIosSimulatorLogsPredicate(String predicate) { + return amend(IOS_SIMULATOR_LOGS_PREDICATE_OPTION, predicate); + } + + /** + * Get Simulator log filtering predicate. + * + * @return Predicate value. + */ + default Optional getIosSimulatorLogsPredicate() { + return Optional.ofNullable((String) getCapability(IOS_SIMULATOR_LOGS_PREDICATE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeepKeyChainsOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeepKeyChainsOption.java new file mode 100644 index 000000000..cc444192c --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeepKeyChainsOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsKeepKeyChainsOption> extends + Capabilities, CanSetCapability { + String KEEP_KEY_CHAINS_OPTION = "keepKeyChains"; + + /** + * Enforce preservation of Simulator keychains folder after full reset. + * + * @return self instance for chaining. + */ + default T keepKeyChains() { + return amend(KEEP_KEY_CHAINS_OPTION, true); + } + + /** + * Set the capability to true in order to preserve Simulator keychains folder after + * full reset. This feature has no effect on real devices. Defaults to false. + * + * @param value Whether to preserve Simulator keychains after full reset. + * @return self instance for chaining. + */ + default T setKeepKeyChains(boolean value) { + return amend(KEEP_KEY_CHAINS_OPTION, value); + } + + /** + * Get whether to preserve Simulator keychains after full reset. + * + * @return True or false. + */ + default Optional doesKeepKeyChains() { + return Optional.ofNullable(toSafeBoolean(getCapability(KEEP_KEY_CHAINS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeychainsExcludePatternsOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeychainsExcludePatternsOption.java new file mode 100644 index 000000000..960a5ed2e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsKeychainsExcludePatternsOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsKeychainsExcludePatternsOption> extends + Capabilities, CanSetCapability { + String KEYCHAINS_EXCLUDE_PATTERNS_OPTION = "keychainsExcludePatterns"; + + /** + * This capability accepts comma-separated path patterns, + * which are going to be excluded from keychains restore while + * full reset is being performed on Simulator. It might be + * useful if you want to exclude only particular keychain types + * from being restored, like the applications keychain. This + * feature has no effect on real devices. E.g. "*keychain*.db*" + * to exclude applications keychain from being restored + * + * @param patterns Comma-separated list of file exclude patterns. + * @return self instance for chaining. + */ + default T setKeychainsExcludePatterns(String patterns) { + return amend(KEYCHAINS_EXCLUDE_PATTERNS_OPTION, patterns); + } + + /** + * Get keychains exclude patterns. + * + * @return Exclude patterns. + */ + default Optional getKeychainsExcludePatterns() { + return Optional.ofNullable((String) getCapability(KEYCHAINS_EXCLUDE_PATTERNS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java new file mode 100644 index 000000000..2aca0a82a --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java @@ -0,0 +1,76 @@ +/* + * 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.options.simulator; + +import com.google.gson.JsonObject; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsPermissionsOption> extends + Capabilities, CanSetCapability { + String PERMISSIONS_OPTION = "permissions"; + + /** + * Allows to set permissions for the specified application bundle on + * Simulator only. The capability value is expected to be a valid JSON + * with {"bundleId1": {"serviceName1": "serviceStatus1", ...}, ...} + * format. Since Xcode SDK 11.4 Apple provides native APIs to interact with + * application settings. Check the output of xcrun simctl privacy booted + * command to get the list of available permission names. Use yes, no + * and unset as values in order to grant, revoke or reset the corresponding + * permission. Below Xcode SDK 11.4 it is required that applesimutils package + * is installed and available in PATH. The list of available service names + * and statuses can be found at https://github.com/wix/AppleSimulatorUtils. + * + * @param json For example {"com.apple.mobilecal": {"calendar": "YES"}} + * @return self instance for chaining. + */ + default T setPermissions(JsonObject json) { + return amend(PERMISSIONS_OPTION, json.toString()); + } + + /** + * Allows to set permissions for the specified application bundle on + * Simulator only. The capability value is expected to be a valid JSON + * string with {"bundleId1": {"serviceName1": "serviceStatus1", ...}, ...} + * format. Since Xcode SDK 11.4 Apple provides native APIs to interact with + * application settings. Check the output of xcrun simctl privacy booted + * command to get the list of available permission names. Use yes, no + * and unset as values in order to grant, revoke or reset the corresponding + * permission. Below Xcode SDK 11.4 it is required that applesimutils package + * is installed and available in PATH. The list of available service names + * and statuses can be found at https://github.com/wix/AppleSimulatorUtils. + * + * @param json For example {"com.apple.mobilecal": {"calendar": "YES"}} + * @return self instance for chaining. + */ + default T setPermissions(String json) { + return amend(PERMISSIONS_OPTION, json); + } + + /** + * Get Simulator permissions.. + * + * @return Permissions json. + */ + default Optional getPermissions() { + return Optional.ofNullable((String) getCapability(PERMISSIONS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsReduceMotionOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsReduceMotionOption.java new file mode 100644 index 000000000..5cee8feb0 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsReduceMotionOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsReduceMotionOption> extends + Capabilities, CanSetCapability { + String REDUCE_MOTION_OPTION = "reduceMotion"; + + /** + * Enforce reduce motion accessibility preference. + * + * @return self instance for chaining. + */ + default T reduceMotion() { + return amend(REDUCE_MOTION_OPTION, true); + } + + /** + * It allows to turn on/off reduce motion accessibility preference. + * Setting reduceMotion on helps to reduce flakiness during tests. + * Only on simulators. + * + * @param value Whether to turn on/off reduce motion accessibility preference. + * @return self instance for chaining. + */ + default T setReduceMotion(boolean value) { + return amend(REDUCE_MOTION_OPTION, value); + } + + /** + * Get whether to reduce motion accessibility preference. + * + * @return True or false. + */ + default Optional doesReduceMotion() { + return Optional.ofNullable(toSafeBoolean(getCapability(REDUCE_MOTION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsScaleFactorOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsScaleFactorOption.java new file mode 100644 index 000000000..1644da81d --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsScaleFactorOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsScaleFactorOption> extends + Capabilities, CanSetCapability { + String SCALE_FACTOR_OPTION = "scaleFactor"; + + /** + * Simulator scale factor. This is useful to have if the default resolution + * of simulated device is greater than the actual display resolution. + * So you can scale the simulator to see the whole device screen without scrolling. + * Acceptable values for simulators running Xcode SDK 8 and older are: '1.0', + * '0.75', '0.5', '0.33' and '0.25', where '1.0' means 100% scale. + * For simulators running Xcode SDK 9 and above the value could be any valid + * positive float number. + * + * @param scaleFactor Scale factor value. + * @return self instance for chaining. + */ + default T setScaleFactor(String scaleFactor) { + return amend(SCALE_FACTOR_OPTION, scaleFactor); + } + + /** + * Get Simulator scale factor. + * + * @return Scale factor value. + */ + default Optional getScaleFactor() { + return Optional.ofNullable((String) getCapability(SCALE_FACTOR_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsShutdownOtherSimulatorsOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsShutdownOtherSimulatorsOption.java new file mode 100644 index 000000000..1fd54493f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsShutdownOtherSimulatorsOption.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.ios.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShutdownOtherSimulatorsOption> extends + Capabilities, CanSetCapability { + String SHUTDOWN_OTHER_SIMULATORS_OPTION = "shutdownOtherSimulators"; + + /** + * Enforce shutdown of other booted simulators except of the current one. + * + * @return self instance for chaining. + */ + default T shutdownOtherSimulators() { + return amend(SHUTDOWN_OTHER_SIMULATORS_OPTION, true); + } + + /** + * If this capability set to true and the current device under test is an iOS + * Simulator then Appium will try to shutdown all the other running Simulators + * before to start a new session. This might be useful while executing webview + * tests on different devices, since only one device can be debugged remotely + * at once due to an Apple bug. The capability only has an effect if + * --relaxed-security command line argument is provided to the server. + * Defaults to false. + * + * @param value Whether shutdown of other booted simulators except of the current one. + * @return self instance for chaining. + */ + default T setShutdownOtherSimulators(boolean value) { + return amend(SHUTDOWN_OTHER_SIMULATORS_OPTION, value); + } + + /** + * Get whether to shutdown of other booted simulators except of the current one. + * + * @return True or false. + */ + default Optional doesShutdownOtherSimulators() { + return Optional.ofNullable(toSafeBoolean(getCapability(SHUTDOWN_OTHER_SIMULATORS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorDevicesSetPathOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorDevicesSetPathOption.java new file mode 100644 index 000000000..cf6f0df41 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorDevicesSetPathOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSimulatorDevicesSetPathOption> extends + Capabilities, CanSetCapability { + String SIMULATOR_DEVICES_SET_PATH_OPTION = "simulatorDevicesSetPath"; + + /** + * This capability allows to set an alternative path to the simulator devices + * set in case you have multiple sets deployed on your local system. Such + * feature could be useful if you, for example, would like to save disk space + * on the main system volume. + * + * @param path Alternative path to the simulator devices set. + * @return self instance for chaining. + */ + default T setSimulatorDevicesSetPath(String path) { + return amend(SIMULATOR_DEVICES_SET_PATH_OPTION, path); + } + + /** + * Get the alternative path to the simulator devices set. + * + * @return Path string. + */ + default Optional getSimulatorDevicesSetPath() { + return Optional.ofNullable((String) getCapability(SIMULATOR_DEVICES_SET_PATH_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java new file mode 100644 index 000000000..7f99af2e0 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSimulatorPasteboardAutomaticSyncOption> extends + Capabilities, CanSetCapability { + String SIMULATOR_PASTEBOARD_AUTOMATIC_SYNC = "simulatorPasteboardAutomaticSync"; + + /** + * Handle the -PasteboardAutomaticSync flag when simulator process launches. + * It could improve launching simulator performance not to sync pasteboard with + * the system when this value is off. on forces the flag enabled. system does + * not provide the flag to the launching command. on, off, or system is available. + * They are case-insensitive. Defaults to off. + * + * @param state Either on, off or system. + * @return self instance for chaining. + */ + default T setSimulatorPasteboardAutomaticSync(PasteboardSyncState state) { + return amend(SIMULATOR_PASTEBOARD_AUTOMATIC_SYNC, state.toString().toLowerCase()); + } + + /** + * Get the pasteboard automation sync state. + * + * @return Pasteboard sync state. + */ + default Optional getSimulatorPasteboardAutomaticSync() { + return Optional.ofNullable(getCapability(SIMULATOR_PASTEBOARD_AUTOMATIC_SYNC)) + .map((v) -> PasteboardSyncState.valueOf(String.valueOf(v).toUpperCase())); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorStartupTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorStartupTimeoutOption.java new file mode 100644 index 000000000..c3e593d7c --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorStartupTimeoutOption.java @@ -0,0 +1,55 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsSimulatorStartupTimeoutOption> extends + Capabilities, CanSetCapability { + String SIMULATOR_STARTUP_TIMEOUT_OPTION = "simulatorStartupTimeout"; + + /** + * Allows to change the default timeout for Simulator startup. + * By default, this value is set to 120000ms (2 minutes), + * although the startup could take longer on a weak hardware + * or if other concurrent processes use much system resources + * during the boot up procedure. + * + * @param timeout Simulator startup timeout. + * @return self instance for chaining. + */ + default T setSimulatorStartupTimeout(Duration timeout) { + return amend(SIMULATOR_STARTUP_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the Simulator startup timeout. + * + * @return Timeout value. + */ + default Optional getSimulatorStartupTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(SIMULATOR_STARTUP_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java new file mode 100644 index 000000000..a0341725a --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSimulatorTracePointerOption> extends + Capabilities, CanSetCapability { + String SIMULATOR_TRACE_POINTER_OPTION = "simulatorTracePointer"; + + /** + * Enforce highlight of pointer moves in the Simulator window. + * + * @return self instance for chaining. + */ + default T simulatorTracePointer() { + return amend(SIMULATOR_TRACE_POINTER_OPTION, true); + } + + /** + * Whether to highlight pointer moves in the Simulator window. + * The Simulator UI client must be shut down before the session + * startup in order for this capability to be applied properly. + * false by default. + * + * @param value Whether to highlight pointer moves in the Simulator window. + * @return self instance for chaining. + */ + default T setSimulatorTracePointer(boolean value) { + return amend(SIMULATOR_TRACE_POINTER_OPTION, value); + } + + /** + * Get whether to highlight pointer moves in the Simulator window. + * + * @return True or false. + */ + default Optional doesSimulatorTracePointerd() { + return Optional.ofNullable(toSafeBoolean(getCapability(SIMULATOR_TRACE_POINTER_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorWindowCenterOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorWindowCenterOption.java new file mode 100644 index 000000000..480e0286e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorWindowCenterOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSimulatorWindowCenterOption> extends + Capabilities, CanSetCapability { + String SIMULATOR_WINDOW_CENTER_OPTION = "simulatorWindowCenter"; + + /** + * Allows to explicitly set the coordinates of Simulator window center + * for Xcode9+ SDK. This capability only has an effect if Simulator + * window has not been opened yet for the current session before it started. + * e.g. "{-100.0,100.0}" or "{500,500}", spaces are not allowed + * + * @param coordinates Window center coordinates. + * @return self instance for chaining. + */ + default T setSimulatorWindowCenter(String coordinates) { + return amend(SIMULATOR_WINDOW_CENTER_OPTION, coordinates); + } + + /** + * Get Simulator window center coordinates. + * + * @return Coordinates string. + */ + default Optional getSimulatorWindowCenter() { + return Optional.ofNullable((String) getCapability(SIMULATOR_WINDOW_CENTER_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsWebkitResponseTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsWebkitResponseTimeoutOption.java new file mode 100644 index 000000000..1ddd413ec --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsWebkitResponseTimeoutOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsWebkitResponseTimeoutOption> extends + Capabilities, CanSetCapability { + String WEBKIT_RESPONSE_TIMEOUT_OPTION = "webkitResponseTimeout"; + + /** + * (Real device only) Set the time to wait for a response from + * WebKit in a Safari session. Defaults to 5000ms. + * + * @param timeout Response timeout. + * @return self instance for chaining. + */ + default T setWebkitResponseTimeout(Duration timeout) { + return amend(WEBKIT_RESPONSE_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the time to wait for a response from WebKit in a Safari session. + * + * @return Timeout value. + */ + default Optional getWebkitResponseTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(WEBKIT_RESPONSE_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsIsHeadlessOption.java similarity index 82% rename from src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java rename to src/main/java/io/appium/java_client/remote/options/SupportsIsHeadlessOption.java index ee365c801..759d7b8b6 100644 --- a/src/main/java/io/appium/java_client/android/options/avd/SupportsIsHeadlessOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsIsHeadlessOption.java @@ -14,10 +14,8 @@ * limitations under the License. */ -package io.appium.java_client.android.options.avd; +package io.appium.java_client.remote.options; -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; import java.util.Optional; @@ -29,7 +27,7 @@ public interface SupportsIsHeadlessOption> extends String IS_HEADLESS_OPTION = "isHeadless"; /** - * Set emulator to start in headless mode (e.g. no UI is shown). + * Set emulator/simulator to start in headless mode (e.g. no UI is shown). * It is only applied if the emulator is not running before the test starts. * * @return self instance for chaining. @@ -39,7 +37,7 @@ default T headless() { } /** - * If set to true then emulator starts in headless mode (e.g. no UI is shown). + * If set to true then emulator/simulator starts in headless mode (e.g. no UI is shown). * It is only applied if the emulator is not running before the test starts. * false by default. * @@ -51,7 +49,7 @@ default T setIsHeadless(boolean value) { } /** - * Get whether the emulator starts in headless mode. + * Get whether the emulator/simulator starts in headless mode. * * @return True or false. */ From f5d12a57f22a332fa69c8f0c060c6fb5c1b8572a Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 27 Oct 2021 11:42:02 +0300 Subject: [PATCH 011/501] refactor: unify locator factories naming and `toString` implementations (#1538) --- .../java/io/appium/java_client/AppiumBy.java | 254 ++++++++++++++++++ .../java/io/appium/java_client/MobileBy.java | 224 ++++++++------- .../pagefactory/bys/builder/Strategies.java | 20 +- .../AndroidAbilityToUseSupplierTest.java | 18 +- .../android/AndroidDataMatcherTest.java | 8 +- .../android/AndroidElementTest.java | 28 +- .../android/AndroidSearchingTest.java | 22 +- .../java_client/android/AndroidTouchTest.java | 6 +- .../android/AndroidViewMatcherTest.java | 4 +- .../java_client/android/FingerPrintTest.java | 4 +- .../java_client/android/UIAutomator2Test.java | 14 +- .../java_client/appium/AndroidTest.java | 44 +-- .../android/AndroidElementGeneratingTest.java | 4 +- .../ios/IOSElementGenerationTest.java | 8 +- .../appium/java_client/ios/IOSAlertTest.java | 4 +- .../java_client/ios/IOSElementTest.java | 7 +- .../java_client/ios/IOSSearchingTest.java | 14 +- .../appium/java_client/ios/IOSTouchTest.java | 12 +- .../java_client/ios/IOSWebViewTest.java | 6 +- .../tests/android/AndroidWidgetTest.java | 12 +- .../widget/tests/ios/XCUITWidgetTest.java | 2 +- .../widget/tests/windows/WindowsApp.java | 13 +- .../tests/windows/WindowsWidgetTest.java | 2 +- 23 files changed, 506 insertions(+), 224 deletions(-) create mode 100644 src/main/java/io/appium/java_client/AppiumBy.java diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java new file mode 100644 index 000000000..6d8c1543d --- /dev/null +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -0,0 +1,254 @@ +/* + * 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 lombok.Getter; +import org.apache.commons.lang3.Validate; +import org.openqa.selenium.By; +import org.openqa.selenium.By.Remotable; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; + +import java.io.Serializable; +import java.util.List; + +@SuppressWarnings("serial") +public abstract class AppiumBy extends By implements Remotable { + + @Getter private final Parameters remoteParameters; + private final String locatorName; + + protected AppiumBy(String selector, String locatorString, String locatorName) { + Validate.notBlank(locatorString, "Must supply a not empty locator value."); + this.remoteParameters = new Parameters(selector, locatorString); + this.locatorName = locatorName; + } + + @SuppressWarnings("unchecked") + @Override public List findElements(SearchContext context) { + return context.findElements(this); + } + + @Override public WebElement findElement(SearchContext context) { + return context.findElement(this); + } + + @Override public String toString() { + return String.format("By.%s: %s", locatorName, remoteParameters.value()); + } + + /** + * About Android accessibility + * https://developer.android.com/intl/ru/training/accessibility/accessible-app.html + * About iOS accessibility + * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ + * UIAccessibilityIdentification_Protocol/index.html + * @param accessibilityId id is a convenient UI automation accessibility Id. + * @return an instance of {@link AppiumBy.ByAndroidUIAutomator} + */ + public static By accessibilityId(final String accessibilityId) { + return new ByAccessibilityId(accessibilityId); + } + + /** + * This locator strategy is only available in Espresso Driver mode. + * @param dataMatcherString is a valid json string detailing hamcrest matcher for Espresso onData(). + * See + * the documentation for more details + * @return an instance of {@link AppiumBy.ByAndroidDataMatcher} + */ + public static By androidDataMatcher(final String dataMatcherString) { + return new ByAndroidDataMatcher(dataMatcherString); + } + + /** + * Refer to https://developer.android.com/training/testing/ui-automator + * @param uiautomatorText is Android UIAutomator string + * @return an instance of {@link AppiumBy.ByAndroidUIAutomator} + */ + public static By androidUIAutomator(final String uiautomatorText) { + return new ByAndroidUIAutomator(uiautomatorText); + } + + /** + * This locator strategy is only available in Espresso Driver mode. + * @param viewMatcherString is a valid json string detailing hamcrest matcher for Espresso onView(). + * See + * the documentation for more details + * @return an instance of {@link AppiumBy.ByAndroidViewMatcher} + */ + public static By androidViewMatcher(final String viewMatcherString) { + return new ByAndroidViewMatcher(viewMatcherString); + } + + /** + * This locator strategy is available in Espresso Driver mode. + * @since Appium 1.8.2 beta + * @param tag is a view tag string + * @return an instance of {@link ByAndroidViewTag} + */ + public static By androidViewTag(final String tag) { + return new ByAndroidViewTag(tag); + } + + /** + * For IOS it is the full name of the XCUI element and begins with XCUIElementType. + * For Android it is the full name of the UIAutomator2 class (e.g.: android.widget.TextView) + * @param selector the class name of the element + * @return an instance of {@link ByClassName} + */ + public static By className(final String selector) { + return new ByClassName(selector); + } + + /** + * This type of locator requires the use of the 'customFindModules' capability and a + * separately-installed element finding plugin. + * + * @param selector selector to pass to the custom element finding plugin + * @return an instance of {@link ByCustom} + * @since Appium 1.9.2 + */ + public static By custom(final String selector) { + return new ByCustom(selector); + } + + /** + * This locator strategy is available only if OpenCV libraries and + * NodeJS bindings are installed on the server machine. + * + * @see + * The documentation on Image Comparison Features + * @see + * The settings available for lookup fine-tuning + * @since Appium 1.8.2 + * @param b64Template base64-encoded template image string. Supported image formats are the same + * as for OpenCV library. + * @return an instance of {@link ByImage} + */ + public static By image(final String b64Template) { + return new ByImage(b64Template); + } + + /** + * This locator strategy is available in XCUITest Driver mode. + * @param iOSClassChainString is a valid class chain locator string. + * See + * the documentation for more details + * @return an instance of {@link AppiumBy.ByIosClassChain} + */ + public static By iOSClassChain(final String iOSClassChainString) { + return new ByIosClassChain(iOSClassChainString); + } + + /** + * This locator strategy is available in XCUITest Driver mode. + * @param iOSNsPredicateString is an iOS NsPredicate String + * @return an instance of {@link AppiumBy.ByIosNsPredicate} + */ + public static By iOSNsPredicateString(final String iOSNsPredicateString) { + return new ByIosNsPredicate(iOSNsPredicateString); + } + + /** + * The Windows UIAutomation selector. + * @param windowsAutomation The element name in the Windows UIAutomation selector + * @return an instance of {@link AppiumBy.ByWindowsAutomation} + */ + public static By windowsAutomation(final String windowsAutomation) { + return new ByWindowsAutomation(windowsAutomation); + } + + public static class ByAccessibilityId extends AppiumBy implements Serializable { + + public ByAccessibilityId(String accessibilityId) { + super("accessibility id", accessibilityId, "accessibilityId"); + } + } + + public static class ByAndroidDataMatcher extends AppiumBy implements Serializable { + + protected ByAndroidDataMatcher(String locatorString) { + super("-android datamatcher", locatorString, "androidDataMatcher"); + } + } + + public static class ByAndroidUIAutomator extends AppiumBy implements Serializable { + + public ByAndroidUIAutomator(String uiautomatorText) { + super("-android uiautomator", uiautomatorText, "androidUIAutomator"); + } + } + + public static class ByAndroidViewMatcher extends AppiumBy implements Serializable { + + protected ByAndroidViewMatcher(String locatorString) { + super("-android viewmatcher", locatorString, "androidViewMatcher"); + } + } + + public static class ByAndroidViewTag extends AppiumBy implements Serializable { + + public ByAndroidViewTag(String tag) { + super("-android viewtag", tag, "androidViewTag"); + } + } + + public static class ByClassName extends AppiumBy implements Serializable { + + protected ByClassName(String selector) { + super("class name", selector, "className"); + } + } + + public static class ByCustom extends AppiumBy implements Serializable { + + protected ByCustom(String selector) { + super("-custom", selector, "custom"); + } + } + + public static class ByImage extends AppiumBy implements Serializable { + + protected ByImage(String b64Template) { + super("-image", b64Template, "image"); + } + } + + public static class ByIosClassChain extends AppiumBy implements Serializable { + + protected ByIosClassChain(String locatorString) { + super("-ios class chain", locatorString, "iOSClassChain"); + } + } + + public static class ByIosNsPredicate extends AppiumBy implements Serializable { + + protected ByIosNsPredicate(String locatorString) { + super("-ios predicate string", locatorString, "iOSNsPredicate"); + } + } + + public static class ByWindowsAutomation extends AppiumBy implements Serializable { + + protected ByWindowsAutomation(String locatorString) { + super("-windows uiautomation", locatorString, "windowsAutomation"); + } + } +} + + diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index 183656627..3d36a1aae 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -16,50 +16,28 @@ package io.appium.java_client; -import lombok.AccessLevel; -import lombok.Getter; -import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.By; -import org.openqa.selenium.By.Remotable; -import org.openqa.selenium.SearchContext; -import org.openqa.selenium.WebElement; - -import java.io.Serializable; -import java.util.List; +/** + * Appium locating strategies. + * + * @deprecated Use {@link AppiumBy} instead. + */ @SuppressWarnings("serial") -public abstract class MobileBy extends By implements Remotable { - - @Getter(AccessLevel.PROTECTED) private final String locatorString; - private final Parameters parameters; - - protected MobileBy(String selector, String locatorString) { - if (StringUtils.isBlank(locatorString)) { - throw new IllegalArgumentException("Must supply a not empty locator value."); - } - this.locatorString = locatorString; - this.parameters = new Parameters(selector, locatorString); - } - - @SuppressWarnings("unchecked") - @Override public List findElements(SearchContext context) { - return context.findElements(this); - } - - @Override public WebElement findElement(SearchContext context) { - return context.findElement(this); - } +@Deprecated +public abstract class MobileBy extends AppiumBy { - @Override - public Parameters getRemoteParameters() { - return parameters; + protected MobileBy(String selector, String locatorString, String locatorName) { + super(selector, locatorString, locatorName); } /** * Refer to https://developer.android.com/training/testing/ui-automator + * @deprecated Use {@link AppiumBy#androidUIAutomator(String)} instead. * @param uiautomatorText is Android UIAutomator string - * @return an instance of {@link io.appium.java_client.MobileBy.ByAndroidUIAutomator} + * @return an instance of {@link ByAndroidUIAutomator} */ + @Deprecated public static By AndroidUIAutomator(final String uiautomatorText) { return new ByAndroidUIAutomator(uiautomatorText); } @@ -70,65 +48,73 @@ public static By AndroidUIAutomator(final String uiautomatorText) { * About iOS accessibility * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ * UIAccessibilityIdentification_Protocol/index.html + * @deprecated Use {@link AppiumBy#accessibilityId(String)} instead. * @param accessibilityId id is a convenient UI automation accessibility Id. - * @return an instance of {@link io.appium.java_client.MobileBy.ByAndroidUIAutomator} + * @return an instance of {@link ByAndroidUIAutomator} */ + @Deprecated public static By AccessibilityId(final String accessibilityId) { return new ByAccessibilityId(accessibilityId); } /** * This locator strategy is available in XCUITest Driver mode. + * @deprecated Use {@link AppiumBy#iOSClassChain(String)} instead. * @param iOSClassChainString is a valid class chain locator string. * See * the documentation for more details - * @return an instance of {@link io.appium.java_client.MobileBy.ByIosClassChain} + * @return an instance of {@link ByIosClassChain} */ + @Deprecated public static By iOSClassChain(final String iOSClassChainString) { return new ByIosClassChain(iOSClassChainString); } /** * This locator strategy is only available in Espresso Driver mode. + * @deprecated Use {@link AppiumBy#androidDataMatcher(String)} instead. * @param dataMatcherString is a valid json string detailing hamcrest matcher for Espresso onData(). * See * the documentation for more details - * @return an instance of {@link io.appium.java_client.MobileBy.ByAndroidDataMatcher} + * @return an instance of {@link ByAndroidDataMatcher} */ + @Deprecated public static By androidDataMatcher(final String dataMatcherString) { return new ByAndroidDataMatcher(dataMatcherString); } /** * This locator strategy is only available in Espresso Driver mode. + * @deprecated Use {@link AppiumBy#androidViewMatcher(String)} instead. * @param viewMatcherString is a valid json string detailing hamcrest matcher for Espresso onView(). * See * the documentation for more details - * @return an instance of {@link io.appium.java_client.MobileBy.ByAndroidViewMatcher} + * @return an instance of {@link ByAndroidViewMatcher} */ + @Deprecated public static By androidViewMatcher(final String viewMatcherString) { return new ByAndroidViewMatcher(viewMatcherString); } /** - * This locator strategy is available in XCUITest Driver mode. - * @param iOSNsPredicateString is an an iOS NsPredicate String - * @return an instance of {@link io.appium.java_client.MobileBy.ByIosNsPredicate} - */ + * This locator strategy is available in XCUITest Driver mode. + * @deprecated Use {@link AppiumBy#iOSNsPredicateString(String)} instead. + * @param iOSNsPredicateString is an iOS NsPredicate String + * @return an instance of {@link ByIosNsPredicate} + */ + @Deprecated public static By iOSNsPredicateString(final String iOSNsPredicateString) { return new ByIosNsPredicate(iOSNsPredicateString); } - public static By windowsAutomation(final String windowsAutomation) { - return new ByWindowsAutomation(windowsAutomation); - } - /** * This locator strategy is available in Espresso Driver mode. + * @deprecated Use {@link AppiumBy#androidViewTag(String)} instead. * @since Appium 1.8.2 beta * @param tag is an view tag string * @return an instance of {@link ByAndroidViewTag} */ + @Deprecated public static By AndroidViewTag(final String tag) { return new ByAndroidViewTag(tag); } @@ -137,6 +123,7 @@ public static By AndroidViewTag(final String tag) { * This locator strategy is available only if OpenCV libraries and * NodeJS bindings are installed on the server machine. * + * @deprecated Use {@link AppiumBy#image(String)} instead. * @see * The documentation on Image Comparison Features * @see @@ -146,6 +133,7 @@ public static By AndroidViewTag(final String tag) { * as for OpenCV library. * @return an instance of {@link ByImage} */ + @Deprecated public static By image(final String b64Template) { return new ByImage(b64Template); } @@ -154,142 +142,182 @@ public static By image(final String b64Template) { * This type of locator requires the use of the 'customFindModules' capability and a * separately-installed element finding plugin. * + * @deprecated Use {@link AppiumBy#custom(String)} instead. * @param selector selector to pass to the custom element finding plugin * @return an instance of {@link ByCustom} * @since Appium 1.9.2 */ + @Deprecated public static By custom(final String selector) { return new ByCustom(selector); } /** - * For IOS it is the full name of the XCUI element and begins with XCUIElementType. - * For Android it is the full name of the UIAutomator2 class (e.g.: android.widget.TextView) - * @param selector the class name of the element - * @return an instance of {@link ByClassName} + * Refer to https://developer.android.com/training/testing/ui-automator + * + * @deprecated Use {@link AppiumBy.ByAndroidUIAutomator} instead. */ - public static By className(final String selector) { - return new ByClassName(selector); - } - - public static class ByAndroidUIAutomator extends MobileBy implements Serializable { + @Deprecated + public static class ByAndroidUIAutomator extends AppiumBy.ByAndroidUIAutomator { public ByAndroidUIAutomator(String uiautomatorText) { - super("-android uiautomator", uiautomatorText); + super(uiautomatorText); } @Override public String toString() { - return "By.AndroidUIAutomator: " + getLocatorString(); + return "By.AndroidUIAutomator: " + getRemoteParameters().value(); } } - - public static class ByAccessibilityId extends MobileBy implements Serializable { + /** + * About Android accessibility + * https://developer.android.com/intl/ru/training/accessibility/accessible-app.html + * About iOS accessibility + * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ + * UIAccessibilityIdentification_Protocol/index.html + * @deprecated Use {@link AppiumBy.ByAccessibilityId} instead. + */ + @Deprecated + public static class ByAccessibilityId extends AppiumBy.ByAccessibilityId { public ByAccessibilityId(String accessibilityId) { - super("accessibility id", accessibilityId); + super(accessibilityId); } @Override public String toString() { - return "By.AccessibilityId: " + getLocatorString(); + return "By.AccessibilityId: " + getRemoteParameters().value(); } } - public static class ByIosClassChain extends MobileBy implements Serializable { + /** + * This locator strategy is available in XCUITest Driver mode. + * See + * the documentation for more details + * @deprecated Use {@link AppiumBy.ByIosClassChain} instead. + */ + @Deprecated + public static class ByIosClassChain extends AppiumBy.ByIosClassChain { protected ByIosClassChain(String locatorString) { - super("-ios class chain", locatorString); + super(locatorString); } @Override public String toString() { - return "By.IosClassChain: " + getLocatorString(); + return "By.IosClassChain: " + getRemoteParameters().value(); } } - public static class ByAndroidDataMatcher extends MobileBy implements Serializable { + /** + * This locator strategy is only available in Espresso Driver mode. + * See + * the documentation for more details + * @deprecated Use {@link AppiumBy.ByAndroidDataMatcher} instead. + */ + @Deprecated + public static class ByAndroidDataMatcher extends AppiumBy.ByAndroidDataMatcher { protected ByAndroidDataMatcher(String locatorString) { - super("-android datamatcher", locatorString); + super(locatorString); } @Override public String toString() { - return "By.AndroidDataMatcher: " + getLocatorString(); + return "By.AndroidDataMatcher: " + getRemoteParameters().value(); } } - public static class ByAndroidViewMatcher extends MobileBy implements Serializable { + /** + * This locator strategy is only available in Espresso Driver mode. + * See + * the documentation for more details + * @deprecated Use {@link AppiumBy.ByAndroidViewMatcher} instead. + */ + @Deprecated + public static class ByAndroidViewMatcher extends AppiumBy.ByAndroidViewMatcher { protected ByAndroidViewMatcher(String locatorString) { - super("-android viewmatcher", locatorString); + super(locatorString); } @Override public String toString() { - return "By.AndroidViewMatcher: " + getLocatorString(); + return "By.AndroidViewMatcher: " + getRemoteParameters().value(); } } - public static class ByIosNsPredicate extends MobileBy implements Serializable { + /** + * This locator strategy is available in XCUITest Driver mode. + * @deprecated Use {@link AppiumBy.ByIosNsPredicate} instead. + */ + @Deprecated + public static class ByIosNsPredicate extends AppiumBy.ByIosNsPredicate { protected ByIosNsPredicate(String locatorString) { - super("-ios predicate string", locatorString); + super(locatorString); } @Override public String toString() { - return "By.IosNsPredicate: " + getLocatorString(); + return "By.IosNsPredicate: " + getRemoteParameters().value(); } } - public static class ByWindowsAutomation extends MobileBy implements Serializable { + /** + * The Windows UIAutomation selector. + * @deprecated Use {@link AppiumBy.ByWindowsAutomation} instead. + */ + @Deprecated + public static class ByWindowsAutomation extends AppiumBy.ByWindowsAutomation { protected ByWindowsAutomation(String locatorString) { - super("-windows uiautomation", locatorString); + super(locatorString); } - } - public static class ByImage extends MobileBy implements Serializable { + /** + * This locator strategy is available only if OpenCV libraries and + * NodeJS bindings are installed on the server machine. + * @deprecated Use {@link AppiumBy.ByImage} instead. + */ + @Deprecated + public static class ByImage extends AppiumBy.ByImage { protected ByImage(String b64Template) { - super("-image", b64Template); + super(b64Template); } @Override public String toString() { - return "By.Image: " + getLocatorString(); + return "By.Image: " + getRemoteParameters().value(); } } - public static class ByCustom extends MobileBy implements Serializable { + /** + * This type of locator requires the use of the 'customFindModules' capability and a + * separately-installed element finding plugin. + * @deprecated Use {@link AppiumBy.ByCustom} instead. + */ + @Deprecated + public static class ByCustom extends AppiumBy.ByCustom { protected ByCustom(String selector) { - super("-custom", selector); + super(selector); } @Override public String toString() { - return "By.Custom: " + getLocatorString(); + return "By.Custom: " + getRemoteParameters().value(); } } - public static class ByAndroidViewTag extends MobileBy implements Serializable { + /** + * This locator strategy is available in Espresso Driver mode. + * @deprecated Use {@link AppiumBy.ByAndroidViewTag} instead. + */ + @Deprecated + public static class ByAndroidViewTag extends AppiumBy.ByAndroidViewTag { public ByAndroidViewTag(String tag) { - super("-android viewtag", tag); + super(tag); } @Override public String toString() { - return "By.AndroidViewTag: " + getLocatorString(); - } - } - - public static class ByClassName extends MobileBy implements Serializable { - - protected ByClassName(String selector) { - super("class name", selector); - } - - @Override public String toString() { - return "By.className: " + getLocatorString(); + return "By.AndroidViewTag: " + getRemoteParameters().value(); } } } - - diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 4b853f046..03382dbcb 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -16,10 +16,10 @@ package io.appium.java_client.pagefactory.bys.builder; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.pagefactory.AndroidBy; import io.appium.java_client.pagefactory.AndroidFindBy; -import io.appium.java_client.pagefactory.iOSBy; + import org.openqa.selenium.By; import java.lang.annotation.Annotation; @@ -34,19 +34,19 @@ enum Strategies { String value = getValue(annotation, this); if (annotation.annotationType().equals(AndroidFindBy.class) || annotation.annotationType().equals(AndroidBy.class)) { - return MobileBy.AndroidUIAutomator(value); + return AppiumBy.androidUIAutomator(value); } return super.getBy(annotation); } }, BYACCESSABILITY("accessibility") { @Override By getBy(Annotation annotation) { - return MobileBy.AccessibilityId(getValue(annotation, this)); + return AppiumBy.accessibilityId(getValue(annotation, this)); } }, BYCLASSNAME("className") { @Override By getBy(Annotation annotation) { - return MobileBy.className(getValue(annotation, this)); + return AppiumBy.className(getValue(annotation, this)); } }, BYID("id") { @@ -86,31 +86,31 @@ enum Strategies { }, BYWINDOWSAUTOMATION("windowsAutomation") { @Override By getBy(Annotation annotation) { - return MobileBy + return AppiumBy .windowsAutomation(getValue(annotation, this)); } }, BY_CLASS_CHAIN("iOSClassChain") { @Override By getBy(Annotation annotation) { - return MobileBy + return AppiumBy .iOSClassChain(getValue(annotation, this)); } }, BY_DATA_MATCHER("androidDataMatcher") { @Override By getBy(Annotation annotation) { - return MobileBy + return AppiumBy .androidDataMatcher(getValue(annotation, this)); } }, BY_VIEW_MATCHER("androidViewMatcher") { @Override By getBy(Annotation annotation) { - return MobileBy + return AppiumBy .androidViewMatcher(getValue(annotation, this)); } }, BY_NS_PREDICATE("iOSNsPredicate") { @Override By getBy(Annotation annotation) { - return MobileBy + return AppiumBy .iOSNsPredicateString(getValue(annotation, this)); } }; diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index 198056e5d..e7ee4b055 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -5,7 +5,7 @@ import static java.time.Duration.ofSeconds; import static org.junit.Assert.assertNotEquals; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; @@ -21,7 +21,7 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { driver.findElement(By.id("io.appium.android.apis:id/gallery")); AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); + List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); Point location = gallery.getLocation(); Point center = gallery.getCenter(); @@ -37,33 +37,33 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { private final ActionSupplier verticalSwiping = () -> new AndroidTouchAction(driver) - .press(element(driver.findElement(MobileBy.AccessibilityId("Gallery")))) + .press(element(driver.findElement(AppiumBy.accessibilityId("Gallery")))) .waitAction(waitOptions(ofSeconds(2))) - .moveTo(element(driver.findElement(MobileBy.AccessibilityId("Auto Complete")))) + .moveTo(element(driver.findElement(AppiumBy.accessibilityId("Auto Complete")))) .release(); @Test public void horizontalSwipingWithSupplier() { Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); driver.startActivity(activity); AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); + List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); int originalImageCount = images.size(); horizontalSwipe.get().perform(); assertNotEquals(originalImageCount, - gallery.findElements(MobileBy.className("android.widget.ImageView")).size()); + gallery.findElements(AppiumBy.className("android.widget.ImageView")).size()); } @Test public void verticalSwipingWithSupplier() throws Exception { driver.resetApp(); - driver.findElement(MobileBy.AccessibilityId("Views")).click(); + driver.findElement(AppiumBy.accessibilityId("Views")).click(); - Point originalLocation = driver.findElement(MobileBy.AccessibilityId("Gallery")).getLocation(); + Point originalLocation = driver.findElement(AppiumBy.accessibilityId("Gallery")).getLocation(); verticalSwiping.get().perform(); Thread.sleep(5000); - assertNotEquals(originalLocation, driver.findElement(MobileBy.AccessibilityId("Gallery")).getLocation()); + assertNotEquals(originalLocation, driver.findElement(AppiumBy.accessibilityId("Gallery")).getLocation()); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java index 5e75653e6..ef54035c6 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java @@ -18,7 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import org.junit.Test; import org.openqa.selenium.json.Json; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -32,8 +32,8 @@ public class AndroidDataMatcherTest extends BaseEspressoTest { public void testFindByDataMatcher() { final WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions - .elementToBeClickable(MobileBy.AccessibilityId("Graphics"))); - driver.findElement(MobileBy.AccessibilityId("Graphics")).click(); + .elementToBeClickable(AppiumBy.accessibilityId("Graphics"))); + driver.findElement(AppiumBy.accessibilityId("Graphics")).click(); String selector = new Json().toJson(ImmutableMap.of( "name", "hasEntry", @@ -41,6 +41,6 @@ public void testFindByDataMatcher() { )); assertNotNull(wait.until(ExpectedConditions - .presenceOfElementLocated(MobileBy.androidDataMatcher(selector)))); + .presenceOfElementLocated(AppiumBy.androidDataMatcher(selector)))); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java index cb89f258f..3d93afaac 100644 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidElementTest.java @@ -20,7 +20,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import org.junit.Before; import org.junit.Test; @@ -36,21 +36,21 @@ public class AndroidElementTest extends BaseAndroidTest { @Test public void findByAccessibilityIdTest() { assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); + .findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); assertEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); + .findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); } @Test public void findByAndroidUIAutomatorTest() { assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); + .findElement(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 0); assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 1); } @Test public void replaceValueTest() { @@ -59,7 +59,7 @@ public class AndroidElementTest extends BaseAndroidTest { Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); driver.startActivity(activity); AndroidElement editElement = driver - .findElement(MobileBy.AndroidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); + .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); editElement.sendKeys(originalValue); assertEquals(originalValue, editElement.getText()); String replacedValue = "replaced value"; @@ -68,11 +68,11 @@ public class AndroidElementTest extends BaseAndroidTest { } @Test public void scrollingToSubElement() { - driver.findElement(MobileBy.AccessibilityId("Views")).click(); + driver.findElement(AppiumBy.accessibilityId("Views")).click(); AndroidElement list = driver.findElement(By.id("android:id/list")); MobileElement radioGroup = list - .findElement(MobileBy - .AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" + .findElement(AppiumBy + .androidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" + "new UiSelector().text(\"Radio Group\"));")); assertNotNull(radioGroup.getLocation()); } @@ -83,7 +83,7 @@ public class AndroidElementTest extends BaseAndroidTest { Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); driver.startActivity(activity); AndroidElement editElement = driver - .findElement(MobileBy.AndroidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); + .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); editElement.setValue(value); assertEquals(value, editElement.getText()); } diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index 4564899f4..17be3a86f 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -20,7 +20,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import org.junit.Before; import org.junit.Test; @@ -35,20 +35,20 @@ public void setup() { } @Test public void findByAccessibilityIdTest() { - assertNotEquals(driver.findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); + assertNotEquals(driver.findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); + assertEquals(driver.findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); } @Test public void findByAndroidUIAutomatorTest() { assertNotEquals(driver - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); + .findElement(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); assertNotEquals(driver - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 0); assertNotEquals(driver - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 1); } @Test public void findByXPathTest() { @@ -58,9 +58,9 @@ public void setup() { } @Test public void findScrollable() { - driver.findElement(MobileBy.AccessibilityId("Views")).click(); + driver.findElement(AppiumBy.accessibilityId("Views")).click(); MobileElement radioGroup = driver - .findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector()" + .findElement(AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector()" + ".resourceId(\"android:id/list\")).scrollIntoView(" + "new UiSelector().text(\"Radio Group\"));")); assertNotNull(radioGroup.getLocation()); diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index 341b8d40b..dfff86414 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; @@ -171,7 +171,7 @@ public void setUp() { driver.startActivity(activity); AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(MobileBy.className("android.widget.ImageView")); + List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); int originalImageCount = images.size(); Point location = gallery.getLocation(); Point center = gallery.getCenter(); @@ -183,7 +183,7 @@ public void setUp() { .release(); swipe.perform(); assertNotEquals(originalImageCount, - gallery.findElements(MobileBy.className("android.widget.ImageView")).size()); + gallery.findElements(AppiumBy.className("android.widget.ImageView")).size()); } @Test public void multiTouchTest() { diff --git a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java index e8253074e..2e3b73448 100644 --- a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java @@ -18,7 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import org.junit.Test; import org.openqa.selenium.json.Json; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -37,6 +37,6 @@ public void testFindByViewMatcher() { )); final WebDriverWait wait = new WebDriverWait(driver, 10); assertNotNull(wait.until(ExpectedConditions - .presenceOfElementLocated(MobileBy.androidViewMatcher(selector)))); + .presenceOfElementLocated(AppiumBy.androidViewMatcher(selector)))); } } diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java index 02cf7dba4..5a8a2a9e8 100644 --- a/src/test/java/io/appium/java_client/android/FingerPrintTest.java +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -16,7 +16,7 @@ package io.appium.java_client.android; -import static io.appium.java_client.MobileBy.AndroidUIAutomator; +import static io.appium.java_client.AppiumBy.androidUIAutomator; import static java.util.concurrent.TimeUnit.SECONDS; import io.appium.java_client.remote.MobileCapabilityType; @@ -89,7 +89,7 @@ private void enterPasswordAndContinue() { } private void clickOnSecurity() { - driver.findElement(AndroidUIAutomator("new UiScrollable(new UiSelector()" + driver.findElement(androidUIAutomator("new UiScrollable(new UiSelector()" + ".scrollable(true)).scrollIntoView(" + "new UiSelector().text(\"Security & location\"));")).click(); } diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java index 8b18bcce6..568e9cf53 100644 --- a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java +++ b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java @@ -3,7 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import org.junit.After; import org.junit.Ignore; @@ -25,7 +25,7 @@ public void afterMethod() { public void testLandscapeRightRotation() { new WebDriverWait(driver, 20).until(ExpectedConditions .elementToBeClickable(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")))); + .findElement(AppiumBy.accessibilityId("Graphics")))); DeviceRotation landscapeRightRotation = new DeviceRotation(0, 0, 90); driver.rotate(landscapeRightRotation); assertEquals(driver.rotation(), landscapeRightRotation); @@ -35,7 +35,7 @@ public void testLandscapeRightRotation() { public void testLandscapeLeftRotation() { new WebDriverWait(driver, 20).until(ExpectedConditions .elementToBeClickable(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")))); + .findElement(AppiumBy.accessibilityId("Graphics")))); DeviceRotation landscapeLeftRotation = new DeviceRotation(0, 0, 270); driver.rotate(landscapeLeftRotation); assertEquals(driver.rotation(), landscapeLeftRotation); @@ -45,7 +45,7 @@ public void testLandscapeLeftRotation() { public void testPortraitUpsideDown() { new WebDriverWait(driver, 20).until(ExpectedConditions .elementToBeClickable(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")))); + .findElement(AppiumBy.accessibilityId("Graphics")))); DeviceRotation landscapeRightRotation = new DeviceRotation(0, 0, 180); driver.rotate(landscapeRightRotation); assertEquals(driver.rotation(), landscapeRightRotation); @@ -60,9 +60,9 @@ public void testToastMSGIsDisplayed() { Activity activity = new Activity("io.appium.android.apis", ".view.PopupMenu1"); driver.startActivity(activity); - wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy - .AccessibilityId("Make a Popup!"))); - MobileElement popUpElement = driver.findElement(MobileBy.AccessibilityId("Make a Popup!")); + wait.until(ExpectedConditions.presenceOfElementLocated(AppiumBy + .accessibilityId("Make a Popup!"))); + MobileElement popUpElement = driver.findElement(AppiumBy.accessibilityId("Make a Popup!")); wait.until(ExpectedConditions.elementToBeClickable(popUpElement)).click(); wait.until(ExpectedConditions.visibilityOfElementLocated( By.xpath(".//*[@text='Search']"))).click(); diff --git a/src/test/java/io/appium/java_client/appium/AndroidTest.java b/src/test/java/io/appium/java_client/appium/AndroidTest.java index 47e2475e4..4347e3f24 100644 --- a/src/test/java/io/appium/java_client/appium/AndroidTest.java +++ b/src/test/java/io/appium/java_client/appium/AndroidTest.java @@ -6,7 +6,7 @@ import static org.junit.Assert.assertNotNull; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import io.appium.java_client.android.Activity; import io.appium.java_client.android.AndroidElement; @@ -83,39 +83,39 @@ public Response execute(String driverCommand) { @Test public void findByAccessibilityIdFromDriverTest() { - assertNotEquals(driver.findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); + assertNotEquals(driver.findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); + assertEquals(driver.findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); } @Test public void findByAndroidUIAutomatorFromDriverTest() { assertNotEquals(driver - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); + .findElement(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); assertNotEquals(driver - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 0); assertNotEquals(driver - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 1); } @Test public void findByAccessibilityIdFromElementTest() { assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy.AccessibilityId("Graphics")).getText(), null); + .findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); assertEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy.AccessibilityId("Graphics")).size(), 1); + .findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); } @Test public void findByAndroidUIAutomatorFromElementTest() { assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).getText(), null); + .findElement(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 0); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 0); assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(MobileBy - .AndroidUIAutomator("new UiSelector().clickable(true)")).size(), 1); + .findElements(AppiumBy + .androidUIAutomator("new UiSelector().clickable(true)")).size(), 1); } @Test public void replaceValueTest() { @@ -124,8 +124,8 @@ public void findByAccessibilityIdFromDriverTest() { Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); startsActivity.startActivity(activity); AndroidElement editElement = driver - .findElement(MobileBy - .AndroidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); + .findElement(AppiumBy + .androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); editElement.sendKeys(originalValue); assertEquals(originalValue, editElement.getText()); String replacedValue = "replaced value"; @@ -134,11 +134,11 @@ public void findByAccessibilityIdFromDriverTest() { } @Test public void scrollingToSubElement() { - driver.findElement(MobileBy.AccessibilityId("Views")).click(); + driver.findElement(AppiumBy.accessibilityId("Views")).click(); AndroidElement list = driver.findElement(By.id("android:id/list")); MobileElement radioGroup = list - .findElement(MobileBy - .AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" + .findElement(AppiumBy + .androidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" + "new UiSelector().text(\"Radio Group\"));")); assertNotNull(radioGroup.getLocation()); } diff --git a/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java b/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java index 1582c7b18..2c8de9eb1 100644 --- a/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java +++ b/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.appium.element.generation.android; -import static io.appium.java_client.MobileBy.AndroidUIAutomator; +import static io.appium.java_client.AppiumBy.androidUIAutomator; import static io.appium.java_client.TestResources.apiDemosApk; import static org.junit.Assert.assertTrue; import static org.openqa.selenium.By.name; @@ -40,7 +40,7 @@ public void whenAndroidNativeAppIsLaunched() { clientCapabilities.setCapability(MobileCapabilityType.FULL_RESET, true); clientCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60); return clientCapabilities; - }, commonPredicate, AndroidUIAutomator("new UiSelector().clickable(true)") + }, commonPredicate, androidUIAutomator("new UiSelector().clickable(true)") )); } diff --git a/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java b/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java index 2a1cc2dfa..4f227464d 100644 --- a/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java +++ b/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java @@ -8,7 +8,7 @@ import static org.openqa.selenium.By.partialLinkText; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.appium.element.generation.BaseElementGenerationTest; import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSElement; @@ -82,7 +82,7 @@ public void whenIOSNativeAppIsLaunched() { Capabilities caps = commonAppCapabilitiesSupplier.get(); return caps.merge(appFileSupplierFunction.apply(testApp).get()); }, commonPredicate, - MobileBy.AccessibilityId("Answer") + AppiumBy.accessibilityId("Answer") )); } @@ -96,10 +96,10 @@ public void whenIOSHybridAppIsLaunched() { new WebDriverWait(driver, Duration.ofSeconds(30)) .until(ExpectedConditions.presenceOfElementLocated(id("login"))) .click(); - driver.findElement(MobileBy.AccessibilityId("webView")).click(); + driver.findElement(AppiumBy.accessibilityId("webView")).click(); new WebDriverWait(driver, Duration.ofSeconds(30)) .until(ExpectedConditions - .presenceOfElementLocated(MobileBy.AccessibilityId("Webview"))); + .presenceOfElementLocated(AppiumBy.accessibilityId("Webview"))); try { Thread.sleep(10000); } catch (InterruptedException e) { diff --git a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java index e5a5033bb..07edb2be5 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java @@ -20,7 +20,7 @@ import static org.junit.Assert.assertTrue; import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import org.apache.commons.lang3.StringUtils; import org.junit.After; import org.junit.FixMethodOrder; @@ -46,7 +46,7 @@ private void ensureAlertPresence() { // CI might not be performant enough, so we need to retry while (true) { try { - driver.findElement(MobileBy.AccessibilityId(iOSAutomationText)).click(); + driver.findElement(AppiumBy.accessibilityId(iOSAutomationText)).click(); } catch (WebDriverException e) { // ignore } diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index 582e9f97c..234b9346c 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -9,17 +9,16 @@ import org.junit.Ignore; import org.junit.Test; import org.junit.runners.MethodSorters; -import org.openqa.selenium.By; import org.openqa.selenium.support.ui.WebDriverWait; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class IOSElementTest extends AppIOSTest { @Test public void findByAccessibilityIdTest() { - assertThat(driver.findElements(MobileBy.AccessibilityId("Compute Sum")).size(), not(is(0))); + assertThat(driver.findElements(AppiumBy.accessibilityId("Compute Sum")).size(), not(is(0))); } // FIXME: Stabilize the test on CI @@ -29,7 +28,7 @@ public void setValueTest() { WebDriverWait wait = new WebDriverWait(driver, 20); IOSElement slider = wait.until( - driver1 -> driver1.findElement(MobileBy.className("XCUIElementTypeSlider"))); + driver1 -> driver1.findElement(AppiumBy.className("XCUIElementTypeSlider"))); slider.setValue("0%"); assertEquals("0%", slider.getAttribute("value")); } diff --git a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java b/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java index e8a0bbc16..a90196bbe 100644 --- a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java @@ -20,34 +20,34 @@ import org.junit.Test; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; public class IOSSearchingTest extends AppIOSTest { @Test public void findByAccessibilityIdTest() { assertNotEquals(driver - .findElement(MobileBy.AccessibilityId("ComputeSumButton")) + .findElement(AppiumBy.accessibilityId("ComputeSumButton")) .getText(), null); assertNotEquals(driver - .findElements(MobileBy.AccessibilityId("ComputeSumButton")) + .findElements(AppiumBy.accessibilityId("ComputeSumButton")) .size(), 0); } @Test public void findByByIosPredicatesTest() { assertNotEquals(driver - .findElement(MobileBy.iOSNsPredicateString("name like 'Answer'")) + .findElement(AppiumBy.iOSNsPredicateString("name like 'Answer'")) .getText(), null); assertNotEquals(driver - .findElements(MobileBy.iOSNsPredicateString("name like 'Answer'")) + .findElements(AppiumBy.iOSNsPredicateString("name like 'Answer'")) .size(), 0); } @Test public void findByByIosClassChainTest() { assertNotEquals(driver - .findElement(MobileBy.iOSClassChain("**/XCUIElementTypeButton")) + .findElement(AppiumBy.iOSClassChain("**/XCUIElementTypeButton")) .getText(), null); assertNotEquals(driver - .findElements(MobileBy.iOSClassChain("**/XCUIElementTypeButton")) + .findElements(AppiumBy.iOSClassChain("**/XCUIElementTypeButton")) .size(), 0); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java index faf2ab98b..8ad29b526 100644 --- a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java @@ -9,7 +9,7 @@ import static org.junit.Assert.assertNotNull; import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import io.appium.java_client.MobileElement; import io.appium.java_client.MultiTouchAction; import org.junit.FixMethodOrder; @@ -30,7 +30,7 @@ public void tapTest() { intA.sendKeys("2"); intB.sendKeys("4"); - MobileElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); + MobileElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))).perform(); assertEquals(driver.findElement(By.xpath("//*[@name = \"Answer\"]")).getText(), "6"); } @@ -44,7 +44,7 @@ public void touchWithPressureTest() { intA.sendKeys("2"); intB.sendKeys("4"); - MobileElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); + MobileElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); new IOSTouchAction(driver) .press(iosPressOptions() .withElement(element(e)) @@ -56,8 +56,8 @@ public void touchWithPressureTest() { } @Test public void multiTouchTest() { - MobileElement e = driver.findElement(MobileBy.AccessibilityId("ComputeSumButton")); - MobileElement e2 = driver.findElement(MobileBy.AccessibilityId("show alert")); + MobileElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); + MobileElement e2 = driver.findElement(AppiumBy.accessibilityId("show alert")); IOSTouchAction tap1 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))); IOSTouchAction tap2 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e2))); @@ -75,7 +75,7 @@ public void touchWithPressureTest() { IOSTouchAction iosTouchAction = new IOSTouchAction(driver); iosTouchAction.doubleTap(element(firstField)); - IOSElement editingMenu = driver.findElement(MobileBy.className("XCUIElementTypeTextField")); + IOSElement editingMenu = driver.findElement(AppiumBy.className("XCUIElementTypeTextField")); assertNotNull(editingMenu); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java index 03b79b2b6..5f8564ccb 100644 --- a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java @@ -4,7 +4,7 @@ import java.time.Duration; -import io.appium.java_client.MobileBy; +import io.appium.java_client.AppiumBy; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; @@ -17,9 +17,9 @@ public class IOSWebViewTest extends BaseIOSWebViewTest { new WebDriverWait(driver, Duration.ofSeconds(30)) .until(ExpectedConditions.presenceOfElementLocated(By.id("login"))) .click(); - driver.findElement(MobileBy.AccessibilityId("webView")).click(); + driver.findElement(AppiumBy.accessibilityId("webView")).click(); new WebDriverWait(driver, Duration.ofSeconds(30)) - .until(ExpectedConditions.presenceOfElementLocated(MobileBy.AccessibilityId("Webview"))); + .until(ExpectedConditions.presenceOfElementLocated(AppiumBy.accessibilityId("Webview"))); findAndSwitchToWebView(); WebElement el = driver.findElement(By.partialLinkText("login")); assertTrue(el.isDisplayed()); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java index 3b94b21cd..93047222b 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.pagefactory_tests.widget.tests.android; -import static io.appium.java_client.MobileBy.AndroidUIAutomator; +import static io.appium.java_client.AppiumBy.androidUIAutomator; import static io.appium.java_client.pagefactory_tests.widget.tests.android.AndroidApp.ANDROID_DEFAULT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.android.AndroidApp.ANDROID_EXTERNALLY_DEFINED_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.android.AnnotatedAndroidWidget.ANDROID_ROOT_WIDGET_LOCATOR; @@ -19,28 +19,28 @@ public AndroidWidgetTest() { @Override public void checkThatWidgetsAreCreatedCorrectly() { checkThatLocatorsAreCreatedCorrectly(app.getWidget(), app.getWidgets(), - AndroidUIAutomator(ANDROID_DEFAULT_WIDGET_LOCATOR), AndroidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); + androidUIAutomator(ANDROID_DEFAULT_WIDGET_LOCATOR), androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } @Override public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getAnnotatedWidget(), ((ExtendedApp) app).getAnnotatedWidgets(), - AndroidUIAutomator(ANDROID_ROOT_WIDGET_LOCATOR), AndroidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); + androidUIAutomator(ANDROID_ROOT_WIDGET_LOCATOR), androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } @Override public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidget(), ((ExtendedApp) app).getExtendedWidgets(), - AndroidUIAutomator(ANDROID_ROOT_WIDGET_LOCATOR), AndroidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); + androidUIAutomator(ANDROID_ROOT_WIDGET_LOCATOR), androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } @Override public void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidgetWithOverriddenLocators(), ((ExtendedApp) app).getExtendedWidgetsWithOverriddenLocators(), - AndroidUIAutomator(ANDROID_EXTERNALLY_DEFINED_WIDGET_LOCATOR), - AndroidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); + androidUIAutomator(ANDROID_EXTERNALLY_DEFINED_WIDGET_LOCATOR), + androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java index 56abc937a..d2e4d483f 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.pagefactory_tests.widget.tests.ios; -import static io.appium.java_client.MobileBy.iOSNsPredicateString; +import static io.appium.java_client.AppiumBy.iOSNsPredicateString; import static io.appium.java_client.pagefactory_tests.widget.tests.combined.DefaultIosXCUITWidget.XCUIT_SUB_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.ios.AnnotatedIosWidget.XCUIT_ROOT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.ios.IosApp.IOS_XCUIT_WIDGET_LOCATOR; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java index 4d264820c..07eb5784d 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java @@ -1,5 +1,6 @@ package io.appium.java_client.pagefactory_tests.widget.tests.windows; +import io.appium.java_client.AppiumBy; import io.appium.java_client.pagefactory.WindowsFindBy; import io.appium.java_client.pagefactory.iOSXCUITFindBy; import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; @@ -25,7 +26,7 @@ public class WindowsApp implements ExtendedApp { * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. * This field was added to check that locator is created correctly according to current platform. * It is expected that the root element and sub-elements are found using - * {@link io.appium.java_client.MobileBy#windowsAutomation(String)} + * {@link AppiumBy#windowsAutomation(String)} */ private AnnotatedWindowsWidget singleAnnotatedIosWidget; @@ -34,7 +35,7 @@ public class WindowsApp implements ExtendedApp { * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. * This field was added to check that locator is created correctly according to current platform. * It is expected that the root element and sub-elements are found using - * {@link io.appium.java_client.MobileBy#windowsAutomation(String)}. + * {@link AppiumBy#windowsAutomation(String)}. */ private List multipleIosIosWidgets; @@ -44,7 +45,7 @@ public class WindowsApp implements ExtendedApp { * But the superclass is annotated by these annotations. This field was added to check that locator is * created correctly according to current platform. * It is expected that the root element and sub-elements are found using - * {@link io.appium.java_client.MobileBy#windowsAutomation(String)}. + * {@link AppiumBy#windowsAutomation(String)}. */ private ExtendedWindowsWidget singleExtendedIosWidget; @@ -54,7 +55,7 @@ public class WindowsApp implements ExtendedApp { * But the superclass is annotated by these annotations. This field was added to check that locator is * created correctly according to current platform. * It is expected that the root element and sub-elements are found using - * {@link io.appium.java_client.MobileBy#windowsAutomation(String)}. + * {@link AppiumBy#windowsAutomation(String)}. */ private List multipleExtendedIosWidgets; @@ -64,7 +65,7 @@ public class WindowsApp implements ExtendedApp { * But the superclass is annotated by these annotations. This field was added to check that locator is * created correctly according to current platform. * It is expected that the root element and sub-elements are found using - * {@link io.appium.java_client.MobileBy#windowsAutomation(String)}. + * {@link AppiumBy#windowsAutomation(String)}. */ @WindowsFindBy(windowsAutomation = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR") @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_EXTERNALLY_DEFINED_LOCATOR") @@ -76,7 +77,7 @@ public class WindowsApp implements ExtendedApp { * But the superclass is annotated by these annotations. This field was added to check that locator is * created correctly according to current platform. * It is expected that the root element and sub-elements are found using - * {@link io.appium.java_client.MobileBy#windowsAutomation(String)}. + * {@link AppiumBy#windowsAutomation(String)}. */ @WindowsFindBy(windowsAutomation = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR") @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_EXTERNALLY_DEFINED_LOCATOR") diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java index fbd9da9a6..8fbc23fd4 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.pagefactory_tests.widget.tests.windows; -import static io.appium.java_client.MobileBy.windowsAutomation; +import static io.appium.java_client.AppiumBy.windowsAutomation; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.AnnotatedWindowsWidget.WINDOWS_ROOT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget.WINDOWS_SUB_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_DEFAULT_WIDGET_LOCATOR; From 3c4bbe91869bd6708e4824947fd652b8cc2dc0ba Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 27 Oct 2021 12:35:01 +0300 Subject: [PATCH 012/501] chore!: drop support of deprecated Selendroid driver (#1553) BREAKING CHANGE: remove `SELENDROID` item from `AutomationName` interface and corresponding entry in `ElementMap` enum --- src/main/java/io/appium/java_client/internal/ElementMap.java | 1 - src/main/java/io/appium/java_client/remote/AutomationName.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/main/java/io/appium/java_client/internal/ElementMap.java b/src/main/java/io/appium/java_client/internal/ElementMap.java index d2f056c5d..75948be47 100644 --- a/src/main/java/io/appium/java_client/internal/ElementMap.java +++ b/src/main/java/io/appium/java_client/internal/ElementMap.java @@ -34,7 +34,6 @@ public enum ElementMap { ANDROID_UIAUTOMATOR2(AutomationName.ANDROID_UIAUTOMATOR2.toLowerCase(), AndroidElement.class), - SELENDROID(AutomationName.SELENDROID.toLowerCase(), AndroidElement.class), IOS_XCUI_TEST(AutomationName.IOS_XCUI_TEST.toLowerCase(), IOSElement.class), ANDROID_UI_AUTOMATOR(MobilePlatform.ANDROID.toLowerCase(), AndroidElement.class), IOS_UI_AUTOMATION(MobilePlatform.IOS.toLowerCase(), IOSElement.class), diff --git a/src/main/java/io/appium/java_client/remote/AutomationName.java b/src/main/java/io/appium/java_client/remote/AutomationName.java index 5be0849a9..e38474dbc 100644 --- a/src/main/java/io/appium/java_client/remote/AutomationName.java +++ b/src/main/java/io/appium/java_client/remote/AutomationName.java @@ -20,8 +20,6 @@ public interface AutomationName { // Officially supported drivers @Deprecated String APPIUM = "Appium"; - @Deprecated - String SELENDROID = "Selendroid"; // https://github.com/appium/appium-xcuitest-driver String IOS_XCUI_TEST = "XCuiTest"; // https://github.com/appium/appium-uiautomator2-driver From f1cc1030b21b7303b7ea4bc2687618e2d4fa4291 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 13:46:05 +0200 Subject: [PATCH 013/501] refactor!: Remove selenium package override (#1555) --- .../io/appium/java_client/AppiumDriver.java | 166 +--- .../java_client/AppiumExecutionMethod.java | 4 +- ...idElement.java => CanSetElementValue.java} | 23 +- .../DefaultGenericMobileDriver.java | 61 -- .../DefaultGenericMobileElement.java | 49 -- .../io/appium/java_client/ExecutesMethod.java | 8 +- .../appium/java_client/HasBrowserCheck.java | 44 + .../appium/java_client/HasSessionDetails.java | 104 --- .../io/appium/java_client/MobileCommand.java | 4 +- .../io/appium/java_client/MobileElement.java | 57 -- .../java_client/android/AndroidDriver.java | 59 +- .../android/CanReplaceElementValue.java | 21 + .../java_client/internal/ElementMap.java | 89 -- .../JsonToMobileElementConverter.java | 84 -- .../io/appium/java_client/ios/IOSDriver.java | 48 +- .../io/appium/java_client/ios/IOSElement.java | 22 - .../io/appium/java_client/mac/Mac2Driver.java | 23 +- .../appium/java_client/mac/Mac2Element.java | 22 - .../pagefactory/AppiumFieldDecorator.java | 13 +- .../utils/WebDriverUnpackUtility.java | 12 +- .../remote/SupportsContextSwitching.java | 81 ++ .../SupportsLocation.java} | 23 +- .../java_client/remote/SupportsRotation.java | 61 ++ .../java_client/windows/WindowsDriver.java | 7 +- .../java_client/windows/WindowsElement.java | 22 - .../org/openqa/selenium/SearchContext.java | 43 - .../java/org/openqa/selenium/WebDriver.java | 757 ------------------ .../java/org/openqa/selenium/WebElement.java | 338 -------- .../java/io/appium/java_client/TestUtils.java | 16 + .../AndroidAbilityToUseSupplierTest.java | 13 +- .../android/AndroidDriverTest.java | 20 - .../android/AndroidElementTest.java | 15 +- .../android/AndroidSearchingTest.java | 4 +- .../java_client/android/AndroidTouchTest.java | 30 +- .../java_client/android/BaseAndroidTest.java | 4 +- .../java_client/android/BaseEspressoTest.java | 4 +- .../android/ExecuteCDPCommandTest.java | 2 +- .../java_client/android/FingerPrintTest.java | 12 +- .../java_client/android/IntentTest.java | 4 +- .../android/OpenNotificationsTest.java | 3 +- .../java_client/android/UIAutomator2Test.java | 13 +- .../java_client/appium/AndroidTest.java | 146 ---- .../appium/AppiumFluentWaitTest.java | 97 --- .../generation/BaseElementGenerationTest.java | 42 - .../android/AndroidElementGeneratingTest.java | 81 -- .../ios/IOSElementGenerationTest.java | 166 ---- .../events/stubs/EmptyWebDriver.java | 2 +- .../io/appium/java_client/ios/AppIOSTest.java | 4 +- .../appium/java_client/ios/BaseIOSTest.java | 2 +- .../java_client/ios/BaseIOSWebViewTest.java | 4 +- .../java_client/ios/BaseSafariTest.java | 2 +- .../appium/java_client/ios/IOSDriverTest.java | 13 +- .../java_client/ios/IOSElementTest.java | 12 +- .../appium/java_client/ios/IOSTouchTest.java | 26 +- .../AndroidPageObjectTest.java | 35 +- .../DesktopBrowserCompatibilityTest.java | 2 +- .../pagefactory_tests/GenericTest.java | 300 ------- .../MobileBrowserCompatibilityTest.java | 2 +- .../pagefactory_tests/XCUITModeTest.java | 31 +- .../widget/tests/AbstractStubWebDriver.java | 23 +- .../widget/tests/StubWebElement.java | 2 +- .../service/local/StartingAppLocallyTest.java | 12 +- 62 files changed, 526 insertions(+), 2863 deletions(-) rename src/main/java/io/appium/java_client/{android/AndroidElement.java => CanSetElementValue.java} (56%) delete mode 100644 src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java delete mode 100644 src/main/java/io/appium/java_client/DefaultGenericMobileElement.java create mode 100644 src/main/java/io/appium/java_client/HasBrowserCheck.java delete mode 100644 src/main/java/io/appium/java_client/HasSessionDetails.java delete mode 100644 src/main/java/io/appium/java_client/MobileElement.java create mode 100644 src/main/java/io/appium/java_client/android/CanReplaceElementValue.java delete mode 100644 src/main/java/io/appium/java_client/internal/ElementMap.java delete mode 100644 src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java delete mode 100644 src/main/java/io/appium/java_client/ios/IOSElement.java delete mode 100644 src/main/java/io/appium/java_client/mac/Mac2Element.java create mode 100644 src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java rename src/main/java/io/appium/java_client/{MobileDriver.java => remote/SupportsLocation.java} (59%) create mode 100644 src/main/java/io/appium/java_client/remote/SupportsRotation.java delete mode 100644 src/main/java/io/appium/java_client/windows/WindowsElement.java delete mode 100644 src/main/java/org/openqa/selenium/SearchContext.java delete mode 100644 src/main/java/org/openqa/selenium/WebDriver.java delete mode 100644 src/main/java/org/openqa/selenium/WebElement.java delete mode 100644 src/test/java/io/appium/java_client/appium/AndroidTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java delete mode 100644 src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index b2fdf10d5..cd987ca94 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -16,32 +16,18 @@ package io.appium.java_client; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; -import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; -import static org.apache.commons.lang3.StringUtils.isBlank; -import com.google.common.collect.ImmutableMap; - -import io.appium.java_client.internal.CapabilityHelpers; -import io.appium.java_client.internal.JsonToMobileElementConverter; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; -import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.DeviceRotation; +import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.html5.Location; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.ErrorHandler; import org.openqa.selenium.remote.ExecuteMethod; @@ -55,29 +41,25 @@ import java.lang.reflect.Field; import java.net.URL; import java.util.Arrays; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.Collections; import java.util.Map; -import java.util.Set; /** * Default Appium driver implementation. - * - * @param the required type of class which implement {@link WebElement}. - * Instances of the defined type will be returned via findElement* and findElements* - * Warning (!!!). Allowed types: - * {@link WebElement}, {@link org.openqa.selenium.remote.RemoteWebElement}, - * {@link MobileElement} and its subclasses that designed - * specifically for each target mobile OS (still Android and iOS) */ -@SuppressWarnings("unchecked") -public class AppiumDriver - extends DefaultGenericMobileDriver implements ComparesImages, ExecutesDriverScript, LogsEvents, HasSettings { +public class AppiumDriver extends RemoteWebDriver implements + ExecutesMethod, + ComparesImages, + ExecutesDriverScript, + LogsEvents, + CanSetElementValue, + HasBrowserCheck, + HasSettings { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters private final URL remoteAddress; - private final RemoteLocationContext locationContext; + protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; /** @@ -94,7 +76,6 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { locationContext = new RemoteLocationContext(executeMethod); super.setErrorHandler(errorHandler); this.remoteAddress = executor.getAddressOfRemoteServer(); - this.setElementConverter(new JsonToMobileElementConverter(this)); } public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities) { @@ -147,17 +128,9 @@ public AppiumDriver(Capabilities desiredCapabilities) { */ protected static Capabilities updateDefaultPlatformName(Capabilities originalCapabilities, String defaultName) { - if (originalCapabilities.getCapability(PLATFORM_NAME) == null) { - DesiredCapabilities dc = new DesiredCapabilities(originalCapabilities); - dc.setCapability(PLATFORM_NAME, defaultName); - return dc; - } - return originalCapabilities; - } - - @Override - public List findElements(By by) { - return super.findElements(by); + return originalCapabilities.getCapability(PLATFORM_NAME) == null + ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) + : originalCapabilities; } @Override @@ -165,77 +138,21 @@ public ExecuteMethod getExecuteMethod() { return executeMethod; } - @Override - public WebDriver context(String name) { - checkNotNull(name, "Must supply a context name"); - try { - execute(DriverCommand.SWITCH_TO_CONTEXT, ImmutableMap.of("name", name)); - return this; - } catch (WebDriverException e) { - throw new NoSuchContextException(e.getMessage(), e); - } - } - - @Override - public Set getContextHandles() { - Response response = execute(DriverCommand.GET_CONTEXT_HANDLES); - Object value = response.getValue(); - try { - List returnedValues = (List) value; - return new LinkedHashSet<>(returnedValues); - } catch (ClassCastException ex) { - throw new WebDriverException( - "Returned value cannot be converted to List: " + value, ex); - } - } - - @Override - public String getContext() { - String contextName = - String.valueOf(execute(DriverCommand.GET_CURRENT_CONTEXT_HANDLE).getValue()); - if ("null".equalsIgnoreCase(contextName)) { - return null; - } - return contextName; - } - /** * This method is used to get build version status of running Appium server. * * @return map containing version details */ public Map getStatus() { + //noinspection unchecked return (Map) execute(DriverCommand.STATUS).getValue(); } - @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())); - } - /** * This method is used to add custom appium commands in Appium 2.0. * * @param httpMethod the available {@link HttpMethod}. - * @param url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints. + * @param url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints. * @param methodName The name of custom appium command. */ public void addCommand(HttpMethod httpMethod, String url, String methodName) { @@ -257,51 +174,10 @@ public void addCommand(HttpMethod httpMethod, String url, String methodName) { ((AppiumCommandExecutor) getCommandExecutor()).refreshAdditionalCommands(); } - @Override - public ScreenOrientation getOrientation() { - Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); - String orientation = response.getValue().toString().toLowerCase(); - if (orientation.equals(ScreenOrientation.LANDSCAPE.value())) { - return ScreenOrientation.LANDSCAPE; - } else if (orientation.equals(ScreenOrientation.PORTRAIT.value())) { - return ScreenOrientation.PORTRAIT; - } else { - throw new WebDriverException("Unexpected orientation returned: " + orientation); - } - } - - @Override - public Location location() { - return locationContext.location(); - } - - @Override - public void setLocation(Location location) { - locationContext.setLocation(location); - } - public URL getRemoteAddress() { return remoteAddress; } - @Override - public boolean isBrowser() { - String browserName = CapabilityHelpers.getCapability(getCapabilities(), - CapabilityType.BROWSER_NAME, String.class); - if (!isBlank(browserName)) { - try { - return (boolean) executeScript("return !!window.navigator;"); - } catch (WebDriverException ign) { - // ignore - } - } - try { - return !containsIgnoreCase(getContext(), "NATIVE_APP"); - } catch (WebDriverException e) { - return false; - } - } - @Override protected void startSession(Capabilities capabilities) { Response response = execute(new AppiumNewSessionCommandPayload(capabilities)); @@ -333,4 +209,14 @@ protected void startSession(Capabilities capabilities) { } setSessionId(response.getSessionId()); } + + @Override + public Response execute(String driverCommand, Map parameters) { + return super.execute(driverCommand, parameters); + } + + @Override + public Response execute(String command) { + return super.execute(command, Collections.emptyMap()); + } } diff --git a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java index 3bab7980c..3abe1ef4f 100644 --- a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java +++ b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java @@ -24,9 +24,9 @@ import java.util.Map; public class AppiumExecutionMethod implements ExecuteMethod { - private final AppiumDriver driver; + private final AppiumDriver driver; - public AppiumExecutionMethod(AppiumDriver driver) { + public AppiumExecutionMethod(AppiumDriver driver) { this.driver = driver; } diff --git a/src/main/java/io/appium/java_client/android/AndroidElement.java b/src/main/java/io/appium/java_client/CanSetElementValue.java similarity index 56% rename from src/main/java/io/appium/java_client/android/AndroidElement.java rename to src/main/java/io/appium/java_client/CanSetElementValue.java index 5c1231c24..45a7916b3 100644 --- a/src/main/java/io/appium/java_client/android/AndroidElement.java +++ b/src/main/java/io/appium/java_client/CanSetElementValue.java @@ -14,19 +14,22 @@ * limitations under the License. */ -package io.appium.java_client.android; +package io.appium.java_client; -import static io.appium.java_client.android.AndroidMobileCommandHelper.replaceElementValueCommand; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.remote.RemoteWebElement; -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.MobileElement; - -public class AndroidElement extends MobileElement { +public interface CanSetElementValue extends ExecutesMethod { /** - * This method replace current text value. - * @param value a new value + * Set a value to an element. + * + * @param webElement Web element instance. + * @param value Value to set. */ - public void replaceValue(String value) { - CommandExecutionHelper.execute(this, replaceElementValueCommand(this, value)); + default void setElementValue(RemoteWebElement webElement, String value) { + this.execute(MobileCommand.SET_VALUE, ImmutableMap.of( + "id", webElement.getId(), + "value", value + )); } } diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java b/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java deleted file mode 100644 index e6d45f5f8..000000000 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.CommandExecutor; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.remote.Response; - -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"unchecked", "rawtypes"}) -abstract class DefaultGenericMobileDriver extends RemoteWebDriver - implements MobileDriver { - - public DefaultGenericMobileDriver(CommandExecutor executor, Capabilities desiredCapabilities) { - super(executor, desiredCapabilities); - } - - @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); - } - - @Override public T findElement(By by) { - return (T) super.findElement(by); - } - - @Override - public String toString() { - Capabilities capabilities = getCapabilities(); - return String.format("%s, Capabilities: %s", getClass().getCanonicalName(), - capabilities != null ? capabilities.asMap().toString() : "null"); - } -} diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java b/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java deleted file mode 100644 index 6e1bfc64a..000000000 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebElement; -import org.openqa.selenium.remote.Response; - -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"unchecked", "rawtypes"}) -abstract class DefaultGenericMobileElement extends RemoteWebElement implements ExecutesMethod { - - @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); - } - - @Override public T findElement(By by) { - return (T) super.findElement(by); - } - -} diff --git a/src/main/java/io/appium/java_client/ExecutesMethod.java b/src/main/java/io/appium/java_client/ExecutesMethod.java index 1f49276bc..f0bd981ca 100644 --- a/src/main/java/io/appium/java_client/ExecutesMethod.java +++ b/src/main/java/io/appium/java_client/ExecutesMethod.java @@ -22,18 +22,18 @@ public interface ExecutesMethod { /** - * Executes JSONWP command and returns a response. + * Executes the given command and returns a response. * - * @param driverCommand a JSONWP command + * @param driverCommand a command to execute * @param parameters map of command parameters * @return a result response */ Response execute(String driverCommand, Map parameters); /** - * Executes JSONWP command and returns a response. + * Executes the given command and returns a response. * - * @param driverCommand a JSONWP command + * @param driverCommand a command to execute * @return a result response */ Response execute(String driverCommand); diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java new file mode 100644 index 000000000..efa5c6c62 --- /dev/null +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -0,0 +1,44 @@ +package io.appium.java_client; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.internal.CapabilityHelpers; +import org.openqa.selenium.ContextAware; +import org.openqa.selenium.HasCapabilities; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.CapabilityType; + +import java.util.Collections; + +import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + +public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { + /** + * Validates if the driver is currently in a web browser context. + * + * @return true or false. + */ + default boolean isBrowser() { + String browserName = CapabilityHelpers.getCapability(getCapabilities(), + CapabilityType.BROWSER_NAME, String.class); + if (!isBlank(browserName)) { + try { + return (boolean) execute(EXECUTE_SCRIPT, ImmutableMap.of( + "script", "return !!window.navigator;", + "args", Collections.emptyList() + )).getValue(); + } catch (WebDriverException ign) { + // ignore + } + } + if (!(this instanceof ContextAware)) { + return false; + } + try { + return !containsIgnoreCase(((ContextAware) this).getContext(), "NATIVE_APP"); + } catch (WebDriverException e) { + return false; + } + } +} diff --git a/src/main/java/io/appium/java_client/HasSessionDetails.java b/src/main/java/io/appium/java_client/HasSessionDetails.java deleted file mode 100644 index 1ae3f9f80..000000000 --- a/src/main/java/io/appium/java_client/HasSessionDetails.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 static io.appium.java_client.MobileCommand.GET_ALLSESSION; -import static io.appium.java_client.MobileCommand.GET_SESSION; -import static java.util.Optional.ofNullable; -import static java.util.stream.Collectors.toMap; -import static org.apache.commons.lang3.StringUtils.isBlank; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.remote.Response; - -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -public interface HasSessionDetails extends ExecutesMethod { - /** - * The current session details. - * - * @return a map with values that hold session details. - */ - @SuppressWarnings("unchecked") - default Map getSessionDetails() { - Response response = execute(GET_SESSION); - Map resultMap = Map.class.cast(response.getValue()); - - //this filtering was added to clear returned result. - //results of further operations should be simply interpreted by users - return ImmutableMap.builder() - .putAll(resultMap.entrySet() - .stream().filter(entry -> { - String key = entry.getKey(); - Object value = entry.getValue(); - return !isBlank(key) - && value != null - && !isBlank(String.valueOf(value)); - }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue))).build(); - } - - default @Nullable Object getSessionDetail(String detail) { - return getSessionDetails().get(detail); - } - - /** - * The current mobile platform. - * - * @return name of the current mobile platform. - */ - default @Nullable String getPlatformName() { - Object platformName = ofNullable(getSessionDetail("platformName")) - .orElseGet(() -> getSessionDetail("platform")); - return ofNullable(platformName).map(String::valueOf).orElse(null); - } - - /** - * The current automation name. - * - * @return current automation name. - */ - default @Nullable String getAutomationName() { - return ofNullable(getSessionDetail("automationName")) - .map(String::valueOf).orElse(null); - } - - /** - * Checks if focus is on browser. - * - * @return is focus on browser or on native content. - */ - default boolean isBrowser() { - return ofNullable(getSessionDetail("browserName")) - .orElse(null) != null; - } - - /** - * Get All Sessions details. - * - * @return List of Map objects with All Session Details. - */ - @SuppressWarnings("unchecked") - default List> getAllSessionDetails() { - Response response = execute(GET_ALLSESSION); - List> resultSet = List.class.cast(response.getValue()); - return ImmutableList.>builder().addAll(resultSet).build(); - } -} diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index f601aaab7..75435081e 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -41,7 +41,7 @@ public class MobileCommand { //General protected static final String RESET; protected static final String GET_STRINGS; - protected static final String SET_VALUE; + public static final String SET_VALUE; protected static final String PULL_FILE; protected static final String PULL_FOLDER; public static final String RUN_APP_IN_BACKGROUND; @@ -97,7 +97,7 @@ public class MobileCommand { protected static final String START_ACTIVITY; protected static final String TOGGLE_LOCATION_SERVICES; protected static final String UNLOCK; - protected static final String REPLACE_VALUE; + public static final String REPLACE_VALUE; protected static final String GET_SETTINGS; protected static final String SET_SETTINGS; protected static final String GET_CURRENT_PACKAGE; diff --git a/src/main/java/io/appium/java_client/MobileElement.java b/src/main/java/io/appium/java_client/MobileElement.java deleted file mode 100644 index 45c932b12..000000000 --- a/src/main/java/io/appium/java_client/MobileElement.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.remote.FileDetector; - -import java.util.List; - -@SuppressWarnings({"unchecked"}) -public abstract class MobileElement - extends DefaultGenericMobileElement { - - /** - * Method returns central coordinates of an element. - * @return The instance of the {@link org.openqa.selenium.Point} - */ - public Point getCenter() { - Point upperLeft = this.getLocation(); - Dimension dimensions = this.getSize(); - return new Point(upperLeft.getX() + dimensions.getWidth() / 2, - upperLeft.getY() + dimensions.getHeight() / 2); - } - - @Override public List findElements(By by) { - return super.findElements(by); - } - - /** - * This method sets the new value of the attribute "value". - * - * @param value is the new value which should be set - */ - public void setValue(String value) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.put("id", id).put("value", value); - execute(MobileCommand.SET_VALUE, builder.build()); - } -} 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 be4bd8e3d..50280c161 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -26,20 +26,29 @@ import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecuteCDPCommand; +import io.appium.java_client.HasAppStrings; +import io.appium.java_client.HasDeviceTime; import io.appium.java_client.HasOnScreenKeyboard; +import io.appium.java_client.HidesKeyboard; +import io.appium.java_client.InteractsWithApps; +import io.appium.java_client.InteractsWithFiles; import io.appium.java_client.LocksDevice; +import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.android.connection.HasNetworkConnection; import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; import io.appium.java_client.android.nativekey.PressesKey; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.SupportsContextSwitching; +import io.appium.java_client.remote.SupportsLocation; +import io.appium.java_client.remote.SupportsRotation; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -48,21 +57,36 @@ /** * Android driver implementation. - * - * @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 org.openqa.selenium.remote.RemoteWebElement} - * {@link io.appium.java_client.MobileElement} - * {@link io.appium.java_client.android.AndroidElement} */ -public class AndroidDriver - extends AppiumDriver - implements PressesKey, HasNetworkConnection, PushesFiles, StartsActivity,LocksDevice, HasAndroidSettings, - HasAndroidDeviceDetails, HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard, - CanRecordScreen, SupportsSpecialEmulatorCommands, SupportsNetworkStateManagement, ListensToLogcatMessages, - HasAndroidClipboard, HasBattery, ExecuteCDPCommand, SupportsExtendedGeolocationCommands { +public class AndroidDriver extends AppiumDriver implements + PressesKey, + SupportsRotation, + SupportsContextSwitching, + SupportsLocation, + PerformsTouchActions, + HidesKeyboard, + HasDeviceTime, + InteractsWithFiles, + InteractsWithApps, + HasAppStrings, + HasNetworkConnection, + PushesFiles, + StartsActivity, + LocksDevice, + HasAndroidSettings, + HasAndroidDeviceDetails, + HasSupportedPerformanceDataType, + AuthenticatesByFinger, + HasOnScreenKeyboard, + CanRecordScreen, + SupportsSpecialEmulatorCommands, + SupportsNetworkStateManagement, + ListensToLogcatMessages, + HasAndroidClipboard, + HasBattery, + ExecuteCDPCommand, + CanReplaceElementValue, + SupportsExtendedGeolocationCommands { private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; @@ -196,6 +220,11 @@ public AndroidBatteryInfo getBatteryInfo() { "script", "mobile: batteryInfo", "args", Collections.emptyList())).getValue()); } + @Override + public RemoteLocationContext getLocationContext() { + return locationContext; + } + @Override public synchronized StringWebSocketClient getLogcatClient() { if (logcatClient == null) { diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java new file mode 100644 index 000000000..72a170f32 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -0,0 +1,21 @@ +package io.appium.java_client.android; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.MobileCommand; +import org.openqa.selenium.remote.RemoteWebElement; + +public interface CanReplaceElementValue extends ExecutesMethod { + /** + * Replaces element value with the given one. + * + * @param element The destination element. + * @param value The value to set. + */ + default void replaceElementValue(RemoteWebElement element, String value) { + this.execute(MobileCommand.REPLACE_VALUE, ImmutableMap.of( + "id", element.getId(), + "value", value + )); + } +} diff --git a/src/main/java/io/appium/java_client/internal/ElementMap.java b/src/main/java/io/appium/java_client/internal/ElementMap.java deleted file mode 100644 index 75948be47..000000000 --- a/src/main/java/io/appium/java_client/internal/ElementMap.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.internal; - -import static org.apache.commons.lang3.StringUtils.isBlank; - -import com.google.common.collect.ImmutableMap; - -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.ios.IOSElement; -import io.appium.java_client.mac.Mac2Element; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.windows.WindowsElement; -import org.openqa.selenium.remote.RemoteWebElement; - -import java.util.Map; -import java.util.Optional; - -public enum ElementMap { - ANDROID_UIAUTOMATOR2(AutomationName.ANDROID_UIAUTOMATOR2.toLowerCase(), AndroidElement.class), - IOS_XCUI_TEST(AutomationName.IOS_XCUI_TEST.toLowerCase(), IOSElement.class), - ANDROID_UI_AUTOMATOR(MobilePlatform.ANDROID.toLowerCase(), AndroidElement.class), - IOS_UI_AUTOMATION(MobilePlatform.IOS.toLowerCase(), IOSElement.class), - WINDOWS(MobilePlatform.WINDOWS.toLowerCase(), WindowsElement.class), - MAC(MobilePlatform.MAC.toLowerCase(), Mac2Element.class); - - private static final Map mobileElementMap; - - static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (ElementMap e:values()) { - builder.put(e.getPlatformOrAutomation(), e); - } - mobileElementMap = builder.build(); - } - - private final String platformOrAutomation; - private final Class elementClass; - - ElementMap(String platformOrAutomation, Class elementClass) { - this.platformOrAutomation = platformOrAutomation; - this.elementClass = elementClass; - } - - public String getPlatformOrAutomation() { - return platformOrAutomation; - } - - public Class getElementClass() { - return elementClass; - } - - /** - * Gets element class by {@code platform} and mobile {@code automation} type. - * - * @param platform is the mobile platform. See {@link MobilePlatform}. - * @param automation is the mobile automation type. See {@link AutomationName} - * @return subclass of {@link RemoteWebElement} that convenient to current session details. - */ - public static Class getElementClass(String platform, String automation) { - if (isBlank(platform) && isBlank(automation)) { - return RemoteWebElement.class; - } - ElementMap element = Optional.ofNullable(mobileElementMap.get( - String.valueOf(platform).toLowerCase().trim())) - .orElseGet(() -> mobileElementMap - .get(String.valueOf(automation).toLowerCase().trim())); - if (element == null) { - return RemoteWebElement.class; - } - return element.getElementClass(); - } -} diff --git a/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java b/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java deleted file mode 100644 index d69e39312..000000000 --- a/src/main/java/io/appium/java_client/internal/JsonToMobileElementConverter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.internal; - -import static io.appium.java_client.internal.ElementMap.getElementClass; - -import io.appium.java_client.remote.MobileCapabilityType; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.remote.JsonToWebElementConverter; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.remote.RemoteWebElement; - -import java.lang.reflect.Constructor; - -/** - * Reconstitutes {@link org.openqa.selenium.WebElement}s from their JSON representation. Will recursively convert Lists - * and Maps to catch nested references. All other values pass through the converter unchanged. - */ -public class JsonToMobileElementConverter extends JsonToWebElementConverter { - - protected final RemoteWebDriver driver; - - private final String platform; - private final String automation; - - /** - * Creates a new instance based on {@code driver} and object with session details. - * - * @param driver an instance of {@link RemoteWebDriver} subclass - */ - public JsonToMobileElementConverter(RemoteWebDriver driver) { - super(driver); - this.driver = driver; - Capabilities caps = driver.getCapabilities(); - this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); - this.automation = CapabilityHelpers.getCapability(caps, MobileCapabilityType.AUTOMATION_NAME, String.class); - } - - @Override - public Object apply(Object result) { - Object toBeReturned = result; - if (toBeReturned instanceof RemoteWebElement) { - toBeReturned = newRemoteWebElement(); - ((RemoteWebElement) toBeReturned).setId(((RemoteWebElement) result).getId()); - } - - return super.apply(toBeReturned); - } - - @Override - protected RemoteWebElement newRemoteWebElement() { - Class target; - target = getElementClass(platform, automation); - - try { - Constructor constructor = target.getDeclaredConstructor(); - constructor.setAccessible(true); - RemoteWebElement result = constructor.newInstance(); - - result.setParent(driver); - result.setFileDetector(driver.getFileDetector()); - - return result; - } catch (Exception e) { - throw new WebDriverException(e); - } - } -} 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 ffd4a8a0c..70fe3c46d 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -22,21 +22,30 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumDriver; +import io.appium.java_client.HasAppStrings; +import io.appium.java_client.HasDeviceTime; import io.appium.java_client.HasOnScreenKeyboard; +import io.appium.java_client.HidesKeyboard; import io.appium.java_client.HidesKeyboardWithKeyName; +import io.appium.java_client.InteractsWithApps; +import io.appium.java_client.InteractsWithFiles; import io.appium.java_client.LocksDevice; +import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.SupportsContextSwitching; +import io.appium.java_client.remote.SupportsLocation; +import io.appium.java_client.remote.SupportsRotation; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.Alert; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; +import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -46,19 +55,27 @@ /** * iOS driver implementation. * - * @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 org.openqa.selenium.remote.RemoteWebElement} - * {@link io.appium.java_client.MobileElement} - * {@link io.appium.java_client.ios.IOSElement} */ -public class IOSDriver - extends AppiumDriver - implements HidesKeyboardWithKeyName, ShakesDevice, HasIOSSettings, HasOnScreenKeyboard, LocksDevice, - PerformsTouchID, PushesFiles, CanRecordScreen, HasIOSClipboard, ListensToSyslogMessages, +public class IOSDriver extends AppiumDriver implements + SupportsContextSwitching, + SupportsRotation, + SupportsLocation, + HidesKeyboard, + HasDeviceTime, + InteractsWithFiles, + InteractsWithApps, + HasAppStrings, + PerformsTouchActions, + HidesKeyboardWithKeyName, + ShakesDevice, + HasIOSSettings, + HasOnScreenKeyboard, + LocksDevice, + PerformsTouchID, + PushesFiles, + CanRecordScreen, + HasIOSClipboard, + ListensToSyslogMessages, HasBattery { private static final String IOS_DEFAULT_PLATFORM = MobilePlatform.IOS; @@ -208,6 +225,11 @@ class IOSAlert implements Alert { } + @Override + public RemoteLocationContext getLocationContext() { + return locationContext; + } + @Override public synchronized StringWebSocketClient getSyslogClient() { if (syslogClient == null) { diff --git a/src/main/java/io/appium/java_client/ios/IOSElement.java b/src/main/java/io/appium/java_client/ios/IOSElement.java deleted file mode 100644 index 55aa47110..000000000 --- a/src/main/java/io/appium/java_client/ios/IOSElement.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 io.appium.java_client.MobileElement; - -public class IOSElement extends MobileElement { -} diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index 215c28971..9ad2b368c 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -17,7 +17,6 @@ package io.appium.java_client.mac; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.HasSettings; import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobileCapabilityType; @@ -25,8 +24,7 @@ import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; @@ -44,7 +42,8 @@ * * @since Appium 1.20.0 */ -public class Mac2Driver extends AppiumDriver implements CanRecordScreen, HasSettings { +public class Mac2Driver extends AppiumDriver implements + CanRecordScreen { public Mac2Driver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, prepareCaps(capabilities)); } @@ -84,16 +83,14 @@ public Mac2Driver(Capabilities desiredCapabilities) { } private static Capabilities prepareCaps(Capabilities originalCaps) { - DesiredCapabilities dc = new DesiredCapabilities(originalCaps); - if (originalCaps.getCapability(PLATFORM_NAME) == null) { - dc.setCapability(PLATFORM_NAME, MAC); - } String automationName = CapabilityHelpers.getCapability(originalCaps, MobileCapabilityType.AUTOMATION_NAME, String.class); - if (!AutomationName.MAC2.equalsIgnoreCase(automationName)) { - dc.setCapability(CapabilityHelpers.APPIUM_PREFIX - + MobileCapabilityType.AUTOMATION_NAME, AutomationName.MAC2); - } - return dc; + return (originalCaps.getCapability(PLATFORM_NAME) == null + || !AutomationName.MAC2.equalsIgnoreCase(automationName)) + ? originalCaps.merge(new ImmutableCapabilities( + PLATFORM_NAME, MAC, + MobileCapabilityType.AUTOMATION_NAME, AutomationName.MAC2 + )) + : originalCaps; } } diff --git a/src/main/java/io/appium/java_client/mac/Mac2Element.java b/src/main/java/io/appium/java_client/mac/Mac2Element.java deleted file mode 100644 index e41042e8d..000000000 --- a/src/main/java/io/appium/java_client/mac/Mac2Element.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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.mac; - -import io.appium.java_client.MobileElement; - -public class Mac2Element extends MobileElement { -} diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 1d2b9caa0..ea3b35e5a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -16,21 +16,16 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.internal.ElementMap.getElementClass; import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; import static java.time.Duration.ofSeconds; import com.google.common.collect.ImmutableList; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.AndroidElement; import io.appium.java_client.internal.CapabilityHelpers; -import io.appium.java_client.ios.IOSElement; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.windows.WindowsElement; import org.openqa.selenium.Capabilities; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.SearchContext; @@ -60,15 +55,13 @@ * {@literal @AndroidFindBy}, {@literal @AndroidFindBys}, or * {@literal @iOSFindBy/@iOSFindBys} annotation with a proxy that locates the * elements using the passed in ElementLocatorFactory. - * Please pay attention: fields of {@link WebElement}, {@link RemoteWebElement}, - * {@link MobileElement}, {@link AndroidElement} and {@link IOSElement} are allowed + * Please pay attention: fields of {@link WebElement} or {@link RemoteWebElement} * to use with this decorator */ public class AppiumFieldDecorator implements FieldDecorator { private static final List> availableElementClasses = ImmutableList.of(WebElement.class, - RemoteWebElement.class, MobileElement.class, AndroidElement.class, - IOSElement.class, WindowsElement.class); + RemoteWebElement.class); public static final Duration DEFAULT_WAITING_TIMEOUT = ofSeconds(1); private final WebDriver webDriver; private final DefaultFieldDecorator defaultElementFieldDecoracor; @@ -213,6 +206,6 @@ private Object decorateWidget(Field field) { private WebElement proxyForAnElement(ElementLocator locator) { ElementInterceptor elementInterceptor = new ElementInterceptor(locator, webDriver); - return getEnhancedProxy(getElementClass(platform, automation), elementInterceptor); + return getEnhancedProxy(RemoteWebElement.class, elementInterceptor); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index b15ee6775..e11aa2e4d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -21,7 +21,7 @@ import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; -import io.appium.java_client.HasSessionDetails; +import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; import org.openqa.selenium.ContextAware; import org.openqa.selenium.SearchContext; @@ -72,7 +72,7 @@ public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchCon * {@link WebDriver} or {@link org.openqa.selenium.WebElement} or some other * user's extension/implementation. * Note: if you want to use your own implementation then it should - * implement {@link ContextAware} or {@link WrapsDriver} or {@link HasSessionDetails} + * implement {@link ContextAware} or {@link WrapsDriver} or {@link HasBrowserCheck} * @return current content type. It depends on current context. If current context is * NATIVE_APP it will return {@link ContentType#NATIVE_MOBILE_SPECIFIC}. * {@link ContentType#HTML_OR_DEFAULT} will be returned if the current context is WEB_VIEW. @@ -81,12 +81,8 @@ public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchCon */ public static ContentType getCurrentContentType(SearchContext context) { return ofNullable(unpackWebDriverFromSearchContext(context)).map(driver -> { - if (HasSessionDetails.class.isAssignableFrom(driver.getClass())) { - HasSessionDetails hasSessionDetails = (HasSessionDetails) driver; - - if (!hasSessionDetails.isBrowser()) { - return NATIVE_MOBILE_SPECIFIC; - } + if (driver instanceof HasBrowserCheck && !((HasBrowserCheck) driver).isBrowser()) { + return NATIVE_MOBILE_SPECIFIC; } if (ContextAware.class.isAssignableFrom(driver.getClass())) { //it is desktop browser diff --git a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java new file mode 100644 index 000000000..7f5f79956 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java @@ -0,0 +1,81 @@ +/* + * 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.remote; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.NoSuchContextException; +import org.openqa.selenium.ContextAware; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.DriverCommand; +import org.openqa.selenium.remote.Response; + +import javax.annotation.Nullable; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +public interface SupportsContextSwitching extends WebDriver, ContextAware, ExecutesMethod { + /** + * Switches to the given context. + * + * @param name The name of the context to switch to. + * @return self instance for chaining. + */ + default WebDriver context(String name) { + checkNotNull(name, "Must supply a context name"); + try { + execute(DriverCommand.SWITCH_TO_CONTEXT, ImmutableMap.of("name", name)); + return this; + } catch (WebDriverException e) { + throw new NoSuchContextException(e.getMessage(), e); + } + } + + /** + * Get the names of available contexts. + * + * @return List list of context names. + */ + default Set getContextHandles() { + Response response = execute(DriverCommand.GET_CONTEXT_HANDLES, ImmutableMap.of()); + Object value = response.getValue(); + try { + //noinspection unchecked + List returnedValues = (List) value; + return new LinkedHashSet<>(returnedValues); + } catch (ClassCastException ex) { + throw new WebDriverException( + "Returned value cannot be converted to List: " + value, ex); + } + } + + /** + * Get the name of the current context. + * + * @return Context name or null if it cannot be determined. + */ + @Nullable + default String getContext() { + String contextName = + String.valueOf(execute(DriverCommand.GET_CURRENT_CONTEXT_HANDLE).getValue()); + return "null".equalsIgnoreCase(contextName) ? null : contextName; + } +} diff --git a/src/main/java/io/appium/java_client/MobileDriver.java b/src/main/java/io/appium/java_client/remote/SupportsLocation.java similarity index 59% rename from src/main/java/io/appium/java_client/MobileDriver.java rename to src/main/java/io/appium/java_client/remote/SupportsLocation.java index 708f3b8f0..b2211dfda 100644 --- a/src/main/java/io/appium/java_client/MobileDriver.java +++ b/src/main/java/io/appium/java_client/remote/SupportsLocation.java @@ -14,22 +14,21 @@ * limitations under the License. */ -package io.appium.java_client; +package io.appium.java_client.remote; -import org.openqa.selenium.By; -import org.openqa.selenium.ContextAware; -import org.openqa.selenium.Rotatable; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; +import org.openqa.selenium.html5.Location; import org.openqa.selenium.html5.LocationContext; +import org.openqa.selenium.remote.html5.RemoteLocationContext; -import java.util.List; +public interface SupportsLocation extends WebDriver, LocationContext { + public RemoteLocationContext getLocationContext(); -public interface MobileDriver extends WebDriver, PerformsTouchActions, ContextAware, Rotatable, - LocationContext, HidesKeyboard, HasDeviceTime, InteractsWithFiles, InteractsWithApps, HasAppStrings, ExecutesMethod, - HasSessionDetails { + default Location location() { + return getLocationContext().location(); + } - List findElements(By by); - - T findElement(By by); + default void setLocation(Location location) { + getLocationContext().setLocation(location); + } } diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java new file mode 100644 index 000000000..8ac22a707 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -0,0 +1,61 @@ +/* + * 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.remote; + +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.DeviceRotation; +import org.openqa.selenium.Rotatable; +import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.remote.DriverCommand; +import org.openqa.selenium.remote.Response; + +import java.util.Map; + +public interface SupportsRotation extends WebDriver, ExecutesMethod, Rotatable { + /** + * Get device rotation. + * + * @return The rotation value. + */ + default DeviceRotation rotation() { + Response response = execute(DriverCommand.GET_SCREEN_ROTATION); + //noinspection unchecked + return new DeviceRotation((Map) response.getValue()); + } + + default void rotate(DeviceRotation rotation) { + execute(DriverCommand.SET_SCREEN_ROTATION, rotation.parameters()); + } + + default void rotate(ScreenOrientation orientation) { + execute(DriverCommand.SET_SCREEN_ORIENTATION, + ImmutableMap.of("orientation", orientation.value().toUpperCase())); + } + + /** + * Get device orientation. + * + * @return The orientation value. + */ + default ScreenOrientation getOrientation() { + Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); + String orientation = String.valueOf(response.getValue()); + return ScreenOrientation.valueOf(orientation.toUpperCase()); + } +} diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index cf89449de..032ce91cd 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -24,14 +24,15 @@ import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; -public class WindowsDriver - extends AppiumDriver implements PressesKeyCode, HidesKeyboardWithKeyName, CanRecordScreen { +public class WindowsDriver extends AppiumDriver implements + PressesKeyCode, + HidesKeyboardWithKeyName, + CanRecordScreen { public WindowsDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, updateDefaultPlatformName(capabilities, WINDOWS)); diff --git a/src/main/java/io/appium/java_client/windows/WindowsElement.java b/src/main/java/io/appium/java_client/windows/WindowsElement.java deleted file mode 100644 index ad5d3a5d8..000000000 --- a/src/main/java/io/appium/java_client/windows/WindowsElement.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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.windows; - -import io.appium.java_client.MobileElement; - -public class WindowsElement extends MobileElement { -} diff --git a/src/main/java/org/openqa/selenium/SearchContext.java b/src/main/java/org/openqa/selenium/SearchContext.java deleted file mode 100644 index d6498972e..000000000 --- a/src/main/java/org/openqa/selenium/SearchContext.java +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium; - -import java.util.List; - -public interface SearchContext { - /** - * Find all elements within the current context using the given mechanism. - * - * @param The type of the resulting elements. - * @param by The locating mechanism to use - * @return A list of all {@link WebElement}s, or an empty list if nothing matches - * @see org.openqa.selenium.By - */ - List findElements(By by); - - - /** - * Find the first {@link WebElement} using the given method. - * - * @param The type of the resulting element. - * @param by The locating mechanism - * @return The first matching element on the current context - * @throws NoSuchElementException If no matching elements are found - */ - T findElement(By by); -} diff --git a/src/main/java/org/openqa/selenium/WebDriver.java b/src/main/java/org/openqa/selenium/WebDriver.java deleted file mode 100644 index c8f990896..000000000 --- a/src/main/java/org/openqa/selenium/WebDriver.java +++ /dev/null @@ -1,757 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium; - -import org.openqa.selenium.logging.LoggingPreferences; -import org.openqa.selenium.logging.Logs; - -import java.net.URL; -import java.time.Duration; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - - -/** - * WebDriver is a remote control interface that enables introspection and control of user agents - * (browsers). The methods in this interface fall into three categories: - *
    - *
  • Control of the browser itself
  • - *
  • Selection of {@link WebElement}s
  • - *
  • Debugging aids
  • - *
- *

- * Key methods are {@link WebDriver#get(String)}, which is used to load a new web page, and the - * various methods similar to {@link WebDriver#findElement(By)}, which is used to find - * {@link WebElement}s. - *

- * Currently, you will need to instantiate implementations of this interface directly. It is hoped - * that you write your tests against this interface so that you may "swap in" a more fully featured - * browser when there is a requirement for one. - *

- * Most implementations of this interface follow - * W3C WebDriver specification - */ -public interface WebDriver extends SearchContext { - // Navigation - - /** - * Load a new web page in the current browser window. This is done using an HTTP POST operation, - * and the method will block until the load is complete (with the default 'page load strategy'. - * This will follow redirects issued either by the server or as a meta-redirect from within the - * returned HTML. Should a meta-redirect "rest" for any duration of time, it is best to wait until - * this timeout is over, since should the underlying page change whilst your test is executing the - * results of future calls against this interface will be against the freshly loaded page. Synonym - * for {@link org.openqa.selenium.WebDriver.Navigation#to(String)}. - *

- * See W3C WebDriver specification - * for more details. - * - * @param url The URL to load. Must be a fully qualified URL - * @see org.openqa.selenium.PageLoadStrategy - */ - void get(String url); - - /** - * Get a string representing the current URL that the browser is looking at. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The URL of the page currently loaded in the browser - */ - String getCurrentUrl(); - - // General properties - - /** - * Get the title of the current page. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The title of the current page, with leading and trailing whitespace stripped, or null - * if one is not already set - */ - String getTitle(); - - /** - * Find all elements within the current page using the given mechanism. - * This method is affected by the 'implicit wait' times in force at the time of execution. When - * implicitly waiting, this method will return as soon as there are more than 0 items in the - * found collection, or will return an empty list if the timeout is reached. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism to use - * @return A list of all matching {@link WebElement}s, or an empty list if nothing matches - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - List findElements(By by); - - - /** - * Find the first {@link WebElement} using the given method. - * This method is affected by the 'implicit wait' times in force at the time of execution. - * The findElement(..) invocation will return a matching row, or try again repeatedly until - * the configured timeout is reached. - *

- * findElement should not be used to look for non-present elements, use {@link #findElements(By)} - * and assert zero length response instead. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism to use - * @return The first matching element on the current page - * @throws NoSuchElementException If no matching elements are found - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - T findElement(By by); - - // Misc - - /** - * Get the source of the last loaded page. If the page has been modified after loading (for - * example, by Javascript) there is no guarantee that the returned text is that of the modified - * page. Please consult the documentation of the particular driver being used to determine whether - * the returned text reflects the current state of the page or the text last sent by the web - * server. The page source returned is a representation of the underlying DOM: do not expect it to - * be formatted or escaped in the same way as the response sent from the web server. Think of it - * as an artist's impression. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The source of the current page - */ - String getPageSource(); - - /** - * Close the current window, quitting the browser if it's the last window currently open. - *

- * See W3C WebDriver specification - * for more details. - */ - void close(); - - /** - * Quits this driver, closing every associated window. - */ - void quit(); - - /** - * Return a set of window handles which can be used to iterate over all open windows of this - * WebDriver instance by passing them to {@link #switchTo()}.{@link Options#window()} - *

- * See W3C WebDriver specification - * for more details. - * - * @return A set of window handles which can be used to iterate over all open windows. - */ - Set getWindowHandles(); - - /** - * Return an opaque handle to this window that uniquely identifies it within this driver instance. - * This can be used to switch to this window at a later date - *

- * See W3C WebDriver specification - * for more details. - * - * @return the current window handle - */ - String getWindowHandle(); - - /** - * Send future commands to a different frame or window. - * - * @return A TargetLocator which can be used to select a frame or window - * @see org.openqa.selenium.WebDriver.TargetLocator - */ - TargetLocator switchTo(); - - /** - * An abstraction allowing the driver to access the browser's history and to navigate to a given - * URL. - * - * @return A {@link org.openqa.selenium.WebDriver.Navigation} that allows the selection of what to - * do next - */ - Navigation navigate(); - - /** - * Gets the Option interface - * - * @return An option interface - * @see org.openqa.selenium.WebDriver.Options - */ - Options manage(); - - /** - * An interface for managing stuff you would do in a browser menu - */ - interface Options { - - /** - * Add a specific cookie. If the cookie's domain name is left blank, it is assumed that the - * cookie is meant for the domain of the current document. - *

- * See W3C WebDriver specification - * for more details. - * - * @param cookie The cookie to add. - */ - void addCookie(Cookie cookie); - - /** - * Delete the named cookie from the current domain. This is equivalent to setting the named - * cookie's expiry date to some time in the past. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the cookie to delete - */ - void deleteCookieNamed(String name); - - /** - * Delete a cookie from the browser's "cookie jar". The domain of the cookie will be ignored. - * - * @param cookie nom nom nom - */ - void deleteCookie(Cookie cookie); - - /** - * Delete all the cookies for the current domain. - *

- * See W3C WebDriver specification - * for more details. - */ - void deleteAllCookies(); - - /** - * Get all the cookies for the current domain. - *

- * See W3C WebDriver specification - * for more details. - * - * @return A Set of cookies for the current domain. - */ - Set getCookies(); - - /** - * Get a cookie with a given name. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name the name of the cookie - * @return the cookie, or null if no cookie with the given name is present - */ - Cookie getCookieNamed(String name); - - /** - * @return the interface for managing driver timeouts. - */ - Timeouts timeouts(); - - /** - * @return the interface for controlling IME engines to generate complex-script input. - */ - ImeHandler ime(); - - /** - * @return the interface for managing the current window. - */ - Window window(); - - /** - * Gets the {@link Logs} interface used to fetch different types of logs. - *

- * To set the logging preferences {@link LoggingPreferences}. - * - * @return A Logs interface. - */ - @Beta - Logs logs(); - } - - /** - * An interface for managing timeout behavior for WebDriver instances. - *

- * See W3C WebDriver specification - * for more details. - */ - interface Timeouts { - - /** - * @deprecated Use {@link #implicitlyWait(Duration)} - * - * Specifies the amount of time the driver should wait when searching for an element if it is - * not immediately present. - *

- * When searching for a single element, the driver should poll the page until the element has - * been found, or this timeout expires before throwing a {@link NoSuchElementException}. When - * searching for multiple elements, the driver should poll the page until at least one element - * has been found or this timeout has expired. - *

- * Increasing the implicit wait timeout should be used judiciously as it will have an adverse - * effect on test run time, especially when used with slower location strategies like XPath. - *

- * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with invalid - * argument will be returned. - * - * @param time The amount of time to wait. - * @param unit The unit of measure for {@code time}. - * @return A self reference. - */ - @Deprecated - Timeouts implicitlyWait(long time, TimeUnit unit); - - /** - * Specifies the amount of time the driver should wait when searching for an element if it is - * not immediately present. - *

- * When searching for a single element, the driver should poll the page until the element has - * been found, or this timeout expires before throwing a {@link NoSuchElementException}. When - * searching for multiple elements, the driver should poll the page until at least one element - * has been found or this timeout has expired. - *

- * Increasing the implicit wait timeout should be used judiciously as it will have an adverse - * effect on test run time, especially when used with slower location strategies like XPath. - *

- * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with invalid - * argument will be returned. - * - * @param duration The duration to wait. - * @return A self reference. - */ - default Timeouts implicitlyWait(Duration duration) { - return implicitlyWait(duration.toMillis(), TimeUnit.MILLISECONDS); - } - - /** - * Gets the amount of time the driver should wait when searching for an element if it is - * not immediately present. - * - * @return The amount of time the driver should wait when searching for an element. - * @see W3C WebDriver - */ - default Duration getImplicitWaitTimeout() { - throw new UnsupportedCommandException(); - } - - /** - * @deprecated Use {@link #setScriptTimeout(Duration)} - * - * Sets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @param time The timeout value. - * @param unit The unit of time. - * @return A self reference. - * @see JavascriptExecutor#executeAsyncScript(String, Object...) - * @see W3C WebDriver - * @see W3C WebDriver - */ - @Deprecated - Timeouts setScriptTimeout(long time, TimeUnit unit); - - /** - * Sets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @param duration The timeout value. - * @deprecated Use {@link #scriptTimeout(Duration)} - * @return A self reference. - * @see JavascriptExecutor#executeAsyncScript(String, Object...) - * @see W3C WebDriver - * @see W3C WebDriver - */ - @Deprecated - default Timeouts setScriptTimeout(Duration duration) { - return setScriptTimeout(duration.toMillis(), TimeUnit.MILLISECONDS); - } - - /** - * Sets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @param duration The timeout value. - * @return A self reference. - * @see JavascriptExecutor#executeAsyncScript(String, Object...) - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Timeouts scriptTimeout(Duration duration) { - return setScriptTimeout(duration); - } - - /** - * Gets the amount of time to wait for an asynchronous script to finish execution before - * throwing an error. If the timeout is negative, not null, or greater than 2e16 - 1, an - * error code with invalid argument will be returned. - * - * @return The amount of time to wait for an asynchronous script to finish execution. - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Duration getScriptTimeout() { - throw new UnsupportedCommandException(); - } - - /** - * @param time The timeout value. - * @param unit The unit of time. - * @return A Timeouts interface. - * @see W3C WebDriver - * @see W3C WebDriver - * @deprecated Use {@link #pageLoadTimeout(Duration)} - * - * Sets the amount of time to wait for a page load to complete before throwing an error. - * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with - * invalid argument will be returned. - */ - @Deprecated - Timeouts pageLoadTimeout(long time, TimeUnit unit); - - /** - * Sets the amount of time to wait for a page load to complete before throwing an error. - * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with - * invalid argument will be returned. - * - * @param duration The timeout value. - * @return A Timeouts interface. - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Timeouts pageLoadTimeout(Duration duration) { - return pageLoadTimeout(duration.toMillis(), TimeUnit.MILLISECONDS); - } - - /** - * Gets the amount of time to wait for a page load to complete before throwing an error. - * If the timeout is negative, not null, or greater than 2e16 - 1, an error code with - * invalid argument will be returned. - * - * @return The amount of time to wait for a page load to complete. - * @see W3C WebDriver - * @see W3C WebDriver - */ - default Duration getPageLoadTimeout() { - throw new UnsupportedCommandException(); - } - } - - /** - * Used to locate a given frame or window. - */ - interface TargetLocator { - /** - * Select a frame by its (zero-based) index. Selecting a frame by index is equivalent to the - * JS expression window.frames[index] where "window" is the DOM window represented by the - * current context. Once the frame has been selected, all subsequent calls on the WebDriver - * interface are made to that frame. - *

- * See W3C WebDriver specification - * for more details. - * - * @param index (zero-based) index - * @return This driver focused on the given frame - * @throws NoSuchFrameException If the frame cannot be found - */ - WebDriver frame(int index); - - /** - * Select a frame by its name or ID. Frames located by matching name attributes are always given - * precedence over those matched by ID. - * - * @param nameOrId the name of the frame window, the id of the <frame> or <iframe> - * element, or the (zero-based) index - * @return This driver focused on the given frame - * @throws NoSuchFrameException If the frame cannot be found - */ - WebDriver frame(String nameOrId); - - /** - * Select a frame using its previously located {@link WebElement}. - *

- * See W3C WebDriver specification - * for more details. - * - * @param frameElement The frame element to switch to. - * @return This driver focused on the given frame. - * @throws NoSuchFrameException If the given element is neither an IFRAME nor a FRAME element. - * @throws StaleElementReferenceException If the WebElement has gone stale. - * @see WebDriver#findElement(By) - */ - WebDriver frame(WebElement frameElement); - - /** - * Change focus to the parent context. If the current context is the top level browsing context, - * the context remains unchanged. - *

- * See W3C WebDriver specification - * for more details. - * - * @return This driver focused on the parent frame - */ - WebDriver parentFrame(); - - /** - * Switch the focus of future commands for this driver to the window with the given name/handle. - *

- * See W3C WebDriver specification - * for more details. - * - * @param nameOrHandle The name of the window or the handle as returned by - * {@link WebDriver#getWindowHandle()} - * @return This driver focused on the given window - * @throws NoSuchWindowException If the window cannot be found - */ - WebDriver window(String nameOrHandle); - - /** - * Creates a new browser window and switches the focus for future commands of this driver - * to the new window. - *

- * See W3C WebDriver specification - * for more details. - * - * @param typeHint The type of new browser window to be created. The created window is not - * guaranteed to be of the requested type; if the driver does not support - * the requested type, a new browser window will be created of whatever type - * the driver does support. - * @return This driver focused on the given window - */ - WebDriver newWindow(WindowType typeHint); - - /** - * Selects either the first frame on the page, or the main document when a page contains - * iframes. - *

- * See W3C WebDriver specification - * for more details. - * - * @return This driver focused on the top window/first frame. - */ - WebDriver defaultContent(); - - /** - * Switches to the element that currently has focus within the document currently "switched to", - * or the body element if this cannot be detected. This matches the semantics of calling - * "document.activeElement" in Javascript. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The WebElement with focus, or the body element if no element with focus can be - * detected. - */ - WebElement activeElement(); - - /** - * Switches to the currently active modal dialog for this particular driver instance. - * - * @return A handle to the dialog. - * @throws NoAlertPresentException If the dialog cannot be found - */ - Alert alert(); - } - - interface Navigation { - /** - * Move back a single "item" in the browser's history. - *

- * See W3C WebDriver specification - * for more details. - */ - void back(); - - /** - * Move a single "item" forward in the browser's history. Does nothing if we are on the latest - * page viewed. - *

- * See W3C WebDriver specification - * for more details. - */ - void forward(); - - - /** - * Load a new web page in the current browser window. This is done using an HTTP POST operation, - * and the method will block until the load is complete. This will follow redirects issued - * either by the server or as a meta-redirect from within the returned HTML. Should a - * meta-redirect "rest" for any duration of time, it is best to wait until this timeout is over, - * since should the underlying page change whilst your test is executing the results of future - * calls against this interface will be against the freshly loaded page. - *

- * See W3C WebDriver specification - * for more details. - * - * @param url The URL to load. Must be a fully qualified URL - */ - void to(String url); - - /** - * Overloaded version of {@link #to(String)} that makes it easy to pass in a URL. - * - * @param url URL - */ - void to(URL url); - - /** - * Refresh the current page - *

- * See W3C WebDriver specification - * for more details. - */ - void refresh(); - } - - /** - * An interface for managing input methods. - */ - interface ImeHandler { - /** - * All available engines on the machine. To use an engine, it has to be activated. - * - * @return list of available IME engines. - * @throws ImeNotAvailableException if the host does not support IME. - */ - List getAvailableEngines(); - - /** - * Get the name of the active IME engine. The name string is platform-specific. - * - * @return name of the active IME engine. - * @throws ImeNotAvailableException if the host does not support IME. - */ - String getActiveEngine(); - - /** - * Indicates whether IME input active at the moment (not if it's available). - * - * @return true if IME input is available and currently active, false otherwise. - * @throws ImeNotAvailableException if the host does not support IME. - */ - boolean isActivated(); - - /** - * De-activate IME input (turns off the currently activated engine). Note that getActiveEngine - * may still return the name of the engine but isActivated will return false. - * - * @throws ImeNotAvailableException if the host does not support IME. - */ - void deactivate(); - - /** - * Make an engines that is available (appears on the list returned by getAvailableEngines) - * active. After this call, the only loaded engine on the IME daemon will be this one and the - * input sent using sendKeys will be converted by the engine. Note that this is a - * platform-independent method of activating IME (the platform-specific way being using keyboard - * shortcuts). - * - * - * @param engine name of engine to activate. - * @throws ImeNotAvailableException if the host does not support IME. - * @throws ImeActivationFailedException if the engine is not available or if activation failed - * for other reasons. - */ - void activateEngine(String engine); - } - - @Beta - interface Window { - - /** - * Get the size of the current window. This will return the outer window dimension, not just - * the view port. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The current window size. - */ - Dimension getSize(); - - /** - * Set the size of the current window. This will change the outer window dimension, - * not just the view port, synonymous to window.resizeTo() in JS. - *

- * See W3C WebDriver specification - * for more details. - * - * @param targetSize The target size. - */ - void setSize(Dimension targetSize); - - /** - * Get the position of the current window, relative to the upper left corner of the screen. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The current window position. - */ - Point getPosition(); - - /** - * Set the position of the current window. This is relative to the upper left corner of the - * screen, synonymous to window.moveTo() in JS. - *

- * See W3C WebDriver specification - * for more details. - * - * @param targetPosition The target position of the window. - */ - void setPosition(Point targetPosition); - - /** - * Maximizes the current window if it is not already maximized - *

- * See W3C WebDriver specification - * for more details. - */ - void maximize(); - - /** - * Minimizes the current window if it is not already minimized - *

- * See W3C WebDriver specification - * for more details. - */ - void minimize(); - - /** - * Fullscreen the current window if it is not already fullscreen - *

- * See W3C WebDriver specification - * for more details. - */ - void fullscreen(); - } -} diff --git a/src/main/java/org/openqa/selenium/WebElement.java b/src/main/java/org/openqa/selenium/WebElement.java deleted file mode 100644 index ba2e441b7..000000000 --- a/src/main/java/org/openqa/selenium/WebElement.java +++ /dev/null @@ -1,338 +0,0 @@ -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.openqa.selenium; - -import java.util.List; - -/** - * Represents an HTML element. Generally, all interesting operations to do with interacting with a - * page will be performed through this interface. - *

- * All method calls will do a freshness check to ensure that the element reference is still valid. - * This essentially determines whether or not the element is still attached to the DOM. If this test - * fails, then an {@link org.openqa.selenium.StaleElementReferenceException} is thrown, and all - * future calls to this instance will fail. - */ -public interface WebElement extends SearchContext, TakesScreenshot { - /** - * Click this element. If this causes a new page to load, you - * should discard all references to this element and any further - * operations performed on this element will throw a - * StaleElementReferenceException. - *

- * Note that if click() is done by sending a native event (which is - * the default on most browsers/platforms) then the method will - * _not_ wait for the next page to load and the caller should verify - * that themselves. - *

- * There are some preconditions for an element to be clicked. The - * element must be visible and it must have a height and width - * greater then 0. - *

- * See W3C WebDriver specification - * for more details. - * - * @throws StaleElementReferenceException If the element no - * longer exists as initially defined - */ - void click(); - - /** - * If this current element is a form, or an element within a form, then this will be submitted to - * the remote server. If this causes the current page to change, then this method will block until - * the new page is loaded. - * - * @throws NoSuchElementException If the given element is not within a form - */ - void submit(); - - /** - * Use this method to simulate typing into an element, which may set its value. - *

- * See W3C WebDriver specification - * for more details. - * - * @param keysToSend character sequence to send to the element - * - * @throws IllegalArgumentException if keysToSend is null - */ - void sendKeys(CharSequence... keysToSend); - - /** - * If this element is a form entry element, this will reset its value. - *

- * See W3C WebDriver specification - * and HTML specification - * for more details. - */ - void clear(); - - /** - * Get the tag name of this element. Not the value of the name attribute: will return - * "input" for the element <input name="foo" />. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The tag name of this element. - */ - String getTagName(); - - /** - * Get the value of the given property of the element. Will return the current value, even if - * this has been modified after the page has been loaded. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the property. - * @return The property's current value or null if the value is not set. - */ - default String getDomProperty(String name) { - throw new UnsupportedOperationException("getDomProperty"); - } - - /** - * Get the value of the given attribute of the element. - *

- * This method, unlike {@link #getAttribute(String)}, returns the value of the attribute with the - * given name but not the property with the same name. - *

- * The following are deemed to be "boolean" attributes, and will return either "true" or null: - *

- * async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked, - * defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate, - * iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade, - * novalidate, nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, - * seeking, selected, truespeed, willvalidate - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the attribute. - * @return The attribute's value or null if the value is not set. - */ - default String getDomAttribute(String name) { - throw new UnsupportedOperationException("getDomAttribute"); - } - - /** - * Get the value of the given attribute of the element. Will return the current value, even if - * this has been modified after the page has been loaded. - *

- * More exactly, this method will return the value of the property with the given name, if it - * exists. If it does not, then the value of the attribute with the given name is returned. If - * neither exists, null is returned. - *

- * The "style" attribute is converted as best can be to a text representation with a trailing - * semi-colon. - *

- * The following are deemed to be "boolean" attributes, and will return either "true" or null: - *

- * async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked, - * defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate, - * iscontenteditable, ismap, itemscope, loop, multiple, muted, nohref, noresize, noshade, - * novalidate, nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, - * seeking, selected, truespeed, willvalidate - *

- * Finally, the following commonly mis-capitalized attribute/property names are evaluated as - * expected: - *

    - *
  • If the given name is "class", the "className" property is returned. - *
  • If the given name is "readonly", the "readOnly" property is returned. - *
- * Note: The reason for this behavior is that users frequently confuse attributes and - * properties. If you need to do something more precise, use {@link #getDomAttribute(String)} - * or {@link #getDomProperty(String)} to obtain the result you desire. - *

- * See W3C WebDriver specification - * for more details. - * - * @param name The name of the attribute. - * @return The attribute/property's current value or null if the value is not set. - */ - String getAttribute(String name); - - /** - * Gets result of computing the WAI-ARIA role of element. - *

- * See W3C WebDriver specification - * for more details. - * - * @return the WAI-ARIA role of the element. - */ - default String getAriaRole() { - throw new UnsupportedOperationException("getAriaRole"); - } - - /** - * Gets result of a Accessible Name and Description Computation for the Accessible Name of the element. - *

- * See W3C WebDriver specification - * for more details. - * - * @return the accessible name of the element. - */ - default String getAccessibleName() { - throw new UnsupportedOperationException("getAccessibleName"); - } - - /** - * Determine whether or not this element is selected or not. This operation only applies to input - * elements such as checkboxes, options in a select and radio buttons. - * For more information on which elements this method supports, - * refer to the specification. - *

- * See W3C WebDriver specification - * for more details. - * - * @return True if the element is currently selected or checked, false otherwise. - */ - boolean isSelected(); - - /** - * Is the element currently enabled or not? This will generally return true for everything but - * disabled input elements. - *

- * See W3C WebDriver specification - * for more details. - * - * @return True if the element is enabled, false otherwise. - */ - boolean isEnabled(); - - /** - * Get the visible (i.e. not hidden by CSS) text of this element, including sub-elements. - *

- * See W3C WebDriver specification - * for more details. - * - * @return The visible text of this element. - */ - String getText(); - - /** - * Find all elements within the current context using the given mechanism. When using xpath be - * aware that webdriver follows standard conventions: a search prefixed with "//" will search the - * entire document, not just the children of this current node. Use ".//" to limit your search to - * the children of this WebElement. - * This method is affected by the 'implicit wait' times in force at the time of execution. When - * implicitly waiting, this method will return as soon as there are more than 0 items in the - * found collection, or will return an empty list if the timeout is reached. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism to use - * @return A list of all {@link WebElement}s, or an empty list if nothing matches. - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - List findElements(By by); - - /** - * Find the first {@link WebElement} using the given method. See the note in - * {@link #findElements(By)} about finding via XPath. - * This method is affected by the 'implicit wait' times in force at the time of execution. - * The findElement(..) invocation will return a matching row, or try again repeatedly until - * the configured timeout is reached. - *

- * findElement should not be used to look for non-present elements, use {@link #findElements(By)} - * and assert zero length response instead. - *

- * See W3C WebDriver specification - * for more details. - * - * @param by The locating mechanism - * @return The first matching element on the current context. - * @throws NoSuchElementException If no matching elements are found - * @see org.openqa.selenium.By - * @see org.openqa.selenium.WebDriver.Timeouts - */ - @Override - T findElement(By by); - - /** - * @return A representation of an element's shadow root for accessing the shadow DOM of a web component. - * @throws NoSuchShadowRootException If no shadow root is found - */ - default SearchContext getShadowRoot() { - throw new UnsupportedOperationException("getShadowRoot"); - } - - /** - * Is this element displayed or not? This method avoids the problem of having to parse an - * element's "style" attribute. - * - * @return Whether or not the element is displayed - */ - boolean isDisplayed(); - - /** - * Where on the page is the top left-hand corner of the rendered element? - *

- * See W3C WebDriver specification - * for more details. - * - * @return A point, containing the location of the top left-hand corner of the element - */ - Point getLocation(); - - /** - * What is the width and height of the rendered element? - *

- * See W3C WebDriver specification - * for more details. - * - * @return The size of the element on the page. - */ - Dimension getSize(); - - /** - * @return The location and size of the rendered element - *

- * See W3C WebDriver specification - * for more details. - */ - Rectangle getRect(); - - /** - * Get the value of a given CSS property. - * Color values could be returned as rgba or rgb strings. - * This depends on whether the browser omits the implicit opacity value or not. - * - * For example if the "background-color" property is set as "green" in the - * HTML source, the returned value could be "rgba(0, 255, 0, 1)" if implicit opacity value is - * preserved or "rgb(0, 255, 0)" if it is omitted. - * - * Note that shorthand CSS properties (e.g. background, font, border, border-top, margin, - * margin-top, padding, padding-top, list-style, outline, pause, cue) are not returned, - * in accordance with the - * DOM CSS2 specification - * - you should directly access the longhand properties (e.g. background-color) to access the - * desired values. - *

- * See W3C WebDriver specification - * for more details. - * - * @param propertyName the css property name of the element - * @return The current, computed value of the property. - */ - String getCssValue(String propertyName); -} diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index c0b55e5f0..f2ed2792e 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -1,7 +1,11 @@ package io.appium.java_client; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.Point; import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebElement; +import javax.annotation.Nullable; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; @@ -64,4 +68,16 @@ public static void waitUntilTrue(Supplier func, Duration timeout, Durat } throw new TimeoutException(String.format("Condition unmet after %sms timeout", timeout.toMillis())); } + + public static Point getCenter(WebElement webElement) { + return getCenter(webElement, null); + } + + public static Point getCenter(WebElement webElement, @Nullable Point location) { + Dimension dim = webElement.getSize(); + if (location == null) { + location = webElement.getLocation(); + } + return new Point(location.x + dim.width / 2, location.y + dim.height / 2); + } } diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index e7ee4b055..0626c4f9d 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -1,17 +1,18 @@ package io.appium.java_client.android; +import static io.appium.java_client.TestUtils.getCenter; import static io.appium.java_client.touch.WaitOptions.waitOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; import static org.junit.Assert.assertNotEquals; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.Point; +import org.openqa.selenium.WebElement; import java.util.List; @@ -20,10 +21,10 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { private final ActionSupplier horizontalSwipe = () -> { driver.findElement(By.id("io.appium.android.apis:id/gallery")); - AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); + WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); + List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); Point location = gallery.getLocation(); - Point center = gallery.getCenter(); + Point center = getCenter(gallery, location); ElementOption pressOption = element(images.get(2),-10,center.y - location.y); ElementOption moveOption = element(gallery, 10,center.y - location.y); @@ -47,8 +48,8 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { @Test public void horizontalSwipingWithSupplier() { Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); driver.startActivity(activity); - AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); + WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); + List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); int originalImageCount = images.size(); horizontalSwipe.get().perform(); diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index 1f3c0ae00..c94669138 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -38,8 +38,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.Map; - public class AndroidDriverTest extends BaseAndroidTest { @@ -253,18 +251,6 @@ public void endTestCoverage() { driver.endTestCoverage("android.intent.action.MAIN", ""); } - @Test - public void getDeviceUDIDTest() { - String deviceSerial = driver.getSessionDetail("deviceUDID").toString(); - assertNotNull(deviceSerial); - } - - @Test - public void getSessionMapData() { - Map map = (Map) driver.getSessionDetail("desired"); - assertNotEquals(map.size(), 0); - } - @Test public void deviceDetailsAndKeyboardTest() { assertFalse(driver.isKeyboardShown()); @@ -314,10 +300,4 @@ public void getPerformanceDataTest() { public void getCurrentPackageTest() { assertEquals(APP_ID, driver.getCurrentPackage()); } - - @Test public void validateAllSessions() { - List> jsonMap = driver.getAllSessionDetails(); - assertNotNull(jsonMap); - } - } diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java index 3d93afaac..9effaadbd 100644 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidElementTest.java @@ -21,10 +21,11 @@ import static org.junit.Assert.assertNotNull; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; public class AndroidElementTest extends BaseAndroidTest { @@ -58,19 +59,19 @@ public class AndroidElementTest extends BaseAndroidTest { Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); driver.startActivity(activity); - AndroidElement editElement = driver + WebElement editElement = driver .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); editElement.sendKeys(originalValue); assertEquals(originalValue, editElement.getText()); String replacedValue = "replaced value"; - editElement.replaceValue(replacedValue); + driver.replaceElementValue((RemoteWebElement) editElement, replacedValue); assertEquals(replacedValue, editElement.getText()); } @Test public void scrollingToSubElement() { driver.findElement(AppiumBy.accessibilityId("Views")).click(); - AndroidElement list = driver.findElement(By.id("android:id/list")); - MobileElement radioGroup = list + WebElement list = driver.findElement(By.id("android:id/list")); + WebElement radioGroup = list .findElement(AppiumBy .androidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" + "new UiSelector().text(\"Radio Group\"));")); @@ -82,9 +83,9 @@ public class AndroidElementTest extends BaseAndroidTest { Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); driver.startActivity(activity); - AndroidElement editElement = driver + WebElement editElement = driver .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); - editElement.setValue(value); + driver.setElementValue((RemoteWebElement) editElement, value); assertEquals(value, editElement.getText()); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index 17be3a86f..e96ac64e7 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -21,10 +21,10 @@ import static org.junit.Assert.assertNotNull; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; public class AndroidSearchingTest extends BaseAndroidTest { @@ -59,7 +59,7 @@ public void setup() { @Test public void findScrollable() { driver.findElement(AppiumBy.accessibilityId("Views")).click(); - MobileElement radioGroup = driver + WebElement radioGroup = driver .findElement(AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector()" + ".resourceId(\"android:id/list\")).scrollIntoView(" + "new UiSelector().text(\"Radio Group\"));")); diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index dfff86414..e03485bbf 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import static io.appium.java_client.TestUtils.getCenter; import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.TapOptions.tapOptions; import static io.appium.java_client.touch.WaitOptions.waitOptions; @@ -10,7 +11,6 @@ import static org.junit.Assert.assertNotEquals; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; @@ -68,14 +68,14 @@ public void setUp() { @Test public void dragNDropByCoordinatesTest() { Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); driver.startActivity(activity); - AndroidElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - AndroidElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); + WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); + WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); assertEquals("Drag text not empty", "", dragText.getText()); - Point center1 = dragDot1.getCenter(); - Point center2 = dragDot3.getCenter(); + Point center1 = getCenter(dragDot1); + Point center2 = getCenter(dragDot3); TouchAction dragNDrop = new TouchAction(driver) .longPress(point(center1.x, center1.y)) @@ -88,14 +88,14 @@ public void setUp() { @Test public void dragNDropByCoordinatesAndDurationTest() { Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); driver.startActivity(activity); - AndroidElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - AndroidElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); + WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); + WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); assertEquals("Drag text not empty", "", dragText.getText()); - Point center1 = dragDot1.getCenter(); - Point center2 = dragDot3.getCenter(); + Point center1 = getCenter(dragDot1); + Point center2 = getCenter(dragDot3); TouchAction dragNDrop = new TouchAction(driver) .longPress(longPressOptions() @@ -133,7 +133,7 @@ public void setUp() { @Test public void tapActionTestByElement() throws Exception { Activity activity = new Activity("io.appium.android.apis", ".view.ChronometerDemo"); driver.startActivity(activity); - AndroidElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); + WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); TouchAction startStop = new TouchAction(driver) .tap(tapOptions().withElement(element(driver.findElement(By.id("io.appium.android.apis:id/start"))))) @@ -151,9 +151,9 @@ public void setUp() { @Test public void tapActionTestByCoordinates() throws Exception { Activity activity = new Activity("io.appium.android.apis", ".view.ChronometerDemo"); driver.startActivity(activity); - AndroidElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); + WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); - Point center1 = driver.findElement(By.id("io.appium.android.apis:id/start")).getCenter(); + Point center1 = getCenter(driver.findElement(By.id("io.appium.android.apis:id/start"))); TouchAction startStop = new TouchAction(driver) .tap(point(center1.x, center1.y)) @@ -170,11 +170,11 @@ public void setUp() { Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); driver.startActivity(activity); - AndroidElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); + WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); + List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); int originalImageCount = images.size(); Point location = gallery.getLocation(); - Point center = gallery.getCenter(); + Point center = getCenter(gallery); TouchAction swipe = new TouchAction(driver) .press(element(images.get(2),-10, center.y - location.y)) diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 5108c98ac..065794566 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -28,7 +28,7 @@ public class BaseAndroidTest { public static final String APP_ID = "io.appium.android.apis"; private static AppiumDriverLocalService service; - protected static AndroidDriver driver; + protected static AndroidDriver driver; /** * initialization. @@ -45,7 +45,7 @@ public class BaseAndroidTest { .setDeviceName("Android Emulator") .setApp(apiDemosApk().toAbsolutePath().toString()) .setEventTimings(); - driver = new AndroidDriver<>(service.getUrl(), options); + driver = new AndroidDriver(service.getUrl(), options); } /** diff --git a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java index cbea1e064..6d9cd7671 100644 --- a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java +++ b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java @@ -29,7 +29,7 @@ public class BaseEspressoTest { private static AppiumDriverLocalService service; - protected static AndroidDriver driver; + protected static AndroidDriver driver; /** * initialization. @@ -48,7 +48,7 @@ public class BaseEspressoTest { capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); capabilities.setCapability("eventTimings", true); - driver = new AndroidDriver<>(service.getUrl(), capabilities); + driver = new AndroidDriver(service.getUrl(), capabilities); } /** 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 3637d0360..634a9a516 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -58,7 +58,7 @@ public void setUp() { 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); + 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); } diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java index 5a8a2a9e8..9b296adf3 100644 --- a/src/test/java/io/appium/java_client/android/FingerPrintTest.java +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -17,7 +17,6 @@ package io.appium.java_client.android; import static io.appium.java_client.AppiumBy.androidUIAutomator; -import static java.util.concurrent.TimeUnit.SECONDS; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -29,19 +28,22 @@ import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; +import java.time.Duration; + public class FingerPrintTest { private static AppiumDriverLocalService service; - private static AndroidDriver driver; + private static AndroidDriver driver; private static void initDriver() { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability("appPackage", "com.android.settings"); capabilities.setCapability("appActivity", "Settings"); - driver = new AndroidDriver<>(service.getUrl(), capabilities); - driver.manage().timeouts().implicitlyWait(15, SECONDS); + driver = new AndroidDriver(service.getUrl(), capabilities); + driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(15)); } /** @@ -65,7 +67,7 @@ private static void initDriver() { } } - private AndroidElement findElementByText(String text) { + private WebElement findElementByText(String text) { return driver.findElements(By.id("android:id/title")).stream().filter(androidElement -> text.equals(androidElement.getText())).findFirst() .orElseThrow(() -> diff --git a/src/test/java/io/appium/java_client/android/IntentTest.java b/src/test/java/io/appium/java_client/android/IntentTest.java index ed82dee0c..441af2a4e 100644 --- a/src/test/java/io/appium/java_client/android/IntentTest.java +++ b/src/test/java/io/appium/java_client/android/IntentTest.java @@ -16,7 +16,7 @@ public class IntentTest { private static AppiumDriverLocalService service; - protected static AndroidDriver driver; + protected static AndroidDriver driver; /** * initialization. @@ -32,7 +32,7 @@ public class IntentTest { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.APP, intentExampleApk().toAbsolutePath().toString()); - driver = new AndroidDriver<>(service.getUrl(), capabilities); + driver = new AndroidDriver(service.getUrl(), capabilities); } /** diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index 7806ecc14..db055c305 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -5,6 +5,7 @@ import org.junit.Test; +import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; import java.util.List; @@ -16,7 +17,7 @@ public void openNotification() { driver.openNotifications(); WebDriverWait wait = new WebDriverWait(driver, 20); assertNotEquals(0, wait.until(input -> { - List result = input + List result = input .findElements(id("com.android.systemui:id/settings_button")); return result.isEmpty() ? null : result; diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java index 568e9cf53..85b91ab30 100644 --- a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java +++ b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java @@ -4,15 +4,16 @@ import static org.junit.Assert.assertNotNull; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; import org.junit.After; import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.DeviceRotation; +import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; public class UIAutomator2Test extends BaseAndroidTest { @@ -23,7 +24,7 @@ public void afterMethod() { @Test public void testLandscapeRightRotation() { - new WebDriverWait(driver, 20).until(ExpectedConditions + new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions .elementToBeClickable(driver.findElement(By.id("android:id/content")) .findElement(AppiumBy.accessibilityId("Graphics")))); DeviceRotation landscapeRightRotation = new DeviceRotation(0, 0, 90); @@ -33,7 +34,7 @@ public void testLandscapeRightRotation() { @Test public void testLandscapeLeftRotation() { - new WebDriverWait(driver, 20).until(ExpectedConditions + new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions .elementToBeClickable(driver.findElement(By.id("android:id/content")) .findElement(AppiumBy.accessibilityId("Graphics")))); DeviceRotation landscapeLeftRotation = new DeviceRotation(0, 0, 270); @@ -43,7 +44,7 @@ public void testLandscapeLeftRotation() { @Test public void testPortraitUpsideDown() { - new WebDriverWait(driver, 20).until(ExpectedConditions + new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions .elementToBeClickable(driver.findElement(By.id("android:id/content")) .findElement(AppiumBy.accessibilityId("Graphics")))); DeviceRotation landscapeRightRotation = new DeviceRotation(0, 0, 180); @@ -56,13 +57,13 @@ public void testPortraitUpsideDown() { */ @Ignore public void testToastMSGIsDisplayed() { - final WebDriverWait wait = new WebDriverWait(driver, 30); + final WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); Activity activity = new Activity("io.appium.android.apis", ".view.PopupMenu1"); driver.startActivity(activity); wait.until(ExpectedConditions.presenceOfElementLocated(AppiumBy .accessibilityId("Make a Popup!"))); - MobileElement popUpElement = driver.findElement(AppiumBy.accessibilityId("Make a Popup!")); + WebElement popUpElement = driver.findElement(AppiumBy.accessibilityId("Make a Popup!")); wait.until(ExpectedConditions.elementToBeClickable(popUpElement)).click(); wait.until(ExpectedConditions.visibilityOfElementLocated( By.xpath(".//*[@text='Search']"))).click(); diff --git a/src/test/java/io/appium/java_client/appium/AndroidTest.java b/src/test/java/io/appium/java_client/appium/AndroidTest.java deleted file mode 100644 index 4347e3f24..000000000 --- a/src/test/java/io/appium/java_client/appium/AndroidTest.java +++ /dev/null @@ -1,146 +0,0 @@ -package io.appium.java_client.appium; - -import static io.appium.java_client.TestResources.apiDemosApk; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.Activity; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.android.StartsActivity; -import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.remote.Response; - -import java.util.Map; - -public class AndroidTest { - - private static AppiumDriverLocalService service; - private static AppiumDriver driver; - private StartsActivity startsActivity; - - /** - * initialization. - */ - @BeforeClass - public static void beforeClass() { - service = AppiumDriverLocalService.buildDefaultService(); - service.start(); - - if (service == null || !service.isRunning()) { - throw new AppiumServerHasNotBeenStartedLocallyException( - "An appium server node is not started!"); - } - - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - driver = new AppiumDriver<>(service.getUrl(), capabilities); - } - - /** - * finishing. - */ - @AfterClass - public static void afterClass() { - if (driver != null) { - driver.quit(); - } - if (service != null) { - service.stop(); - } - } - - @Before - public void setUp() { - startsActivity = new StartsActivity() { - @Override - public Response execute(String driverCommand, Map parameters) { - return driver.execute(driverCommand, parameters); - } - - @Override - public Response execute(String driverCommand) { - return driver.execute(driverCommand); - } - }; - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - startsActivity.startActivity(activity); - } - - @Test - public void findByAccessibilityIdFromDriverTest() { - assertNotEquals(driver.findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); - } - - @Test public void findByAndroidUIAutomatorFromDriverTest() { - assertNotEquals(driver - .findElement(AppiumBy - .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); - assertNotEquals(driver - .findElements(AppiumBy - .androidUIAutomator("new UiSelector().clickable(true)")).size(), 0); - assertNotEquals(driver - .findElements(AppiumBy - .androidUIAutomator("new UiSelector().clickable(true)")).size(), 1); - } - - @Test public void findByAccessibilityIdFromElementTest() { - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); - assertEquals(driver.findElement(By.id("android:id/content")) - .findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); - } - - @Test public void findByAndroidUIAutomatorFromElementTest() { - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElement(AppiumBy - .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(AppiumBy - .androidUIAutomator("new UiSelector().clickable(true)")).size(), 0); - assertNotEquals(driver.findElement(By.id("android:id/content")) - .findElements(AppiumBy - .androidUIAutomator("new UiSelector().clickable(true)")).size(), 1); - } - - @Test public void replaceValueTest() { - String originalValue = "original value"; - - Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); - startsActivity.startActivity(activity); - AndroidElement editElement = driver - .findElement(AppiumBy - .androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); - editElement.sendKeys(originalValue); - assertEquals(originalValue, editElement.getText()); - String replacedValue = "replaced value"; - editElement.replaceValue(replacedValue); - assertEquals(replacedValue, editElement.getText()); - } - - @Test public void scrollingToSubElement() { - driver.findElement(AppiumBy.accessibilityId("Views")).click(); - AndroidElement list = driver.findElement(By.id("android:id/list")); - MobileElement radioGroup = list - .findElement(AppiumBy - .androidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(" - + "new UiSelector().text(\"Radio Group\"));")); - assertNotNull(radioGroup.getLocation()); - } - -} diff --git a/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java b/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java deleted file mode 100644 index ead5bff7d..000000000 --- a/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 static java.time.Duration.ofSeconds; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsEqual.equalTo; - -import io.appium.java_client.AppiumFluentWait; - -import org.junit.Assert; -import org.junit.Test; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.support.ui.Wait; - -import java.time.Clock; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; - -public class AppiumFluentWaitTest { - - private static class FakeElement { - public boolean isDisplayed() { - return false; - } - } - - @Test(expected = TimeoutException.class) - public void testDefaultStrategy() { - final FakeElement el = new FakeElement(); - final Wait wait = new AppiumFluentWait<>(el, Clock.systemDefaultZone(), duration -> { - assertThat(duration.getSeconds(), is(equalTo(1L))); - Thread.sleep(duration.toMillis()); - }).withPollingStrategy(AppiumFluentWait.IterationInfo::getInterval) - .withTimeout(ofSeconds(3)) - .pollingEvery(ofSeconds(1)); - wait.until(FakeElement::isDisplayed); - Assert.fail("TimeoutException is expected"); - } - - @Test - public void testCustomStrategyOverridesDefaultInterval() { - final FakeElement el = new FakeElement(); - final AtomicInteger callsCounter = new AtomicInteger(0); - final Wait wait = new AppiumFluentWait<>(el, Clock.systemDefaultZone(), duration -> { - callsCounter.incrementAndGet(); - assertThat(duration.getSeconds(), is(equalTo(2L))); - Thread.sleep(duration.toMillis()); - }).withPollingStrategy(info -> ofSeconds(2)) - .withTimeout(ofSeconds(3)) - .pollingEvery(ofSeconds(1)); - try { - wait.until(FakeElement::isDisplayed); - Assert.fail("TimeoutException is expected"); - } catch (TimeoutException e) { - // this is expected - assertThat(callsCounter.get(), is(equalTo(2))); - } - } - - @Test - public void testIntervalCalculationForCustomStrategy() { - final FakeElement el = new FakeElement(); - final AtomicInteger callsCounter = new AtomicInteger(0); - // Linear dependency - final Function pollingStrategy = x -> x * 2; - final Wait wait = new AppiumFluentWait<>(el, Clock.systemDefaultZone(), duration -> { - int callNumber = callsCounter.incrementAndGet(); - assertThat(duration.getSeconds(), is(equalTo(pollingStrategy.apply((long) callNumber)))); - Thread.sleep(duration.toMillis()); - }).withPollingStrategy(info -> ofSeconds(pollingStrategy.apply(info.getNumber()))) - .withTimeout(ofSeconds(4)) - .pollingEvery(ofSeconds(1)); - try { - wait.until(FakeElement::isDisplayed); - Assert.fail("TimeoutException is expected"); - } catch (TimeoutException e) { - // this is expected - assertThat(callsCounter.get(), is(equalTo(2))); - } - } -} diff --git a/src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java b/src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java deleted file mode 100644 index 83271f229..000000000 --- a/src/test/java/io/appium/java_client/appium/element/generation/BaseElementGenerationTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.appium.java_client.appium.element.generation; - -import static org.junit.Assert.assertEquals; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.After; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; - -import java.util.function.BiPredicate; -import java.util.function.Supplier; - -public class BaseElementGenerationTest { - protected AppiumDriver driver; - protected AppiumDriverLocalService service; - - protected final BiPredicate> commonPredicate = (by, aClass) -> { - WebElement element = driver.findElement(by); - assertEquals(element.getClass(), aClass); - return true; - }; - - @After - public void tearDown() { - try { - if (driver != null) { - driver.quit(); - } - if (service != null) { - service.stop(); - } - } finally { - driver = null; - service = null; - } - } - -} diff --git a/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java b/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java deleted file mode 100644 index 2c8de9eb1..000000000 --- a/src/test/java/io/appium/java_client/appium/element/generation/android/AndroidElementGeneratingTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.appium.java_client.appium.element.generation.android; - -import static io.appium.java_client.AppiumBy.androidUIAutomator; -import static io.appium.java_client.TestResources.apiDemosApk; -import static org.junit.Assert.assertTrue; -import static org.openqa.selenium.By.name; -import static org.openqa.selenium.By.tagName; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.appium.element.generation.BaseElementGenerationTest; -import io.appium.java_client.remote.AndroidMobileCapabilityType; -import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; - -import java.util.function.BiPredicate; -import java.util.function.Supplier; - -public class AndroidElementGeneratingTest extends BaseElementGenerationTest { - - private final Supplier commonCapabilitiesSupplier = () -> { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - serverCapabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - return serverCapabilities; - }; - - @Test - public void whenAndroidNativeAppIsLaunched() { - assertTrue(check(() -> { - DesiredCapabilities clientCapabilities = commonCapabilitiesSupplier.get(); - clientCapabilities.setCapability(MobileCapabilityType.FULL_RESET, true); - clientCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60); - return clientCapabilities; - }, commonPredicate, androidUIAutomator("new UiSelector().clickable(true)") - )); - } - - @Test - public void whenAndroidHybridAppIsLaunched() { - assertTrue(check(() -> { - DesiredCapabilities clientCapabilities = commonCapabilitiesSupplier.get(); - clientCapabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "io.appium.android.apis"); - clientCapabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".view.WebView1"); - return clientCapabilities; - }, (by, aClass) -> { - driver.context("WEBVIEW_io.appium.android.apis"); - return commonPredicate.test(by, aClass); - }, tagName("a"))); - } - - @Test - public void whenAndroidBrowserIsLaunched() { - assertTrue(check(() -> { - DesiredCapabilities clientCapabilities = commonCapabilitiesSupplier.get(); - clientCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); - clientCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.BROWSER); - clientCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - return clientCapabilities; - }, (by, aClass) -> { - driver.get("https://www.google.com"); - return commonPredicate.test(by, aClass); - }, name("q"))); - } - - private boolean check(Supplier capabilitiesSupplier, - BiPredicate> filter, - By by) { - service = AppiumDriverLocalService.buildDefaultService(); - driver = new AppiumDriver<>(service, capabilitiesSupplier.get()); - return filter.test(by, AndroidElement.class); - } -} diff --git a/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java b/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java deleted file mode 100644 index 4f227464d..000000000 --- a/src/test/java/io/appium/java_client/appium/element/generation/ios/IOSElementGenerationTest.java +++ /dev/null @@ -1,166 +0,0 @@ -package io.appium.java_client.appium.element.generation.ios; - -import static io.appium.java_client.TestResources.testAppZip; -import static io.appium.java_client.TestResources.vodQaAppZip; -import static org.junit.Assert.assertTrue; -import static org.openqa.selenium.By.id; -import static org.openqa.selenium.By.name; -import static org.openqa.selenium.By.partialLinkText; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.AppiumBy; -import io.appium.java_client.appium.element.generation.BaseElementGenerationTest; -import io.appium.java_client.ios.BaseIOSTest; -import io.appium.java_client.ios.IOSElement; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.IOSMobileCapabilityType; -import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.remote.MobileCapabilityType; -import io.appium.java_client.remote.MobilePlatform; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.Ignore; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; - -import java.io.File; -import java.time.Duration; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.function.Supplier; - -public class IOSElementGenerationTest extends BaseElementGenerationTest { - - private static final File testApp = testAppZip().toFile(); - - private static final File webViewApp = vodQaAppZip().toFile(); - - private final Supplier commonAppCapabilitiesSupplier = () -> { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - serverCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - serverCapabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return serverCapabilities; - }; - - private final Function> appFileSupplierFunction = file -> { - final DesiredCapabilities clientCapabilities = new DesiredCapabilities(); - return () -> { - clientCapabilities.setCapability(MobileCapabilityType.APP, file.getAbsolutePath()); - return clientCapabilities; - }; - }; - - private final Supplier serverBrowserCapabilitiesSupplier = () -> { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.SAFARI); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - serverCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - serverCapabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); - return serverCapabilities; - }; - - private final Supplier clientBrowserCapabilitiesSupplier = () -> { - DesiredCapabilities clientCapabilities = new DesiredCapabilities(); - clientCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return clientCapabilities; - }; - - @Test - public void whenIOSNativeAppIsLaunched() { - assertTrue(check(() -> { - Capabilities caps = commonAppCapabilitiesSupplier.get(); - return caps.merge(appFileSupplierFunction.apply(testApp).get()); - }, commonPredicate, - AppiumBy.accessibilityId("Answer") - )); - } - - @Ignore - @Test - public void whenIOSHybridAppIsLaunched() { - assertTrue(check(() -> { - Capabilities caps = commonAppCapabilitiesSupplier.get(); - return caps.merge(appFileSupplierFunction.apply(webViewApp).get()); - }, (by, aClass) -> { - new WebDriverWait(driver, Duration.ofSeconds(30)) - .until(ExpectedConditions.presenceOfElementLocated(id("login"))) - .click(); - driver.findElement(AppiumBy.accessibilityId("webView")).click(); - new WebDriverWait(driver, Duration.ofSeconds(30)) - .until(ExpectedConditions - .presenceOfElementLocated(AppiumBy.accessibilityId("Webview"))); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - driver.getContextHandles().forEach((handle) -> { - if (handle.contains("WEBVIEW")) { - driver.context(handle); - } - }); - return commonPredicate.test(by, aClass); - }, partialLinkText("login"))); - } - - @Test - public void whenIOSBrowserIsLaunched() { - assertTrue(check(() -> { - Capabilities caps = serverBrowserCapabilitiesSupplier.get(); - return caps.merge(clientBrowserCapabilitiesSupplier.get()); - }, (by, aClass) -> { - driver.get("https://www.google.com"); - return commonPredicate.test(by, aClass); - }, name("q"))); - } - - @Test - public void whenIOSNativeAppIsLaunched2() { - assertTrue(check(() -> { - DesiredCapabilities serverCapabilities = commonAppCapabilitiesSupplier.get(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return serverCapabilities.merge(appFileSupplierFunction.apply(testApp).get()); - }, commonPredicate, id("IntegerA"))); - } - - @Test - public void whenIOSBrowserIsLaunched2() { - assertTrue(check(() -> { - DesiredCapabilities serverCapabilities = serverBrowserCapabilitiesSupplier.get(); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); - return serverCapabilities.merge(clientBrowserCapabilitiesSupplier.get()); - }, (by, aClass) -> { - driver.get("https://www.google.com"); - return commonPredicate.test(by, aClass); - }, name("q"))); - } - - private boolean check(Supplier capabilitiesSupplier, - BiPredicate> filter, - By by) { - service = AppiumDriverLocalService.buildDefaultService(); - Capabilities caps = capabilitiesSupplier.get(); - DesiredCapabilities fixedCaps = new DesiredCapabilities(caps); - fixedCaps.setCapability("commandTimeouts", "120000"); - try { - driver = new AppiumDriver<>(service, fixedCaps); - } catch (SessionNotCreatedException e) { - fixedCaps.setCapability("useNewWDA", true); - driver = new AppiumDriver<>(service, fixedCaps); - } - return filter.test(by, IOSElement.class); - } -} diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java index ae2e0df64..5316f56e4 100644 --- a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -97,7 +97,7 @@ public StubWebElement findElement(String by, String using) throws WebDriverExcep return new StubWebElement(); } - public List findElements(By by) { + public List findElements(By by) { return createStubList(); } diff --git a/src/test/java/io/appium/java_client/ios/AppIOSTest.java b/src/test/java/io/appium/java_client/ios/AppIOSTest.java index 28a911ca2..26551d91b 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/AppIOSTest.java @@ -34,10 +34,10 @@ public static void beforeClass() throws Exception { capabilities.setCapability("commandTimeouts", "240000"); capabilities.setCapability(MobileCapabilityType.APP, testAppZip().toAbsolutePath().toString()); try { - driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } catch (SessionNotCreatedException e) { capabilities.setCapability("useNewWDA", true); - driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } } } \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index 68097c7cc..c887ab6f8 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -29,7 +29,7 @@ public class BaseIOSTest { protected static AppiumDriverLocalService service; - protected static IOSDriver driver; + protected static IOSDriver driver; protected static final int PORT = 4723; public static final String DEVICE_NAME = System.getenv("IOS_DEVICE_NAME") != null ? System.getenv("IOS_DEVICE_NAME") : "iPhone 12"; diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 445e37033..999719551 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -51,9 +51,9 @@ public static void beforeClass() throws IOException { capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); capabilities.setCapability("commandTimeouts", "240000"); capabilities.setCapability(MobileCapabilityType.APP, vodQaAppZip().toAbsolutePath().toString()); - Supplier> createDriver = () -> { + Supplier createDriver = () -> { try { - return new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + return new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } catch (MalformedURLException e) { throw new RuntimeException(e); } diff --git a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java index cc4a7d05d..122d30257 100644 --- a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java @@ -44,6 +44,6 @@ public class BaseSafariTest extends BaseIOSTest { capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, WDA_LAUNCH_TIMEOUT.toMillis()); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, DEVICE_NAME); - driver = new IOSDriver<>(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index 345a7186b..f06e5b882 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -26,7 +26,6 @@ import static org.junit.Assert.fail; import com.google.common.collect.ImmutableMap; -import io.appium.java_client.MobileElement; import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.remote.HideKeyboardStrategy; import org.junit.Before; @@ -34,7 +33,9 @@ import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.WebElement; import org.openqa.selenium.html5.Location; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -66,11 +67,13 @@ public void addCustomCommandWithSessionIdTest() { @Test public void addCustomCommandWithElementIdTest() { - IOSElement intA = driver.findElement(By.id("IntegerA")); + WebElement intA = driver.findElement(By.id("IntegerA")); intA.clear(); driver.addCommand(HttpMethod.POST, - String.format("/session/%s/appium/element/%s/value", driver.getSessionId(), intA.getId()), "setNewValue"); - final Response setNewValue = driver.execute("setNewValue", ImmutableMap.of("id", intA.getId(), "value", "8")); + String.format("/session/%s/appium/element/%s/value", driver.getSessionId(), + ((RemoteWebElement) intA).getId()), "setNewValue"); + final Response setNewValue = driver.execute("setNewValue", + ImmutableMap.of("id", ((RemoteWebElement) intA).getId(), "value", "8")); assertNotNull(setNewValue.getSessionId()); } @@ -124,7 +127,7 @@ public void getDeviceTimeTest() { } @Test public void keyboardTest() { - MobileElement element = driver.findElement(By.id("IntegerA")); + WebElement element = driver.findElement(By.id("IntegerA")); element.click(); assertTrue(driver.isKeyboardShown()); } diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index 234b9346c..1004dc1a0 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -1,18 +1,22 @@ package io.appium.java_client.ios; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; import org.junit.runners.MethodSorters; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.ui.WebDriverWait; import io.appium.java_client.AppiumBy; +import java.time.Duration; + @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class IOSElementTest extends AppIOSTest { @@ -25,11 +29,11 @@ public void findByAccessibilityIdTest() { @Ignore @Test public void setValueTest() { - WebDriverWait wait = new WebDriverWait(driver, 20); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20)); - IOSElement slider = wait.until( + WebElement slider = wait.until( driver1 -> driver1.findElement(AppiumBy.className("XCUIElementTypeSlider"))); - slider.setValue("0%"); + driver.setElementValue((RemoteWebElement) slider, "0%"); assertEquals("0%", slider.getAttribute("value")); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java index 8ad29b526..dab6dde45 100644 --- a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java @@ -10,41 +10,43 @@ import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileElement; import io.appium.java_client.MultiTouchAction; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; + @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class IOSTouchTest extends AppIOSTest { @Test public void tapTest() { - IOSElement intA = driver.findElement(By.id("IntegerA")); - IOSElement intB = driver.findElement(By.id("IntegerB")); + WebElement intA = driver.findElement(By.id("IntegerA")); + WebElement intB = driver.findElement(By.id("IntegerB")); intA.clear(); intB.clear(); intA.sendKeys("2"); intB.sendKeys("4"); - MobileElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); + WebElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))).perform(); assertEquals(driver.findElement(By.xpath("//*[@name = \"Answer\"]")).getText(), "6"); } @Test public void touchWithPressureTest() { - IOSElement intA = driver.findElement(By.id("IntegerA")); - IOSElement intB = driver.findElement(By.id("IntegerB")); + WebElement intA = driver.findElement(By.id("IntegerA")); + WebElement intB = driver.findElement(By.id("IntegerB")); intA.clear(); intB.clear(); intA.sendKeys("2"); intB.sendKeys("4"); - MobileElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); + WebElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); new IOSTouchAction(driver) .press(iosPressOptions() .withElement(element(e)) @@ -56,26 +58,26 @@ public void touchWithPressureTest() { } @Test public void multiTouchTest() { - MobileElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); - MobileElement e2 = driver.findElement(AppiumBy.accessibilityId("show alert")); + WebElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); + WebElement e2 = driver.findElement(AppiumBy.accessibilityId("show alert")); IOSTouchAction tap1 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))); IOSTouchAction tap2 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e2))); new MultiTouchAction(driver).add(tap1).add(tap2).perform(); - WebDriverWait waiting = new WebDriverWait(driver, 10); + WebDriverWait waiting = new WebDriverWait(driver, Duration.ofSeconds(10)); assertNotNull(waiting.until(alertIsPresent())); driver.switchTo().alert().accept(); } @Test public void doubleTapTest() { - IOSElement firstField = driver.findElement(By.id("IntegerA")); + WebElement firstField = driver.findElement(By.id("IntegerA")); firstField.sendKeys("2"); IOSTouchAction iosTouchAction = new IOSTouchAction(driver); iosTouchAction.doubleTap(element(firstField)); - IOSElement editingMenu = driver.findElement(AppiumBy.className("XCUIElementTypeTextField")); + WebElement editingMenu = driver.findElement(AppiumBy.className("XCUIElementTypeTextField")); assertNotNull(editingMenu); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index 99121e990..56c423ab4 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -23,9 +23,6 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.AndroidElement; - import io.appium.java_client.android.BaseAndroidTest; import io.appium.java_client.pagefactory.AndroidBy; @@ -64,10 +61,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { private List androidUIAutomatorViews; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") - private List mobileElementViews; + private List mobileElementViews; @FindBy(className = "android.widget.TextView") - private List mobiletextVieWs; + private List mobiletextVieWs; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") private List remoteElementViews; @@ -94,10 +91,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { private WebElement androidUIAutomatorView; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") - private MobileElement mobileElementView; + private WebElement mobileElementView; @FindBy(className = "android.widget.TextView") - private MobileElement mobiletextVieW; + private WebElement mobiletextVieW; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") private RemoteWebElement remotetextVieW; @@ -114,12 +111,12 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")") @AndroidFindBy(id = "android:id/text1") - private AndroidElement androidElementView; + private WebElement androidElementView; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")") @AndroidFindBy(id = "android:id/text1") - private List androidElementViews; + private List androidElementViews; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/Fakecontent\")") @@ -154,7 +151,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @CacheLookup @FindBy(className = "android.widget.TextView") - private MobileElement cached; + private WebElement cached; @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")") @@ -173,21 +170,21 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), @AndroidBy(id = "android:id/fakeId")}, priority = 1) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") - private AndroidElement androidElementViewFoundByMixedSearching; + private WebElement androidElementViewFoundByMixedSearching; @AndroidFindBy(id = "android:id/text1", priority = 2) @AndroidFindAll(value = { @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), @AndroidBy(id = "android:id/fakeId")}, priority = 1) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") - private List androidElementsViewFoundByMixedSearching; + private List androidElementsViewFoundByMixedSearching; @AndroidFindBys({ @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), @AndroidBy(className = "android.widget.FrameLayout")}) @AndroidFindBys({@AndroidBy(id = "android:id/text1", priority = 1), @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) - private AndroidElement androidElementViewFoundByMixedSearching2; + private WebElement androidElementViewFoundByMixedSearching2; @AndroidFindBys({ @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), @@ -195,7 +192,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidFindBys({ @AndroidBy(id = "android:id/text1", priority = 1), @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) - private List androidElementsViewFoundByMixedSearching2; + private List androidElementsViewFoundByMixedSearching2; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(id = "android:id/fakeId1") @@ -207,7 +204,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) @AndroidFindBy(id = "android:id/fakeId3", priority = 3) @AndroidFindBy(id = "android:id/fakeId4", priority = 4) - private AndroidElement androidElementViewFoundByMixedSearching3; + private WebElement androidElementViewFoundByMixedSearching3; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(id = "android:id/fakeId1") @@ -219,7 +216,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) @AndroidFindBy(id = "android:id/fakeId3", priority = 3) @AndroidFindBy(id = "android:id/fakeId4", priority = 4) - private List androidElementsViewFoundByMixedSearching3; + private List androidElementsViewFoundByMixedSearching3; /** * The setting up. @@ -336,8 +333,8 @@ public class AndroidPageObjectTest extends BaseAndroidTest { } @Test public void checkThatClassObjectMethodsDoNotInvokeTheSearching() { - assertTrue(AndroidElement.class.isAssignableFrom(fakeElement.getClass())); - assertNotEquals(AndroidElement.class, fakeElement.getClass()); + assertTrue(WebElement.class.isAssignableFrom(fakeElement.getClass())); + assertNotEquals(WebElement.class, fakeElement.getClass()); assertEquals(driver, ((WrapsDriver) fakeElement).getWrappedDriver()); } @@ -347,7 +344,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { } @Test public void checkCached() { - assertEquals(cached.getId(), cached.getId()); + assertEquals(((RemoteWebElement) cached).getId(), ((RemoteWebElement) cached).getId()); } @Test(expected = NoSuchElementException.class) diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index 63ff333b5..81b3be1cf 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -48,7 +48,7 @@ public class DesktopBrowserCompatibilityTest { private List foundLinks; private List main; //this list is located by id="main" private WebDriver trap1; - private List> trap2; + private List trap2; /** * The starting. diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java deleted file mode 100644 index 16e83e2fe..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/GenericTest.java +++ /dev/null @@ -1,300 +0,0 @@ -package io.appium.java_client.pagefactory_tests; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import io.appium.java_client.pagefactory.AppiumFieldDecorator; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; - -import org.apache.commons.lang3.NotImplementedException; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.HasCapabilities; -import org.openqa.selenium.Platform; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.support.PageFactory; -import io.appium.java_client.MobileElement; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class GenericTest { - - /** - * The Generic types are null on an unbound page. - */ - private static void assertUnboundGenericsNull(T genericItem, - List genericItems) { - assertNull(genericItem); - assertNull(genericItems); - } - - /** - * The Generic types are not null on a page bound by a WebElement (or WebElement - * sub type). - */ - private static void assertBoundGenericsNotNull(T genericItem, - List genericItems) { - assertNotNull(genericItem); - assertNotNull(genericItems); - } - - /** - * The Element types are never null. - */ - private static void assertElementsNotNull(WebElement elementItem, - List elementItems) { - assertNotNull(elementItem); - assertNotNull(elementItems); - } - - /** - * The Object types are always null. - */ - private static void assertObjectsNull(Object objectItem, List objectItems) { - assertNull(objectItem); - assertNull(objectItems); - } - - /** - * A page with no generic types. The Object types are never initialized. - */ - static class TempNoGenericsPage { - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - /** - * A page with an unbound generic type. The generic and Object types are never - * initialized. - */ - static class TempUnboundPage { - public T genericItem; - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List genericItems; - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertUnboundGenericsNull(genericItem, genericItems); - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - /** - * A page with a WebElement bound generic type. The Object types are never - * initialized. - */ - static class TempWebBoundPage { - public T genericItem; - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List genericItems; - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertBoundGenericsNotNull(genericItem, genericItems); - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - /** - * A page with a MobileElement bound generic type. The Object types are never - * initialized. - */ - static class TempMobileBoundPage { - public T genericItem; - public WebElement webElementItem; - public MobileElement mobileElementItem; - public Object objectItem; - - public List genericItems; - public List webElementItems; - public List mobileElementItems; - public List objectItems; - - public void assertInit() { - assertBoundGenericsNotNull(genericItem, genericItems); - assertElementsNotNull(webElementItem, webElementItems); - assertElementsNotNull(mobileElementItem, mobileElementItems); - assertObjectsNull(objectItem, objectItems); - } - } - - static class MockWebDriver implements WebDriver, HasCapabilities { - - @Override - public void get(String url) { - System.out.print(url); - } - - @Override - public String getCurrentUrl() { - return null; - } - - @Override - public String getTitle() { - return null; - } - - @Override - public List findElements(By by) { - throw new NotImplementedException("MockWebDriver did not expect to findElements"); - } - - @Override - public T findElement(By by) { - throw new NotImplementedException("MockWebDriver did not expect to findElement"); - } - - @Override - public String getPageSource() { - return null; - } - - @Override - public void close() { - System.out.print("Closed"); - } - - @Override - public void quit() { - System.out.print("Died"); - } - - @Override - public Set getWindowHandles() { - return null; - } - - @Override - public String getWindowHandle() { - return null; - } - - @Override - public TargetLocator switchTo() { - return null; - } - - @Override - public Navigation navigate() { - return null; - } - - @Override - public Options manage() { - return null; - } - - @Override - public Capabilities getCapabilities() { - - final Map capabilities = new HashMap<>(); - - // These are needed to map the proxy element to a MobileElement. - capabilities.put(CapabilityType.PLATFORM_NAME, Platform.ANY.toString()); - capabilities.put(MobileCapabilityType.AUTOMATION_NAME, - AutomationName.IOS_XCUI_TEST.toString()); - - return new Capabilities() { - - @Override - public Object getCapability(String capabilityName) { - return capabilities.get(capabilityName); - } - - @Override - public Map asMap() { - return capabilities; - } - }; - } - } - - @Test - public void noGenericsTestCase() { - TempNoGenericsPage page = new TempNoGenericsPage(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void unBoundTestCase() { - TempUnboundPage page = new TempUnboundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void unboundWebElementTestCase() { - TempUnboundPage page = new TempUnboundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void webBoundUnknownElementTestCase() { - TempWebBoundPage page = new TempWebBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void webBoundWebElementTestCase() { - TempWebBoundPage page = new TempWebBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void webBoundMobileElementTestCase() { - TempWebBoundPage page = new TempWebBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void mobileBoundUnknownElementTestCase() { - TempMobileBoundPage page = new TempMobileBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } - - @Test - public void mobileBoundMobileElementTestCase() { - TempMobileBoundPage page = new TempMobileBoundPage<>(); - PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page); - page.assertInit(); - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java index 4be99b958..8c4b5cf30 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java @@ -66,7 +66,7 @@ public class MobileBrowserCompatibilityTest { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.BROWSER); - driver = new AndroidDriver(service.getUrl(), capabilities); + 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); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java index ee2324256..aa72d203e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package io.appium.java_client.pagefactory_tests; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; @@ -28,7 +27,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import io.appium.java_client.MobileElement; import io.appium.java_client.ios.AppIOSTest; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; @@ -38,8 +36,8 @@ import org.junit.Test; import org.junit.runners.MethodSorters; import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.PageFactory; -import org.openqa.selenium.support.ui.WebDriverWait; import java.util.List; @@ -47,50 +45,49 @@ public class XCUITModeTest extends AppIOSTest { private boolean populated = false; - private WebDriverWait waiting = new WebDriverWait(driver, 10); @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "label contains 'Compute'") @iOSXCUITFindBy(className = "XCUIElementTypeButton") - private MobileElement computeButton; + private WebElement computeButton; @HowToUseLocators(iOSXCUITAutomation = CHAIN) @iOSXCUITFindBy(iOSNsPredicate = "name like 'Answer'") private WebElement answer; @iOSXCUITFindBy(iOSNsPredicate = "name = 'IntegerA'") - private MobileElement textField1; + private WebElement textField1; @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "name = 'IntegerB'") @iOSXCUITFindBy(accessibility = "IntegerB") - private MobileElement textField2; + private WebElement textField2; @iOSXCUITFindBy(iOSNsPredicate = "name ENDSWITH 'Gesture'") - private MobileElement gesture; + private WebElement gesture; @iOSXCUITFindBy(className = "XCUIElementTypeSlider") - private MobileElement slider; + private WebElement slider; @iOSXCUITFindBy(id = "locationStatus") - private MobileElement locationStatus; + private WebElement locationStatus; @HowToUseLocators(iOSXCUITAutomation = CHAIN) @iOSXCUITFindBy(iOSNsPredicate = "name BEGINSWITH 'contact'") - private MobileElement contactAlert; + private WebElement contactAlert; @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @iOSXCUITFindBy(iOSNsPredicate = "name BEGINSWITH 'location'") - private MobileElement locationAlert; + private WebElement locationAlert; @iOSXCUITFindBy(iOSClassChain = "XCUIElementTypeWindow/*/XCUIElementTypeTextField[2]") - private MobileElement secondTextField; + private WebElement secondTextField; @iOSXCUITFindBy(iOSClassChain = "XCUIElementTypeWindow/*/XCUIElementTypeButton[-1]") - private MobileElement lastButton; + private WebElement lastButton; @iOSXCUITFindBy(iOSClassChain = "XCUIElementTypeWindow/*/XCUIElementTypeButton") - private List allButtons; + private List allButtons; /** * The setting up. @@ -144,8 +141,8 @@ public class XCUITModeTest extends AppIOSTest { } @Test public void setValueTest() { - textField1.setValue("2"); - textField2.setValue("4"); + driver.setElementValue((RemoteWebElement) textField1, "2"); + driver.setElementValue((RemoteWebElement) textField2, "4"); driver.hideKeyboard(); computeButton.click(); assertEquals("6", answer.getText()); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index 7e3d5783a..b9b9d097e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -8,12 +8,13 @@ import static io.appium.java_client.remote.MobilePlatform.WINDOWS; import static org.apache.commons.lang3.StringUtils.EMPTY; -import io.appium.java_client.HasSessionDetails; +import io.appium.java_client.HasBrowserCheck; import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Cookie; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import org.openqa.selenium.logging.Logs; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.Response; @@ -25,7 +26,9 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -public abstract class AbstractStubWebDriver implements WebDriver, HasSessionDetails, +public abstract class AbstractStubWebDriver implements + WebDriver, + HasBrowserCheck, HasCapabilities { @Override public Response execute(String driverCommand, Map parameters) { @@ -37,12 +40,6 @@ public Response execute(String driverCommand) { return null; } - @Override - public abstract String getPlatformName(); - - @Override - public abstract String getAutomationName(); - @Override public boolean isBrowser() { return false; @@ -64,7 +61,7 @@ public String getTitle() { } @Override - public List findElements(By by) { + public List findElements(By by) { return of(new StubWebElement(this, by), new StubWebElement(this, by)); } @@ -108,6 +105,14 @@ public Navigation navigate() { return null; } + public String getPlatformName() { + return ""; + } + + public String getAutomationName() { + return ""; + } + @Override public Capabilities getCapabilities() { Map caps = new HashMap<>(); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java index 52aa50807..cffb170fd 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java @@ -70,7 +70,7 @@ public String getText() { } @Override - public List findElements(By by) { + public List findElements(By by) { return of(new StubWebElement(driver, by), new StubWebElement(driver, by)); } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java index 612db0aed..7f0bdf590 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java @@ -44,7 +44,7 @@ public class StartingAppLocallyTest { @Test public void startingAndroidAppWithCapabilitiesOnlyTest() { - AndroidDriver driver = new AndroidDriver<>(new UiAutomator2Options() + AndroidDriver driver = new AndroidDriver(new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() .setApp(apiDemosApk().toAbsolutePath().toString())); @@ -68,7 +68,7 @@ public void startingAndroidAppWithCapabilitiesAndServiceTest() { .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); - AndroidDriver driver = new AndroidDriver<>(builder, new UiAutomator2Options() + AndroidDriver driver = new AndroidDriver(builder, new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() .setApp(apiDemosApk().toAbsolutePath().toString())); @@ -106,7 +106,7 @@ public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { .setAppPackage("io.appium.android.apis") .setAppActivity(".view.WebView1"); - AndroidDriver driver = new AndroidDriver<>(builder, clientOptions); + AndroidDriver driver = new AndroidDriver(builder, clientOptions); try { Capabilities caps = driver.getCapabilities(); @@ -130,7 +130,7 @@ public void startingIOSAppWithCapabilitiesOnlyTest() { capabilities.setCapability(MobileCapabilityType.APP, uiCatalogAppZip().toAbsolutePath().toString()); capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - IOSDriver driver = new IOSDriver<>(capabilities); + IOSDriver driver = new IOSDriver(capabilities); try { Capabilities caps = driver.getCapabilities(); @@ -160,7 +160,7 @@ public void startingIOSAppWithCapabilitiesAndServiceTest() { .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); - IOSDriver driver = new IOSDriver<>(builder, capabilities); + IOSDriver driver = new IOSDriver(builder, capabilities); try { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) @@ -188,7 +188,7 @@ public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS).withCapabilities(serverCapabilities); - IOSDriver driver = new IOSDriver<>(builder, clientCapabilities); + IOSDriver driver = new IOSDriver(builder, clientCapabilities); try { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) From da8fde2b34e6818cb0447c43ff627d4510557928 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Oct 2021 18:03:27 +0200 Subject: [PATCH 014/501] chore: switch to javac compiler (#1556) --- build.gradle | 33 +++---------------- docs/Note-for-developers.md | 23 +------------ .../remote/AppiumCommandExecutor.java | 2 +- 3 files changed, 6 insertions(+), 52 deletions(-) diff --git a/build.gradle b/build.gradle index ebc729080..c242b1352 100644 --- a/build.gradle +++ b/build.gradle @@ -3,8 +3,8 @@ import org.apache.tools.ant.filters.* plugins { id 'java-library' id 'idea' - id 'maven-publish' id 'eclipse' + id 'maven-publish' id 'jacoco' id 'checkstyle' id 'signing' @@ -16,16 +16,6 @@ repositories { mavenCentral() } -configurations { - ecj - lombok -} - -dependencies { - ecj 'org.eclipse.jdt:ecj:3.26.0' - lombok 'org.projectlombok:lombok:1.18.22' -} - java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -33,25 +23,10 @@ java { withSourcesJar() } -compileJava { - def ecjJar = configurations.ecj.singleFile - def lombokjar = configurations.lombok.singleFile - - options.fork = true - options.fork executable: 'java', jvmArgs: [ '-javaagent:'+lombokjar.path+'=ECJ', '-jar', ecjJar.path, '-cp', lombokjar.path] - options.define compilerArgs: [ - '-encoding', 'utf-8', - // https://www.ibm.com/support/knowledgecenter/SS8PJ7_9.7.0/org.eclipse.jdt.doc.user/tasks/task-using_batch_compiler.htm - '-warn:-unused,-unchecked,-raw,-serial,-suppress', - ] - - // https://github.com/gradle/gradle/issues/12904 - options.headerOutputDirectory.convention(null) -} - dependencies { - compileOnly('org.projectlombok:lombok:1.18.22') - annotationProcessor('org.projectlombok:lombok:1.18.20') + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + api ("org.seleniumhq.selenium:selenium-java") { version { strictly "${project.property('selenium.version')}" diff --git a/docs/Note-for-developers.md b/docs/Note-for-developers.md index 586df8f5e..d6182196d 100644 --- a/docs/Note-for-developers.md +++ b/docs/Note-for-developers.md @@ -12,28 +12,7 @@ This is the Gradle project. Be sure that: -- The `JAVA_HOME` environmental contains a path to JDK > 7 - -- If non built-in gradle distribution is used then its version should be > 2.1 - -## Compiler - -This project is compiled in some not common way. We use `ecj` Eclipse Java Compiler. Below is the sample how to define this compiler by IDE. -![eclipse compiler](https://cloud.githubusercontent.com/assets/4927589/14228367/6fce184e-f91b-11e5-837c-2673446d24ea.png) - -## JDK - -Please check following settings: - -![](https://cloud.githubusercontent.com/assets/4927589/18324490/7ffd3ba4-7545-11e6-9f22-eb028737283c.png) - -![](https://cloud.githubusercontent.com/assets/4927589/18324593/f5254e3a-7545-11e6-85c5-e4c491ee268d.png) - -![](https://cloud.githubusercontent.com/assets/4927589/18324648/3f4635a6-7546-11e6-966c-2949059968ac.png) - -![](https://cloud.githubusercontent.com/assets/4927589/18324760/cbca4aee-7546-11e6-8cfb-e86d8018be6a.png) - -![](https://cloud.githubusercontent.com/assets/4927589/18324835/2e3bfc04-7547-11e6-8f5e-981aea8f1771.png) +- The `JAVA_HOME` environmental contains a path to JDK 1.8+ ## Coding Standards diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index e1e1b766c..463e14c38 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -161,7 +161,7 @@ private Response createSession(Command command) throws IOException { } public void refreshAdditionalCommands() { - getAdditionalCommands().forEach(super::defineCommand); + getAdditionalCommands().forEach(this::defineCommand); } @Override From 0a12636955882ee6717aacd88ac7b10fae8e781d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 28 Oct 2021 07:50:26 +0200 Subject: [PATCH 015/501] feat: Add web view options for XCUITest driver (#1557) --- .../ios/options/XCUITestOptions.java | 42 +++++++++++- .../SupportsAbsoluteWebLocationsOption.java | 63 ++++++++++++++++++ ...portsAdditionalWebviewBundleIdsOption.java | 53 +++++++++++++++ ...ortsEnableAsyncExecuteFromHttpsOption.java | 59 +++++++++++++++++ .../SupportsFullContextListOption.java | 63 ++++++++++++++++++ ...SupportsIncludeSafariInWebviewsOption.java | 62 ++++++++++++++++++ .../webview/SupportsNativeWebTapOption.java | 60 +++++++++++++++++ .../SupportsNativeWebTapStrictOption.java | 59 +++++++++++++++++ .../SupportsSafariAllowPopupsOption.java | 58 +++++++++++++++++ .../SupportsSafariGarbageCollectOption.java | 59 +++++++++++++++++ ...upportsSafariIgnoreFraudWarningOption.java | 59 +++++++++++++++++ ...upportsSafariIgnoreWebHostnamesOption.java | 51 +++++++++++++++ .../SupportsSafariInitialUrlOption.java | 47 ++++++++++++++ ...afariLogAllCommunicationHexDumpOption.java | 64 +++++++++++++++++++ ...pportsSafariLogAllCommunicationOption.java | 60 +++++++++++++++++ ...ortsSafariOpenLinksInBackgroundOption.java | 59 +++++++++++++++++ .../SupportsSafariSocketChunkSizeOption.java | 52 +++++++++++++++ ...afariWebInspectorMaxFrameLengthOption.java | 52 +++++++++++++++ .../SupportsWebkitResponseTimeoutOption.java | 52 +++++++++++++++ .../SupportsWebviewConnectRetriesOption.java | 51 +++++++++++++++ .../SupportsWebviewConnectTimeoutOption.java | 52 +++++++++++++++ 21 files changed, 1175 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsAbsoluteWebLocationsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsAdditionalWebviewBundleIdsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsEnableAsyncExecuteFromHttpsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsFullContextListOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsIncludeSafariInWebviewsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapStrictOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariAllowPopupsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariGarbageCollectOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreFraudWarningOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreWebHostnamesOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariInitialUrlOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationHexDumpOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariOpenLinksInBackgroundOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariSocketChunkSizeOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariWebInspectorMaxFrameLengthOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsWebkitResponseTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectRetriesOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectTimeoutOption.java diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index f06086820..eab916b61 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -74,6 +74,25 @@ import io.appium.java_client.ios.options.wda.SupportsWdaStartupRetryIntervalOption; import io.appium.java_client.ios.options.wda.SupportsWebDriverAgentUrlOption; import io.appium.java_client.ios.options.wda.SupportsXcodeCertificateOptions; +import io.appium.java_client.ios.options.webview.SupportsAbsoluteWebLocationsOption; +import io.appium.java_client.ios.options.webview.SupportsAdditionalWebviewBundleIdsOption; +import io.appium.java_client.ios.options.webview.SupportsEnableAsyncExecuteFromHttpsOption; +import io.appium.java_client.ios.options.webview.SupportsFullContextListOption; +import io.appium.java_client.ios.options.webview.SupportsIncludeSafariInWebviewsOption; +import io.appium.java_client.ios.options.webview.SupportsNativeWebTapOption; +import io.appium.java_client.ios.options.webview.SupportsNativeWebTapStrictOption; +import io.appium.java_client.ios.options.webview.SupportsSafariAllowPopupsOption; +import io.appium.java_client.ios.options.webview.SupportsSafariGarbageCollectOption; +import io.appium.java_client.ios.options.webview.SupportsSafariIgnoreFraudWarningOption; +import io.appium.java_client.ios.options.webview.SupportsSafariIgnoreWebHostnamesOption; +import io.appium.java_client.ios.options.webview.SupportsSafariInitialUrlOption; +import io.appium.java_client.ios.options.webview.SupportsSafariLogAllCommunicationHexDumpOption; +import io.appium.java_client.ios.options.webview.SupportsSafariLogAllCommunicationOption; +import io.appium.java_client.ios.options.webview.SupportsSafariOpenLinksInBackgroundOption; +import io.appium.java_client.ios.options.webview.SupportsSafariSocketChunkSizeOption; +import io.appium.java_client.ios.options.webview.SupportsSafariWebInspectorMaxFrameLengthOption; +import io.appium.java_client.ios.options.webview.SupportsWebviewConnectRetriesOption; +import io.appium.java_client.ios.options.webview.SupportsWebviewConnectTimeoutOption; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; @@ -164,9 +183,28 @@ public class XCUITestOptions extends BaseOptions implements SupportsSimulatorPasteboardAutomaticSyncOption, SupportsSimulatorDevicesSetPathOption, SupportsCustomSslCertOption, - SupportsWebkitResponseTimeoutOption, - // TODO: Web context options: https://github.com/appium/appium-xcuitest-driver#web-context + // Web context options: https://github.com/appium/appium-xcuitest-driver#web-context SupportsAutoWebViewOption, + SupportsAbsoluteWebLocationsOption, + SupportsSafariGarbageCollectOption, + SupportsIncludeSafariInWebviewsOption, + SupportsSafariLogAllCommunicationOption, + SupportsSafariLogAllCommunicationHexDumpOption, + SupportsSafariSocketChunkSizeOption, + SupportsSafariWebInspectorMaxFrameLengthOption, + SupportsAdditionalWebviewBundleIdsOption, + SupportsWebviewConnectTimeoutOption, + SupportsSafariIgnoreWebHostnamesOption, + SupportsNativeWebTapOption, + SupportsNativeWebTapStrictOption, + SupportsSafariInitialUrlOption, + SupportsSafariAllowPopupsOption, + SupportsSafariIgnoreFraudWarningOption, + SupportsSafariOpenLinksInBackgroundOption, + SupportsWebviewConnectRetriesOption, + SupportsWebkitResponseTimeoutOption, + SupportsEnableAsyncExecuteFromHttpsOption, + SupportsFullContextListOption, // TODO: Other options: https://github.com/appium/appium-xcuitest-driver#other SupportsClearSystemFilesOption, SupportsEnablePerformanceLoggingOption { diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsAbsoluteWebLocationsOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsAbsoluteWebLocationsOption.java new file mode 100644 index 000000000..ae3375b70 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsAbsoluteWebLocationsOption.java @@ -0,0 +1,63 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAbsoluteWebLocationsOption> extends + Capabilities, CanSetCapability { + String ABSOLUTE_WEB_LOCATIONS_OPTION = "absoluteWebLocations"; + + /** + * Enforces Get Element Location to return coordinates + * relative to the page origin for web view elements. + * + * @return self instance for chaining. + */ + default T absoluteWebLocations() { + return amend(ABSOLUTE_WEB_LOCATIONS_OPTION, true); + } + + /** + * This capability will direct the Get Element Location command, when used + * within webviews, to return coordinates which are relative to the origin of + * the page, rather than relative to the current scroll offset. This capability + * has no effect outside of webviews. Default false. + * + * @param value Whether to return coordinates relative to the page origin for web view elements. + * @return self instance for chaining. + */ + default T setAbsoluteWebLocations(boolean value) { + return amend(ABSOLUTE_WEB_LOCATIONS_OPTION, value); + } + + /** + * Get whether Get Element Location returns coordinates + * relative to the page origin for web view elements. + * + * @return True or false. + */ + default Optional doesAbsoluteWebLocations() { + return Optional.ofNullable(toSafeBoolean(getCapability(ABSOLUTE_WEB_LOCATIONS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsAdditionalWebviewBundleIdsOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsAdditionalWebviewBundleIdsOption.java new file mode 100644 index 000000000..a21044b8f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsAdditionalWebviewBundleIdsOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.List; +import java.util.Optional; + +public interface SupportsAdditionalWebviewBundleIdsOption> extends + Capabilities, CanSetCapability { + String ADDITIONAL_WEBVIEW_BUNDLE_IDS_OPTION = "additionalWebviewBundleIds"; + + /** + * Array of possible bundle identifiers for webviews. This is sometimes + * necessary if the Web Inspector is found to be returning a modified + * bundle identifier for the app. Defaults to []. + * + * @param identifiers Identifiers list. + * @return self instance for chaining. + */ + default T setAdditionalWebviewBundleIds(List identifiers) { + return amend(ADDITIONAL_WEBVIEW_BUNDLE_IDS_OPTION, identifiers); + } + + /** + * Get the array of possible bundle identifiers for webviews. + * + * @return Identifier list. + */ + default Optional> getAdditionalWebviewBundleIds() { + //noinspection unchecked + return Optional.ofNullable( + (List) getCapability(ADDITIONAL_WEBVIEW_BUNDLE_IDS_OPTION) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsEnableAsyncExecuteFromHttpsOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsEnableAsyncExecuteFromHttpsOption.java new file mode 100644 index 000000000..36e135436 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsEnableAsyncExecuteFromHttpsOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsEnableAsyncExecuteFromHttpsOption> extends + Capabilities, CanSetCapability { + String ENABLE_ASYNC_EXECUTE_FROM_HTTPS_OPTION = "enableAsyncExecuteFromHttps"; + + /** + * Enforces to allow simulators to execute async JavaScript on pages using HTTPS. + * + * @return self instance for chaining. + */ + default T enableAsyncExecuteFromHttps() { + return amend(ENABLE_ASYNC_EXECUTE_FROM_HTTPS_OPTION, true); + } + + /** + * Capability to allow simulators to execute asynchronous JavaScript + * on pages using HTTPS. Defaults to false. + * + * @param value Whether to allow simulators to execute async JavaScript on pages using HTTPS. + * @return self instance for chaining. + */ + default T setEnableAsyncExecuteFromHttps(boolean value) { + return amend(ENABLE_ASYNC_EXECUTE_FROM_HTTPS_OPTION, value); + } + + /** + * Get whether to allow simulators to execute async JavaScript on pages using HTTPS. + * + * @return True or false. + */ + default Optional doesEnableAsyncExecuteFromHttps() { + return Optional.ofNullable(toSafeBoolean(getCapability(ENABLE_ASYNC_EXECUTE_FROM_HTTPS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsFullContextListOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsFullContextListOption.java new file mode 100644 index 000000000..da432480c --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsFullContextListOption.java @@ -0,0 +1,63 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsFullContextListOption> extends + Capabilities, CanSetCapability { + String FULL_CONTEXT_LIST_OPTION = "fullContextList"; + + /** + * Enforces to return the detailed information on contexts for the get available + * context command. + * + * @return self instance for chaining. + */ + default T fullContextList() { + return amend(FULL_CONTEXT_LIST_OPTION, true); + } + + /** + * Sets to return the detailed information on contexts for the get available + * context command. If this capability is enabled, then each item in the returned + * contexts list would additionally include WebView title, full URL and the bundle + * identifier. Defaults to false. + * + * @param value Whether to return the detailed info on available context command. + * @return self instance for chaining. + */ + default T setFullContextList(boolean value) { + return amend(FULL_CONTEXT_LIST_OPTION, value); + } + + /** + * Get whether to return the detailed information on contexts for the get available + * context command. + * + * @return True or false. + */ + default Optional doesFullContextList() { + return Optional.ofNullable(toSafeBoolean(getCapability(FULL_CONTEXT_LIST_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsIncludeSafariInWebviewsOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsIncludeSafariInWebviewsOption.java new file mode 100644 index 000000000..c7709050b --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsIncludeSafariInWebviewsOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsIncludeSafariInWebviewsOption> extends + Capabilities, CanSetCapability { + String INCLUDE_SAFARI_IN_WEBVIEWS_OPTION = "includeSafariInWebviews"; + + /** + * Enforces Safari web views to be added to the list of contexts available + * during a native/webview app test. + * + * @return self instance for chaining. + */ + default T includeSafariInWebviews() { + return amend(INCLUDE_SAFARI_IN_WEBVIEWS_OPTION, true); + } + + /** + * Add Safari web contexts to the list of contexts available during a + * native/webview app test. This is useful if the test opens Safari and + * needs to be able to interact with it. Defaults to false. + * + * @param value Whether to add Safari to the list of contexts available during a native/webview app test. + * @return self instance for chaining. + */ + default T setIncludeSafariInWebviews(boolean value) { + return amend(INCLUDE_SAFARI_IN_WEBVIEWS_OPTION, value); + } + + /** + * Get whether to add Safari web views to the list of contexts available + * during a native/webview app test. + * + * @return True or false. + */ + default Optional doesIncludeSafariInWebviews() { + return Optional.ofNullable(toSafeBoolean(getCapability(INCLUDE_SAFARI_IN_WEBVIEWS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapOption.java new file mode 100644 index 000000000..5158a06f7 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsNativeWebTapOption> extends + Capabilities, CanSetCapability { + String NATIVE_WEB_TAP_OPTION = "nativeWebTap"; + + /** + * Enforces native non-javascript-based taps in web context mode. + * + * @return self instance for chaining. + */ + default T nativeWebTap() { + return amend(NATIVE_WEB_TAP_OPTION, true); + } + + /** + * Enable native, non-javascript-based taps being in web context mode. Defaults + * to false. Warning: sometimes the preciseness of native taps could be broken, + * because there is no reliable way to map web element coordinates to native ones. + * + * @param value Whether to enable native taps in web view mode. + * @return self instance for chaining. + */ + default T setNativeWebTap(boolean value) { + return amend(NATIVE_WEB_TAP_OPTION, value); + } + + /** + * Get whether to enable native taps in web view mode. + * + * @return True or false. + */ + default Optional doesNativeWebTap() { + return Optional.ofNullable(toSafeBoolean(getCapability(NATIVE_WEB_TAP_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapStrictOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapStrictOption.java new file mode 100644 index 000000000..0711d9b1f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsNativeWebTapStrictOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsNativeWebTapStrictOption> extends + Capabilities, CanSetCapability { + String NATIVE_WEB_TAP_STRICT_OPTION = "nativeWebTapStrict"; + + /** + * Enforce native taps to be done by XCUITest driver rather than WebDriverAgent. + * + * @return self instance for chaining. + */ + default T nativeWebTapStrict() { + return amend(NATIVE_WEB_TAP_STRICT_OPTION, true); + } + + /** + * Configure native taps to be done by XCUITest driver rather than WebDriverAgent. + * Only applicable if nativeWebTap is enabled. false by default. + * + * @param value Whether native taps are done by XCUITest driver rather than WebDriverAgent. + * @return self instance for chaining. + */ + default T setNativeWebTapStrict(boolean value) { + return amend(NATIVE_WEB_TAP_STRICT_OPTION, value); + } + + /** + * Get whether native taps are done by XCUITest driver rather than WebDriverAgent. + * + * @return True or false. + */ + default Optional doesNativeWebTapStrict() { + return Optional.ofNullable(toSafeBoolean(getCapability(NATIVE_WEB_TAP_STRICT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariAllowPopupsOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariAllowPopupsOption.java new file mode 100644 index 000000000..d7ad7d1f0 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariAllowPopupsOption.java @@ -0,0 +1,58 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariAllowPopupsOption> extends + Capabilities, CanSetCapability { + String SAFARI_ALLOW_POPUPS_OPTION = "safariAllowPopups"; + + /** + * Enforces to allow javascript to open popups in Safari. + * + * @return self instance for chaining. + */ + default T safariAllowPopups() { + return amend(SAFARI_ALLOW_POPUPS_OPTION, true); + } + + /** + * Allow javascript to open new windows in Safari. Default keeps current sim setting. + * + * @param value Whether to allow javascript to open popups in Safari. + * @return self instance for chaining. + */ + default T setSafariAllowPopups(boolean value) { + return amend(SAFARI_ALLOW_POPUPS_OPTION, value); + } + + /** + * Get whether to allow javascript to open new windows in Safari. + * + * @return True or false. + */ + default Optional doesSafariAllowPopups() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_ALLOW_POPUPS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariGarbageCollectOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariGarbageCollectOption.java new file mode 100644 index 000000000..2990e2a75 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariGarbageCollectOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariGarbageCollectOption> extends + Capabilities, CanSetCapability { + String SAFARI_GARBAGE_COLLECT_OPTION = "safariGarbageCollect"; + + /** + * Enforces to turn on garbage collection when executing scripts on Safari. + * + * @return self instance for chaining. + */ + default T safariGarbageCollect() { + return amend(SAFARI_GARBAGE_COLLECT_OPTION, true); + } + + /** + * Turns on/off Web Inspector garbage collection when executing scripts on Safari. + * Turning on may improve performance. Defaults to false. + * + * @param value Whether to turn on garbage collection when executing scripts on Safari. + * @return self instance for chaining. + */ + default T setSafariGarbageCollect(boolean value) { + return amend(SAFARI_GARBAGE_COLLECT_OPTION, value); + } + + /** + * Get whether to turn on garbage collection when executing scripts on Safari. + * + * @return True or false. + */ + default Optional doesSafariGarbageCollect() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_GARBAGE_COLLECT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreFraudWarningOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreFraudWarningOption.java new file mode 100644 index 000000000..ad51e338a --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreFraudWarningOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariIgnoreFraudWarningOption> extends + Capabilities, CanSetCapability { + String SAFARI_IGNORE_FRAUD_WARNING_OPTION = "safariIgnoreFraudWarning"; + + /** + * Enforces to prevent Safari from showing a fraudulent website warning. + * + * @return self instance for chaining. + */ + default T safariIgnoreFraudWarning() { + return amend(SAFARI_IGNORE_FRAUD_WARNING_OPTION, true); + } + + /** + * Prevent Safari from showing a fraudulent website warning. + * Default keeps current sim setting.. + * + * @param value Whether to prevent Safari from showing a fraudulent website warning. + * @return self instance for chaining. + */ + default T setSafariIgnoreFraudWarning(boolean value) { + return amend(SAFARI_IGNORE_FRAUD_WARNING_OPTION, value); + } + + /** + * Get whether to prevent Safari from showing a fraudulent website warning. + * + * @return True or false. + */ + default Optional doesSafariIgnoreFraudWarning() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_IGNORE_FRAUD_WARNING_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreWebHostnamesOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreWebHostnamesOption.java new file mode 100644 index 000000000..e8e154e72 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariIgnoreWebHostnamesOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariIgnoreWebHostnamesOption> extends + Capabilities, CanSetCapability { + String SAFARI_IGNORE_WEB_HOSTNAMES_OPTION = "safariIgnoreWebHostnames"; + + /** + * Provide a list of hostnames (comma-separated) that the Safari automation + * tools should ignore. This is to provide a workaround to prevent a webkit + * bug where the web context is unintentionally changed to a 3rd party website + * and the test gets stuck. The common culprits are search engines (yahoo, bing, + * google) and about:blank. + * + * @param hostnames E.g. 'www.yahoo.com, www.bing.com, www.google.com, about:blank'. + * @return self instance for chaining. + */ + default T setSafariIgnoreWebHostnames(String hostnames) { + return amend(SAFARI_IGNORE_WEB_HOSTNAMES_OPTION, hostnames); + } + + /** + * Get the comma-separated list of host names to be ignored. + * + * @return XCTest result bundle path. + */ + default Optional getSafariIgnoreWebHostnames() { + return Optional.ofNullable((String) getCapability(SAFARI_IGNORE_WEB_HOSTNAMES_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariInitialUrlOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariInitialUrlOption.java new file mode 100644 index 000000000..bd2193a3e --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariInitialUrlOption.java @@ -0,0 +1,47 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariInitialUrlOption> extends + Capabilities, CanSetCapability { + String SAFARI_INITIAL_URL_OPTION = "safariInitialUrl"; + + /** + * Set initial safari url, default is a local welcome page. + * + * @param url Initial safari url. + * @return self instance for chaining. + */ + default T setSafariInitialUrl(String url) { + return amend(SAFARI_INITIAL_URL_OPTION, url); + } + + /** + * Get the initial safari url. + * + * @return Initial safari url. + */ + default Optional getSafariInitialUrl() { + return Optional.ofNullable((String) getCapability(SAFARI_INITIAL_URL_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationHexDumpOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationHexDumpOption.java new file mode 100644 index 000000000..4dbece202 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationHexDumpOption.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.ios.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariLogAllCommunicationHexDumpOption> extends + Capabilities, CanSetCapability { + String SAFARI_LOG_ALL_COMMUNICATION_HEX_DUMP_OPTION = "safariLogAllCommunicationHexDump"; + + /** + * Enforces logging of plists sent to and received from the Web Inspector + * in hex dump format. + * + * @return self instance for chaining. + */ + default T safariLogAllCommunicationHexDump() { + return amend(SAFARI_LOG_ALL_COMMUNICATION_HEX_DUMP_OPTION, true); + } + + /** + * Log all communication sent to and received from the Web Inspector, as raw + * hex dump and printable characters. This logging is done before any data + * manipulation, and so can elucidate some communication issues. Like + * appium:safariLogAllCommunication, this can produce a lot of data in some cases, + * so it is recommended to be used only when necessary. Defaults to false. + * + * @param value Whether to log all internal web debugger communication in hex dump format. + * @return self instance for chaining. + */ + default T setSafariLogAllCommunicationHexDump(boolean value) { + return amend(SAFARI_LOG_ALL_COMMUNICATION_HEX_DUMP_OPTION, value); + } + + /** + * Get whether to log of plists sent to and received from the Web Inspector + * in hex dump format. + * + * @return True or false. + */ + default Optional doesSafariLogAllCommunicationHexDump() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_LOG_ALL_COMMUNICATION_HEX_DUMP_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationOption.java new file mode 100644 index 000000000..e351cbb62 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariLogAllCommunicationOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariLogAllCommunicationOption> extends + Capabilities, CanSetCapability { + String SAFARI_LOG_ALL_COMMUNICATION_OPTION = "safariLogAllCommunication"; + + /** + * Enforces logging of plists sent to and received from the Web Inspector. + * + * @return self instance for chaining. + */ + default T safariLogAllCommunication() { + return amend(SAFARI_LOG_ALL_COMMUNICATION_OPTION, true); + } + + /** + * Log all plists sent to and received from the Web Inspector, as plain text. + * For some operations this can be a lot of data, so it is recommended to + * be used only when necessary. Defaults to false. + * + * @param value Whether to log all internal web debugger communication. + * @return self instance for chaining. + */ + default T setSafariLogAllCommunication(boolean value) { + return amend(SAFARI_LOG_ALL_COMMUNICATION_OPTION, value); + } + + /** + * Get whether to log of plists sent to and received from the Web Inspector. + * + * @return True or false. + */ + default Optional doesSafariLogAllCommunication() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_LOG_ALL_COMMUNICATION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariOpenLinksInBackgroundOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariOpenLinksInBackgroundOption.java new file mode 100644 index 000000000..28b79a962 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariOpenLinksInBackgroundOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariOpenLinksInBackgroundOption> extends + Capabilities, CanSetCapability { + String SAFARI_OPEN_LINKS_IN_BACKGROUND_OPTION = "safariOpenLinksInBackground"; + + /** + * Enforces Safari to open links in new windows. + * + * @return self instance for chaining. + */ + default T safariOpenLinksInBackground() { + return amend(SAFARI_OPEN_LINKS_IN_BACKGROUND_OPTION, true); + } + + /** + * Whether Safari should allow links to open in new windows. + * Default keeps current sim setting. + * + * @param value Whether Safari should allow links to open in new windows. + * @return self instance for chaining. + */ + default T setSafariOpenLinksInBackground(boolean value) { + return amend(SAFARI_OPEN_LINKS_IN_BACKGROUND_OPTION, value); + } + + /** + * Get whether Safari should allow links to open in new windows. + * + * @return True or false. + */ + default Optional doesSafariOpenLinksInBackground() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_OPEN_LINKS_IN_BACKGROUND_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariSocketChunkSizeOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariSocketChunkSizeOption.java new file mode 100644 index 000000000..24190efaa --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariSocketChunkSizeOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsSafariSocketChunkSizeOption> extends + Capabilities, CanSetCapability { + String SAFARI_SOCKET_CHUNK_SIZE_OPTION = "safariSocketChunkSize"; + + /** + * The size, in bytes, of the data to be sent to the Web Inspector on + * iOS 11+ real devices. Some devices hang when sending large amounts of + * data to the Web Inspector, and breaking them into smaller parts can be + * helpful in those cases. Defaults to 16384 (also the maximum possible). + * + * @param size Socket chunk size in range 1..16384. + * @return self instance for chaining. + */ + default T setSafariSocketChunkSize(int size) { + return amend(SAFARI_SOCKET_CHUNK_SIZE_OPTION, size); + } + + /** + * Get the size of a single remote debugger socket chunk. + * + * @return Chunk size in bytes. + */ + default Optional getSafariSocketChunkSize() { + return Optional.ofNullable(toInteger(getCapability(SAFARI_SOCKET_CHUNK_SIZE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariWebInspectorMaxFrameLengthOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariWebInspectorMaxFrameLengthOption.java new file mode 100644 index 000000000..b3b4c6f26 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsSafariWebInspectorMaxFrameLengthOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsSafariWebInspectorMaxFrameLengthOption> extends + Capabilities, CanSetCapability { + String SAFARI_WEB_INSPECTOR_MAX_FRAME_LENGTH_OPTION = "safariWebInspectorMaxFrameLength"; + + /** + * The maximum size in bytes of a single data frame for the Web Inspector. + * Too high values could introduce slowness and/or memory leaks. + * Too low values could introduce possible buffer overflow exceptions. + * Defaults to 20MB (20*1024*1024). + * + * @param length Max size of a single data frame. + * @return self instance for chaining. + */ + default T setSafariWebInspectorMaxFrameLength(int length) { + return amend(SAFARI_WEB_INSPECTOR_MAX_FRAME_LENGTH_OPTION, length); + } + + /** + * Get the maximum size in bytes of a single data frame for the Web Inspector. + * + * @return Size in bytes. + */ + default Optional getSafariWebInspectorMaxFrameLength() { + return Optional.ofNullable(toInteger(getCapability(SAFARI_WEB_INSPECTOR_MAX_FRAME_LENGTH_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebkitResponseTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebkitResponseTimeoutOption.java new file mode 100644 index 000000000..dc9378399 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebkitResponseTimeoutOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.webview; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsWebkitResponseTimeoutOption> extends + Capabilities, CanSetCapability { + String WEBKIT_RESPONSE_TIMEOUT_OPTION = "webkitResponseTimeout"; + + /** + * (Real device only) Set the time to wait for a response from WebKit in + * a Safari session. Defaults to 5000ms. + * + * @param timeout Timeout to wait for a response from WebKit in a Safari session. + * @return self instance for chaining. + */ + default T setWebviewConnectTimeout(Duration timeout) { + return amend(WEBKIT_RESPONSE_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait for a response from WebKit in a Safari session. + * + * @return Timeout value. + */ + default Optional getWebviewConnectTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(WEBKIT_RESPONSE_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectRetriesOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectRetriesOption.java new file mode 100644 index 000000000..a1b658945 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectRetriesOption.java @@ -0,0 +1,51 @@ +/* + * 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.options.webview; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsWebviewConnectRetriesOption> extends + Capabilities, CanSetCapability { + String WEBVIEW_CONNECT_RETRIES_OPTION = "webviewConnectRetries"; + + /** + * Number of times to send connection message to remote debugger, + * to get a webview. Default: 8. + * + * @param retries Max retries count. + * @return self instance for chaining. + */ + default T setWebviewConnectRetries(int retries) { + return amend(WEBVIEW_CONNECT_RETRIES_OPTION, retries); + } + + /** + * Get the number of retries to send connection message to remote debugger, + * to get a webview. + * + * @return Max retries count. + */ + default Optional getWebviewConnectRetries() { + return Optional.ofNullable(toInteger(getCapability(WEBVIEW_CONNECT_RETRIES_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectTimeoutOption.java new file mode 100644 index 000000000..cd00db23f --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/webview/SupportsWebviewConnectTimeoutOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.webview; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsWebviewConnectTimeoutOption> extends + Capabilities, CanSetCapability { + String WEBVIEW_CONNECT_TIMEOUT_OPTION = "webviewConnectTimeout"; + + /** + * The time to wait for the initial presence of webviews in + * MobileSafari or hybrid apps. Defaults to 0ms. + * + * @param timeout Timeout to wait for the initial presence of webviews. + * @return self instance for chaining. + */ + default T setWebviewConnectTimeout(Duration timeout) { + return amend(WEBVIEW_CONNECT_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait for the initial presence of webviews. + * + * @return Timeout value. + */ + default Optional getWebviewConnectTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(WEBVIEW_CONNECT_TIMEOUT_OPTION)) + ); + } +} From 7040ee1cd2ba093840800e88c5f2835bbf28434b Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Oct 2021 09:57:00 +0300 Subject: [PATCH 016/501] chore: revise used Selenium dependencies (#1560) --- build.gradle | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index c242b1352..3b428fec7 100644 --- a/build.gradle +++ b/build.gradle @@ -23,28 +23,27 @@ java { withSourcesJar() } +ext { + seleniumVersion = project.property('selenium.version') +} + dependencies { compileOnly 'org.projectlombok:lombok:1.18.22' annotationProcessor 'org.projectlombok:lombok:1.18.22' - api ("org.seleniumhq.selenium:selenium-java") { + api ('org.seleniumhq.selenium:selenium-api') { version { - strictly "${project.property('selenium.version')}" + strictly "${seleniumVersion}" } - - exclude group: 'com.google.code.gson' - exclude module: 'htmlunit-driver' - exclude group: 'net.sourceforge.htmlunit' - } - implementation ("org.seleniumhq.selenium:selenium-support") { + api ('org.seleniumhq.selenium:selenium-remote-driver') { version { - strictly "${project.property('selenium.version')}" + strictly "${seleniumVersion}" } } - implementation ("org.seleniumhq.selenium:selenium-api") { + implementation ('org.seleniumhq.selenium:selenium-support') { version { - strictly "${project.property('selenium.version')}" + strictly "${seleniumVersion}" } } implementation 'com.google.code.gson:gson:2.8.8' @@ -62,6 +61,11 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.3') { exclude group: 'org.seleniumhq.selenium' } + testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { + version { + strictly "${seleniumVersion}" + } + } } ext { @@ -176,7 +180,7 @@ wrapper { processResources { filter ReplaceTokens, tokens: [ - 'selenium.version': project.property('selenium.version') + 'selenium.version': seleniumVersion ] } From 98c8a3c5f57e44a7b7f5ab6d190f618125d31d89 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Oct 2021 09:57:17 +0300 Subject: [PATCH 017/501] chore: revise used dependencies (#1558) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3b428fec7..847dbd2d3 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ dependencies { } } implementation 'com.google.code.gson:gson:2.8.8' - implementation 'org.apache.httpcomponents:httpclient:4.5.13' + implementation 'commons-codec:commons-codec:1.15' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' From e5fa9de0e98c769d501e492d91894682dadc3552 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 28 Oct 2021 15:55:36 +0200 Subject: [PATCH 018/501] chore: Add the rest of XCUITest driver options (#1561) --- .../io/appium/java_client/AppiumDriver.java | 11 ++- .../android/options/UiAutomator2Options.java | 9 ++- .../ios/options/XCUITestOptions.java | 25 +++++- .../other/SupportsCommandTimeoutsOption.java | 79 +++++++++++++++++++ .../other/SupportsLaunchWithIdbOption.java | 62 +++++++++++++++ ...SupportsResetOnSessionStartOnlyOption.java | 52 ++++++++++++ .../other/SupportsShowIosLogOption.java | 59 ++++++++++++++ .../other/SupportsUseJsonSourceOption.java | 60 ++++++++++++++ .../remote/options/BaseOptions.java | 31 ++++++++ .../options/SupportsBrowserNameOption.java | 34 ++++++++ .../SupportsSkipLogCaptureOption.java | 10 +-- .../java_client/android/FingerPrintTest.java | 13 ++- .../java_client/android/IntentTest.java | 11 ++- .../io/appium/java_client/ios/AppIOSTest.java | 26 +++--- .../java_client/ios/BaseIOSWebViewTest.java | 21 ++--- .../java_client/ios/BaseSafariTest.java | 20 ++--- .../java_client/ios/IOSWebViewTest.java | 16 ++-- .../MobileBrowserCompatibilityTest.java | 26 +++--- .../service/local/ServerBuilderTest.java | 58 ++++++-------- .../service/local/StartingAppLocallyTest.java | 74 ++++++++--------- 20 files changed, 538 insertions(+), 159 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/other/SupportsLaunchWithIdbOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/other/SupportsResetOnSessionStartOnlyOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/other/SupportsShowIosLogOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/other/SupportsUseJsonSourceOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsBrowserNameOption.java rename src/main/java/io/appium/java_client/{android/options/other => remote/options}/SupportsSkipLogCaptureOption.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 cd987ca94..31f68b353 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -17,10 +17,12 @@ package io.appium.java_client; import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; +import static org.apache.commons.lang3.StringUtils.isBlank; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; @@ -28,6 +30,7 @@ import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.ErrorHandler; import org.openqa.selenium.remote.ExecuteMethod; @@ -199,7 +202,13 @@ protected void startSession(Capabilities capabilities) { } @SuppressWarnings("unchecked") Map rawCapabilities = (Map) responseValue; - MutableCapabilities returnedCapabilities = new MutableCapabilities(rawCapabilities); + // A workaround for Selenium API enforcing some legacy capability values + rawCapabilities.remove(CapabilityType.PLATFORM); + if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME) + && isBlank((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { + rawCapabilities.remove(CapabilityType.BROWSER_NAME); + } + MutableCapabilities returnedCapabilities = new BaseOptions<>(rawCapabilities); try { Field capsField = RemoteWebDriver.class.getDeclaredField("capabilities"); capsField.setAccessible(true); diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index ee9ae2755..dc4b7a74c 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -78,7 +78,7 @@ import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption; import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption; import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption; -import io.appium.java_client.android.options.other.SupportsSkipLogCaptureOption; +import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption; import io.appium.java_client.android.options.other.SupportsUserProfileOption; import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption; import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption; @@ -104,6 +104,8 @@ import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; +import java.util.Map; + /** * https://github.com/appium/appium-uiautomator2-driver#capabilities */ @@ -211,6 +213,11 @@ public UiAutomator2Options(Capabilities source) { setCommonOptions(); } + public UiAutomator2Options(Map source) { + super(source); + setCommonOptions(); + } + private void setCommonOptions() { setPlatformName(MobilePlatform.ANDROID); setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2); diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index eab916b61..2eb61386d 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -22,6 +22,11 @@ import io.appium.java_client.ios.options.app.SupportsLocalizableStringsDirOption; import io.appium.java_client.ios.options.general.SupportsIncludeDeviceCapsToSessionInfoOption; import io.appium.java_client.ios.options.general.SupportsResetLocationServiceOption; +import io.appium.java_client.ios.options.other.SupportsCommandTimeoutsOption; +import io.appium.java_client.ios.options.other.SupportsLaunchWithIdbOption; +import io.appium.java_client.ios.options.other.SupportsResetOnSessionStartOnlyOption; +import io.appium.java_client.ios.options.other.SupportsShowIosLogOption; +import io.appium.java_client.ios.options.other.SupportsUseJsonSourceOption; import io.appium.java_client.ios.options.simulator.SupportsCalendarAccessAuthorizedOption; import io.appium.java_client.ios.options.simulator.SupportsCalendarFormatOption; import io.appium.java_client.ios.options.simulator.SupportsConnectHardwareKeyboardOption; @@ -106,9 +111,12 @@ import io.appium.java_client.remote.options.SupportsLocaleOption; import io.appium.java_client.remote.options.SupportsOrientationOption; import io.appium.java_client.remote.options.SupportsOtherAppsOption; +import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption; import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; +import java.util.Map; + /** * https://github.com/appium/appium-xcuitest-driver#capabilities */ @@ -205,9 +213,15 @@ public class XCUITestOptions extends BaseOptions implements SupportsWebkitResponseTimeoutOption, SupportsEnableAsyncExecuteFromHttpsOption, SupportsFullContextListOption, - // TODO: Other options: https://github.com/appium/appium-xcuitest-driver#other - SupportsClearSystemFilesOption, - SupportsEnablePerformanceLoggingOption { + SupportsEnablePerformanceLoggingOption, + // Other options: https://github.com/appium/appium-xcuitest-driver#other + SupportsResetOnSessionStartOnlyOption, + SupportsCommandTimeoutsOption, + SupportsUseJsonSourceOption, + SupportsSkipLogCaptureOption, + SupportsLaunchWithIdbOption, + SupportsShowIosLogOption, + SupportsClearSystemFilesOption { public XCUITestOptions() { setCommonOptions(); @@ -218,6 +232,11 @@ public XCUITestOptions(Capabilities source) { setCommonOptions(); } + public XCUITestOptions(Map source) { + super(source); + setCommonOptions(); + } + private void setCommonOptions() { setPlatformName(MobilePlatform.IOS); setAutomationName(AutomationName.IOS_XCUI_TEST); diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java new file mode 100644 index 000000000..42935504b --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java @@ -0,0 +1,79 @@ +/* + * 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.options.other; + +import com.google.gson.JsonObject; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsCommandTimeoutsOption> extends + Capabilities, CanSetCapability { + String COMMAND_TIMEOUTS_OPTION = "commandTimeouts"; + + /** + * Custom timeout(s) in milliseconds for WDA backend commands execution. + * This might be useful if WDA backend freezes unexpectedly or requires too + * much time to fail and blocks automated test execution. The value is expected + * to be of type string and can either contain max milliseconds to wait for + * each WDA command to be executed before terminating the session forcefully + * or a valid JSON string, where keys are internal Appium command names (you + * can find these in logs, look for "Executing command 'command_name'" records) + * and values are timeouts in milliseconds. You can also set the 'default' key + * to assign the timeout for all other commands not explicitly enumerated as + * JSON keys. + * + * @param timeouts E.g. '{"findElement": 40000, "findElements": 40000}'. + * @return self instance for chaining. + */ + default T setCommandTimeouts(JsonObject timeouts) { + return amend(COMMAND_TIMEOUTS_OPTION, timeouts.toString()); + } + + /** + * Custom timeout(s) in milliseconds for WDA backend commands execution. + * This might be useful if WDA backend freezes unexpectedly or requires too + * much time to fail and blocks automated test execution. The value is expected + * to be of type string and can either contain max milliseconds to wait for + * each WDA command to be executed before terminating the session forcefully + * or a valid JSON string, where keys are internal Appium command names (you + * can find these in logs, look for "Executing command 'command_name'" records) + * and values are timeouts in milliseconds. You can also set the 'default' key + * to assign the timeout for all other commands not explicitly enumerated as + * JSON keys. + * + * @param timeout The timeout value for all commands. + * @return self instance for chaining. + */ + default T setCommandTimeouts(Duration timeout) { + return amend(COMMAND_TIMEOUTS_OPTION, String.valueOf(timeout.toMillis())); + } + + /** + * Get custom timeout(s) in milliseconds for WDA backend commands execution. + * + * @return Command timeouts. + */ + default Optional getCommandTimeouts() { + return Optional.ofNullable( + (String) getCapability(COMMAND_TIMEOUTS_OPTION) + ); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsLaunchWithIdbOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsLaunchWithIdbOption.java new file mode 100644 index 000000000..8c36b58bf --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsLaunchWithIdbOption.java @@ -0,0 +1,62 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsLaunchWithIdbOption> extends + Capabilities, CanSetCapability { + String LAUNCH_WITH_IDB_OPTION = "launchWithIDB"; + + /** + * Enforces launching of WebDriverAgentRunner with idb instead of xcodebuild. + * + * @return self instance for chaining. + */ + default T launchWithIdb() { + return amend(LAUNCH_WITH_IDB_OPTION, true); + } + + /** + * Launch WebDriverAgentRunner with idb instead of xcodebuild. This could save + * a significant amount of time by skipping the xcodebuild process, although the + * idb might not be very reliable, especially with fresh Xcode SDKs. Check + * the idb repository for more details on possible compatibility issues. + * Defaults to false. + * + * @param value Whether to launch WebDriverAgentRunner with idb instead of xcodebuild. + * @return self instance for chaining. + */ + default T setLaunchWithIdb(boolean value) { + return amend(LAUNCH_WITH_IDB_OPTION, value); + } + + /** + * Get whether to launch WebDriverAgentRunner with idb instead of xcodebuild. + * + * @return True or false. + */ + default Optional doesLaunchWithIdb() { + return Optional.ofNullable(toSafeBoolean(getCapability(LAUNCH_WITH_IDB_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsResetOnSessionStartOnlyOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsResetOnSessionStartOnlyOption.java new file mode 100644 index 000000000..65f29c837 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsResetOnSessionStartOnlyOption.java @@ -0,0 +1,52 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsResetOnSessionStartOnlyOption> extends + Capabilities, CanSetCapability { + String RESET_ON_SESSION_START_ONLY_OPTION = "resetOnSessionStartOnly"; + + /** + * Whether to perform reset on test session finish (false) or not (true). + * Keeping this variable set to true and Simulator running (the default + * behaviour since version 1.6.4) may significantly shorten the duration of + * test session initialization. + * + * @param value Whether to perform reset on test session finish (false) or not (true).. + * @return self instance for chaining. + */ + default T setResetOnSessionStartOnly(boolean value) { + return amend(RESET_ON_SESSION_START_ONLY_OPTION, value); + } + + /** + * Get whether to perform reset on test session finish (false) or not (true). + * + * @return True or false. + */ + default Optional doesResetOnSessionStartOnly() { + return Optional.ofNullable(toSafeBoolean(getCapability(RESET_ON_SESSION_START_ONLY_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsShowIosLogOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsShowIosLogOption.java new file mode 100644 index 000000000..ee0676d44 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsShowIosLogOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShowIosLogOption> extends + Capabilities, CanSetCapability { + String SHOW_IOS_LOG_OPTION = "showIOSLog"; + + /** + * Enforces showing any logs captured from a device in the appium logs. + * + * @return self instance for chaining. + */ + default T showIosLog() { + return amend(SHOW_IOS_LOG_OPTION, true); + } + + /** + * Whether to show any logs captured from a device in the appium logs. + * Default false. + * + * @param value Whether to show any logs captured from a device in the appium logs. + * @return self instance for chaining. + */ + default T setShowIosLog(boolean value) { + return amend(SHOW_IOS_LOG_OPTION, value); + } + + /** + * Get whether to show any logs captured from a device in the appium logs. + * + * @return True or false. + */ + default Optional doesShowIosLog() { + return Optional.ofNullable(toSafeBoolean(getCapability(SHOW_IOS_LOG_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsUseJsonSourceOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsUseJsonSourceOption.java new file mode 100644 index 000000000..dd88a9a34 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsUseJsonSourceOption.java @@ -0,0 +1,60 @@ +/* + * 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.options.other; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUseJsonSourceOption> extends + Capabilities, CanSetCapability { + String USE_JSON_SOURCE_OPTION = "useJSONSource"; + + /** + * Enforces getting JSON source from WDA and transform it to XML on the Appium + * server side. + * + * @return self instance for chaining. + */ + default T useJSONSource() { + return amend(USE_JSON_SOURCE_OPTION, true); + } + + /** + * Get JSON source from WDA and transform it to XML on the Appium server side. + * Defaults to false. + * + * @param value Whether to get JSON source from WDA and transform it to XML. + * @return self instance for chaining. + */ + default T setUseJSONSource(boolean value) { + return amend(USE_JSON_SOURCE_OPTION, value); + } + + /** + * Get whether to get JSON source from WDA and transform it to XML. + * + * @return True or false. + */ + default Optional doesUseJSONSource() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_JSON_SOURCE_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index bb597d195..bfa8c3cc4 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -18,6 +18,8 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.Platform; +import org.openqa.selenium.WebDriverException; import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.AcceptedW3CCapabilityKeys; import org.openqa.selenium.remote.CapabilityType; @@ -26,6 +28,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; @@ -46,6 +49,7 @@ public class BaseOptions> extends MutableCapabilities i SupportsNoResetOption, SupportsFullResetOption, SupportsNewCommandTimeoutOption, + SupportsBrowserNameOption, SupportsPlatformVersionOption { private static final AcceptedW3CCapabilityKeys W3C_KEY_PATTERNS = new AcceptedW3CCapabilityKeys(); @@ -55,6 +59,15 @@ public class BaseOptions> extends MutableCapabilities i public BaseOptions() { } + /** + * Creates new instance with provided capabilities. + * + * @param source Capabilities map to merge into new instance + */ + public BaseOptions(Map source) { + super(source); + } + /** * Creates new instance with provided capabilities. * @@ -75,6 +88,24 @@ public T setPlatformName(String platform) { return amend(CapabilityType.PLATFORM_NAME, platform); } + @Override + @Nullable + public Platform getPlatformName() { + return Optional.ofNullable(getCapability(CapabilityType.PLATFORM_NAME)) + .map(cap -> { + if (cap instanceof Platform) { + return (Platform) cap; + } + + try { + return Platform.fromString((String.valueOf(cap))); + } catch (WebDriverException e) { + return null; + } + }) + .orElse(null); + } + @Override public Map asMap() { return unmodifiableMap(super.asMap().entrySet().stream() diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsBrowserNameOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsBrowserNameOption.java new file mode 100644 index 000000000..b0506feda --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsBrowserNameOption.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.remote.options; + +import org.openqa.selenium.Capabilities; + +public interface SupportsBrowserNameOption> extends + Capabilities, CanSetCapability { + String BROWSER_NAME_OPTION = "browserName"; + + /** + * Set the browser name to use. + * + * @param browserName One of supported browser names. + * @return self instance for chaining. + */ + default T withBrowserName(String browserName) { + return amend(BROWSER_NAME_OPTION, browserName); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsSkipLogCaptureOption.java similarity index 82% rename from src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java rename to src/main/java/io/appium/java_client/remote/options/SupportsSkipLogCaptureOption.java index 79c48e2a2..8da26009c 100644 --- a/src/main/java/io/appium/java_client/android/options/other/SupportsSkipLogCaptureOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsSkipLogCaptureOption.java @@ -14,10 +14,8 @@ * limitations under the License. */ -package io.appium.java_client.android.options.other; +package io.appium.java_client.remote.options; -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; import java.util.Optional; @@ -29,7 +27,7 @@ public interface SupportsSkipLogCaptureOption> extends String SKIP_LOG_CAPTURE_OPTION = "skipLogCapture"; /** - * Skips capturing logs such as logcat. + * Skips capturing system logs. * * @return self instance for chaining. */ @@ -38,7 +36,7 @@ default T skipLogCapture() { } /** - * Skips to start capturing logs such as logcat. It might improve network performance. + * Skips to start capturing system logs. It might improve network performance. * Log-related commands won't work if the capability is enabled. Defaults to false. * * @param value Set it to true in order to skip logcat capture. @@ -49,7 +47,7 @@ default T setSkipLogCapture(boolean value) { } /** - * Get whether to skip capturing logs such as logcat. + * Get whether to skip capturing system logs. * * @return True or false. */ diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java index 9b296adf3..42d696b58 100644 --- a/src/test/java/io/appium/java_client/android/FingerPrintTest.java +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -18,7 +18,7 @@ import static io.appium.java_client.AppiumBy.androidUIAutomator; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import org.junit.After; import org.junit.AfterClass; @@ -29,7 +29,6 @@ import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; import java.time.Duration; @@ -38,11 +37,11 @@ public class FingerPrintTest { private static AndroidDriver driver; private static void initDriver() { - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability("appPackage", "com.android.settings"); - capabilities.setCapability("appActivity", "Settings"); - driver = new AndroidDriver(service.getUrl(), capabilities); + UiAutomator2Options options = new UiAutomator2Options() + .setDeviceName("Android Emulator") + .setAppPackage("com.android.settings") + .setAppActivity("Settings"); + driver = new AndroidDriver(service.getUrl(), options); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(15)); } diff --git a/src/test/java/io/appium/java_client/android/IntentTest.java b/src/test/java/io/appium/java_client/android/IntentTest.java index 441af2a4e..ea10811e6 100644 --- a/src/test/java/io/appium/java_client/android/IntentTest.java +++ b/src/test/java/io/appium/java_client/android/IntentTest.java @@ -4,13 +4,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.openqa.selenium.By; -import org.openqa.selenium.remote.DesiredCapabilities; import java.util.function.Predicate; @@ -29,10 +28,10 @@ public class IntentTest { throw new RuntimeException("An appium server node is not started!"); } - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, intentExampleApk().toAbsolutePath().toString()); - driver = new AndroidDriver(service.getUrl(), capabilities); + UiAutomator2Options options = new UiAutomator2Options() + .setDeviceName("Android Emulator") + .setApp(intentExampleApk().toAbsolutePath().toString()); + driver = new AndroidDriver(service.getUrl(), options); } /** diff --git a/src/test/java/io/appium/java_client/ios/AppIOSTest.java b/src/test/java/io/appium/java_client/ios/AppIOSTest.java index 26551d91b..5aad73dfe 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/AppIOSTest.java @@ -1,14 +1,12 @@ package io.appium.java_client.ios; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.IOSMobileCapabilityType; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.BeforeClass; import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.remote.DesiredCapabilities; import java.net.URL; +import java.time.Duration; import static io.appium.java_client.TestResources.testAppZip; @@ -24,20 +22,16 @@ public static void beforeClass() throws Exception { throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!"); } - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, PLATFORM_VERSION); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, DEVICE_NAME); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - WDA_LAUNCH_TIMEOUT.toMillis()); - //sometimes environment has performance problems - capabilities.setCapability("commandTimeouts", "240000"); - capabilities.setCapability(MobileCapabilityType.APP, testAppZip().toAbsolutePath().toString()); + XCUITestOptions options = new XCUITestOptions() + .setDeviceName(DEVICE_NAME) + .setCommandTimeouts(Duration.ofSeconds(240)) + .setApp(testAppZip().toAbsolutePath().toString()) + .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); try { - driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); } catch (SessionNotCreatedException e) { - capabilities.setCapability("useNewWDA", true); - driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + options.useNewWDA(); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); } } } \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 999719551..74b1c8f62 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -16,13 +16,10 @@ package io.appium.java_client.ios; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.IOSMobileCapabilityType; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.BeforeClass; import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.remote.DesiredCapabilities; import java.io.IOException; import java.net.MalformedURLException; @@ -44,16 +41,14 @@ public static void beforeClass() throws IOException { throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!"); } - final DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, PLATFORM_VERSION); - capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, WDA_LAUNCH_TIMEOUT.toMillis()); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, DEVICE_NAME); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - capabilities.setCapability("commandTimeouts", "240000"); - capabilities.setCapability(MobileCapabilityType.APP, vodQaAppZip().toAbsolutePath().toString()); + XCUITestOptions options = new XCUITestOptions() + .setDeviceName(DEVICE_NAME) + .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) + .setCommandTimeouts(Duration.ofSeconds(240)) + .setApp(vodQaAppZip().toAbsolutePath().toString()); Supplier createDriver = () -> { try { - return new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + return new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); } catch (MalformedURLException e) { throw new RuntimeException(e); } @@ -63,7 +58,7 @@ public static void beforeClass() throws IOException { } catch (SessionNotCreatedException e) { // Sometimes WDA session creation freezes unexpectedly on CI: // https://dev.azure.com/srinivasansekar/java-client/_build/results?buildId=356&view=ms.vss-test-web.build-test-results-tab - capabilities.setCapability("useNewWDA", true); + options.useNewWDA(); driver = createDriver.get(); } } diff --git a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java index 122d30257..0dd44f2a6 100644 --- a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java @@ -16,13 +16,10 @@ package io.appium.java_client.ios; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.IOSMobileCapabilityType; +import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.BeforeClass; -import org.openqa.selenium.remote.DesiredCapabilities; import java.io.IOException; import java.net.URL; @@ -36,14 +33,11 @@ public class BaseSafariTest extends BaseIOSTest { throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!"); } - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.SAFARI); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, PLATFORM_VERSION); - //sometimes environment has performance problems - capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - WDA_LAUNCH_TIMEOUT.toMillis()); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, DEVICE_NAME); - driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), capabilities); + XCUITestOptions options = new XCUITestOptions() + .withBrowserName(MobileBrowserType.SAFARI) + .setDeviceName(DEVICE_NAME) + .setPlatformVersion(PLATFORM_VERSION) + .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); + driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java index 5f8564ccb..4afb89cd1 100644 --- a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java @@ -7,21 +7,23 @@ import io.appium.java_client.AppiumBy; import org.junit.Test; import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; public class IOSWebViewTest extends BaseIOSWebViewTest { + private static final Duration LOOKUP_TIMEOUT = Duration.ofSeconds(30); - @Test public void webViewPageTestCase() throws InterruptedException { - new WebDriverWait(driver, Duration.ofSeconds(30)) + @Test + public void webViewPageTestCase() throws InterruptedException { + new WebDriverWait(driver, LOOKUP_TIMEOUT) .until(ExpectedConditions.presenceOfElementLocated(By.id("login"))) .click(); - driver.findElement(AppiumBy.accessibilityId("webView")).click(); - new WebDriverWait(driver, Duration.ofSeconds(30)) + new WebDriverWait(driver, LOOKUP_TIMEOUT) + .until(ExpectedConditions.presenceOfElementLocated(AppiumBy.accessibilityId("webView"))) + .click(); + new WebDriverWait(driver, LOOKUP_TIMEOUT) .until(ExpectedConditions.presenceOfElementLocated(AppiumBy.accessibilityId("Webview"))); findAndSwitchToWebView(); - WebElement el = driver.findElement(By.partialLinkText("login")); - assertTrue(el.isDisplayed()); + assertTrue(driver.findElement(By.partialLinkText("login")).isDisplayed()); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java index 8c4b5cf30..d9f4b6707 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java @@ -19,10 +19,10 @@ import static java.time.Duration.ofSeconds; import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.pagefactory.AndroidFindBy; 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.Assert; @@ -30,7 +30,6 @@ 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.FindBys; @@ -44,7 +43,8 @@ public class MobileBrowserCompatibilityTest { private AppiumDriverLocalService service; - @AndroidFindBy(className = "someClass") @AndroidFindBy(xpath = "//someTag") + @AndroidFindBy(className = "someClass") + @AndroidFindBy(xpath = "//someTag") private RemoteWebElement btnG; //this element should be found by id = 'btnG' or name = 'btnG' @FindBy(name = "q") @@ -53,20 +53,20 @@ public class MobileBrowserCompatibilityTest { @AndroidFindBy(className = "someClass") @FindBys({@FindBy(className = "r"), @FindBy(tagName = "a")}) - private List - foundLinks; + private List foundLinks; /** * 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.BROWSER); - driver = new AndroidDriver(service.getUrl(), capabilities); + UiAutomator2Options options = new UiAutomator2Options() + .withBrowserName(MobileBrowserType.BROWSER) + .setDeviceName("Android Emulator"); + driver = new AndroidDriver(service.getUrl(), options); //This time out is set because test can be run on slow Android SDK emulator PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } @@ -74,7 +74,8 @@ public class MobileBrowserCompatibilityTest { /** * finishing. */ - @After public void tearDown() { + @After + public void tearDown() { if (driver != null) { driver.quit(); } @@ -84,7 +85,8 @@ public class MobileBrowserCompatibilityTest { } } - @Test public void test() { + @Test + public void test() { driver.get("https://www.google.com"); searchTextField.sendKeys("Hello"); diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index 48e4671b4..ea8a7c706 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -2,13 +2,6 @@ import static io.appium.java_client.TestResources.apiDemosApk; import static io.appium.java_client.TestUtils.getLocalIp4Address; -import static io.appium.java_client.remote.AndroidMobileCapabilityType.APP_ACTIVITY; -import static io.appium.java_client.remote.AndroidMobileCapabilityType.APP_PACKAGE; -import static io.appium.java_client.remote.AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE; -import static io.appium.java_client.remote.MobileCapabilityType.APP; -import static io.appium.java_client.remote.MobileCapabilityType.FULL_RESET; -import static io.appium.java_client.remote.MobileCapabilityType.NEW_COMMAND_TIMEOUT; -import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; import static io.appium.java_client.service.local.AppiumServiceBuilder.APPIUM_PATH; import static io.appium.java_client.service.local.flags.GeneralServerFlag.CALLBACK_ADDRESS; @@ -29,19 +22,21 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.android.options.UiAutomator2Options; import io.github.bonigarcia.wdm.WebDriverManager; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; -import org.openqa.selenium.remote.DesiredCapabilities; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.nio.file.Path; +import java.time.Duration; import java.util.ArrayList; import java.util.List; +@SuppressWarnings("ResultOfMethodCallIgnored") public class ServerBuilderTest { /** @@ -154,16 +149,15 @@ public void checkAbilityToStartServiceUsingFlags() { @Test public void checkAbilityToStartServiceUsingCapabilities() { - DesiredCapabilities caps = new DesiredCapabilities(); - caps.setCapability(PLATFORM_NAME, "Android"); - caps.setCapability(FULL_RESET, true); - caps.setCapability(NEW_COMMAND_TIMEOUT, 60); - caps.setCapability(APP_PACKAGE, "io.appium.android.apis"); - caps.setCapability(APP_ACTIVITY, ".view.WebView1"); - caps.setCapability(APP, apiDemosApk().toAbsolutePath().toString()); - caps.setCapability(CHROMEDRIVER_EXECUTABLE, chromeManager.getDownloadedDriverPath()); - - service = new AppiumServiceBuilder().withCapabilities(caps).build(); + UiAutomator2Options options = new UiAutomator2Options() + .fullReset() + .setNewCommandTimeout(Duration.ofSeconds(60)) + .setAppPackage("io.appium.android.apis") + .setAppActivity(".view.WebView1") + .setApp(apiDemosApk().toAbsolutePath().toString()) + .setChromedriverExecutable(chromeManager.getDownloadedDriverPath()); + + service = new AppiumServiceBuilder().withCapabilities(options).build(); service.start(); assertTrue(service.isRunning()); } @@ -172,25 +166,25 @@ public void checkAbilityToStartServiceUsingCapabilities() { public void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { File app = ROOT_TEST_PATH.resolve("ApiDemos-debug.apk").toFile(); - DesiredCapabilities caps = new DesiredCapabilities(); - caps.setCapability(PLATFORM_NAME, "Android"); - caps.setCapability(FULL_RESET, true); - caps.setCapability(NEW_COMMAND_TIMEOUT, 60); - caps.setCapability(APP_PACKAGE, "io.appium.android.apis"); - caps.setCapability(APP_ACTIVITY, ".view.WebView1"); - caps.setCapability(APP, app.getAbsolutePath()); - caps.setCapability("winPath", "C:\\selenium\\app.apk"); - caps.setCapability("unixPath", "/selenium/app.apk"); - caps.setCapability("quotes", "\"'"); - caps.setCapability("goog:chromeOptions", - ImmutableMap.of("env", ImmutableMap.of("test", "value"), "val2", 0)); - caps.setCapability(CHROMEDRIVER_EXECUTABLE, chromeManager.getDownloadedDriverPath()); + UiAutomator2Options options = new UiAutomator2Options() + .fullReset() + .setNewCommandTimeout(Duration.ofSeconds(60)) + .setAppPackage("io.appium.android.apis") + .setAppActivity(".view.WebView1") + .setApp(app.getAbsolutePath()) + .setChromedriverExecutable(chromeManager.getDownloadedDriverPath()) + .amend("winPath", "C:\\selenium\\app.apk") + .amend("unixPath", "/selenium/app.apk") + .amend("quotes", "\"'") + .setChromeOptions( + ImmutableMap.of("env", ImmutableMap.of("test", "value"), "val2", 0) + ); service = new AppiumServiceBuilder() .withArgument(CALLBACK_ADDRESS, testIP) .withArgument(SESSION_OVERRIDE) .withArgument(PRE_LAUNCH) - .withCapabilities(caps).build(); + .withCapabilities(options).build(); service.start(); assertTrue(service.isRunning()); } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java index 7f0bdf590..467d6c21f 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java @@ -28,15 +28,15 @@ import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.IOSMobileCapabilityType; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.github.bonigarcia.wdm.WebDriverManager; import org.junit.Test; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.Platform; import java.time.Duration; @@ -121,24 +121,20 @@ public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { @Test public void startingIOSAppWithCapabilitiesOnlyTest() { - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - //sometimes environment has performance problems - capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - capabilities.setCapability(MobileCapabilityType.APP, uiCatalogAppZip().toAbsolutePath().toString()); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - - IOSDriver driver = new IOSDriver(capabilities); + XCUITestOptions options = new XCUITestOptions() + .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) + .setDeviceName(BaseIOSTest.DEVICE_NAME) + .setApp(uiCatalogAppZip().toAbsolutePath().toString()) + .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); + IOSDriver driver = new IOSDriver(options); try { - Capabilities caps = driver.getCapabilities(); + XCUITestOptions caps = new XCUITestOptions(driver.getCapabilities()); - assertEquals(AutomationName.IOS_XCUI_TEST, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); - assertEquals(MobilePlatform.IOS, caps.getCapability(MobileCapabilityType.PLATFORM_NAME)); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); - assertEquals(BaseIOSTest.PLATFORM_VERSION, caps.getCapability(MobileCapabilityType.PLATFORM_VERSION)); - assertEquals(uiCatalogAppZip().toAbsolutePath().toString(), caps.getCapability(MobileCapabilityType.APP)); + assertEquals(AutomationName.IOS_XCUI_TEST, caps.getAutomationName().orElse(null)); + assertEquals(Platform.IOS, caps.getPlatformName()); + assertNotNull(caps.getDeviceName().orElse(null)); + assertEquals(BaseIOSTest.PLATFORM_VERSION, caps.getPlatformVersion().orElse(null)); + assertEquals(uiCatalogAppZip().toAbsolutePath().toString(), caps.getApp().orElse(null)); } finally { driver.quit(); } @@ -147,20 +143,17 @@ public void startingIOSAppWithCapabilitiesOnlyTest() { @Test public void startingIOSAppWithCapabilitiesAndServiceTest() { - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - capabilities.setCapability(MobileCapabilityType.APP, uiCatalogAppZip().toAbsolutePath().toString()); - capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - //sometimes environment has performance problems - capabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); + XCUITestOptions options = new XCUITestOptions() + .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) + .setDeviceName(BaseIOSTest.DEVICE_NAME) + .setApp(uiCatalogAppZip().toAbsolutePath().toString()) + .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); - IOSDriver driver = new IOSDriver(builder, capabilities); + IOSDriver driver = new IOSDriver(builder, options); try { Capabilities caps = driver.getCapabilities(); assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) @@ -173,27 +166,24 @@ public void startingIOSAppWithCapabilitiesAndServiceTest() { @Test public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { - DesiredCapabilities serverCapabilities = new DesiredCapabilities(); - serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, BaseIOSTest.DEVICE_NAME); - serverCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); - serverCapabilities.setCapability(IOSMobileCapabilityType.WDA_LAUNCH_TIMEOUT, - BaseIOSTest.WDA_LAUNCH_TIMEOUT.toMillis()); //some environment is too slow - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, BaseIOSTest.PLATFORM_VERSION); - serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); + XCUITestOptions serverOptions = new XCUITestOptions() + .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) + .setDeviceName(BaseIOSTest.DEVICE_NAME) + .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); - DesiredCapabilities clientCapabilities = new DesiredCapabilities(); - clientCapabilities.setCapability(MobileCapabilityType.APP, uiCatalogAppZip().toAbsolutePath().toString()); + XCUITestOptions clientOptions = new XCUITestOptions() + .setApp(uiCatalogAppZip().toAbsolutePath().toString()); AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) - .withArgument(GeneralServerFlag.STRICT_CAPS).withCapabilities(serverCapabilities); + .withArgument(GeneralServerFlag.STRICT_CAPS) + .withCapabilities(serverOptions); - IOSDriver driver = new IOSDriver(builder, clientCapabilities); + IOSDriver driver = new IOSDriver(builder, clientOptions); try { - Capabilities caps = driver.getCapabilities(); - assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) - .toString().equalsIgnoreCase(MobilePlatform.IOS)); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + XCUITestOptions caps = new XCUITestOptions(driver.getCapabilities()); + assertEquals(Platform.IOS, caps.getPlatformName()); + assertNotNull(caps.getDeviceName().orElse(null)); assertFalse(driver.isBrowser()); } finally { driver.quit(); From d029bc9389925c7dc0829406a71d0677b44ce08b Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 29 Oct 2021 11:15:32 +0300 Subject: [PATCH 019/501] chore: deprecate Windows UIAutomation selector (#1562) --- .../java/io/appium/java_client/AppiumBy.java | 16 ------------- .../java/io/appium/java_client/MobileBy.java | 23 ++++++++++++++++--- .../pagefactory/bys/builder/Strategies.java | 21 ++++++++++------- .../tests/windows/WindowsWidgetTest.java | 2 +- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 6d8c1543d..0f578b0b0 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -164,15 +164,6 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) { return new ByIosNsPredicate(iOSNsPredicateString); } - /** - * The Windows UIAutomation selector. - * @param windowsAutomation The element name in the Windows UIAutomation selector - * @return an instance of {@link AppiumBy.ByWindowsAutomation} - */ - public static By windowsAutomation(final String windowsAutomation) { - return new ByWindowsAutomation(windowsAutomation); - } - public static class ByAccessibilityId extends AppiumBy implements Serializable { public ByAccessibilityId(String accessibilityId) { @@ -242,13 +233,6 @@ protected ByIosNsPredicate(String locatorString) { super("-ios predicate string", locatorString, "iOSNsPredicate"); } } - - public static class ByWindowsAutomation extends AppiumBy implements Serializable { - - protected ByWindowsAutomation(String locatorString) { - super("-windows uiautomation", locatorString, "windowsAutomation"); - } - } } diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index 3d36a1aae..65f382ec7 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -16,6 +16,8 @@ package io.appium.java_client; +import java.io.Serializable; + import org.openqa.selenium.By; /** @@ -107,6 +109,17 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) { return new ByIosNsPredicate(iOSNsPredicateString); } + /** + * The Windows UIAutomation selector. + * @deprecated Not supported on the server side. + * @param windowsAutomation The element name in the Windows UIAutomation selector + * @return an instance of {@link MobileBy.ByWindowsAutomation} + */ + @Deprecated + public static By windowsAutomation(final String windowsAutomation) { + return new ByWindowsAutomation(windowsAutomation); + } + /** * This locator strategy is available in Espresso Driver mode. * @deprecated Use {@link AppiumBy#androidViewTag(String)} instead. @@ -261,13 +274,17 @@ protected ByIosNsPredicate(String locatorString) { /** * The Windows UIAutomation selector. - * @deprecated Use {@link AppiumBy.ByWindowsAutomation} instead. + * @deprecated Not supported on the server side. */ @Deprecated - public static class ByWindowsAutomation extends AppiumBy.ByWindowsAutomation { + public static class ByWindowsAutomation extends MobileBy implements Serializable { protected ByWindowsAutomation(String locatorString) { - super(locatorString); + super("-windows uiautomation", locatorString, "windowsAutomation"); + } + + @Override public String toString() { + return "By.windowsAutomation: " + getRemoteParameters().value(); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 03382dbcb..7b1d13ab1 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -16,18 +16,19 @@ package io.appium.java_client.pagefactory.bys.builder; -import io.appium.java_client.AppiumBy; -import io.appium.java_client.pagefactory.AndroidBy; -import io.appium.java_client.pagefactory.AndroidFindBy; - -import org.openqa.selenium.By; - import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import org.openqa.selenium.By; + +import io.appium.java_client.AppiumBy; +import io.appium.java_client.MobileBy; +import io.appium.java_client.pagefactory.AndroidBy; +import io.appium.java_client.pagefactory.AndroidFindBy; + enum Strategies { BYUIAUTOMATOR("uiAutomator") { @Override By getBy(Annotation annotation) { @@ -84,10 +85,14 @@ enum Strategies { .partialLinkText(getValue(annotation, this)); } }, + /** + * The Windows UIAutomation strategy. + * @deprecated Not supported on the server side. + */ + @Deprecated BYWINDOWSAUTOMATION("windowsAutomation") { @Override By getBy(Annotation annotation) { - return AppiumBy - .windowsAutomation(getValue(annotation, this)); + return MobileBy.windowsAutomation(getValue(annotation, this)); } }, BY_CLASS_CHAIN("iOSClassChain") { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java index 8fbc23fd4..fbd9da9a6 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.pagefactory_tests.widget.tests.windows; -import static io.appium.java_client.AppiumBy.windowsAutomation; +import static io.appium.java_client.MobileBy.windowsAutomation; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.AnnotatedWindowsWidget.WINDOWS_ROOT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget.WINDOWS_SUB_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_DEFAULT_WIDGET_LOCATOR; From b6cab92892954fee72acbade984ac4e14c9ff3ee Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 29 Oct 2021 12:56:35 +0200 Subject: [PATCH 020/501] feat: Add Espresso options (#1563) --- .../android/options/BaseMapOptionData.java | 77 ++++ .../android/options/EspressoOptions.java | 211 +++++++++ .../android/options/UiAutomator2Options.java | 4 +- .../android/options/app/ActivityOptions.java | 53 +++ .../android/options/app/IntentOptions.java | 421 ++++++++++++++++++ .../app/SupportsActivityOptionsOption.java | 53 +++ ...ava => SupportsAppWaitDurationOption.java} | 2 +- .../app/SupportsIntentOptionsOption.java | 53 +++ .../options/localization/AppLocale.java | 93 ++++ .../localization/SupportsAppLocaleOption.java | 56 +++ .../options/server/EspressoBuildConfig.java | 293 ++++++++++++ .../SupportsEspressoBuildConfigOption.java | 69 +++ ...ortsEspressoServerLaunchTimeoutOption.java | 53 +++ .../SupportsForceEspressoRebuildOption.java | 63 +++ .../server/SupportsShowGradleLogOption.java | 61 +++ .../SupportsSkipServerInstallationOption.java | 6 +- .../server/SupportsSystemPortOption.java | 5 +- .../options/SupportsEventTimingsOption.java | 2 +- .../android/AndroidViewMatcherTest.java | 4 +- .../java_client/android/BaseAndroidTest.java | 2 +- .../java_client/android/BaseEspressoTest.java | 15 +- 21 files changed, 1576 insertions(+), 20 deletions(-) create mode 100644 src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java create mode 100644 src/main/java/io/appium/java_client/android/options/EspressoOptions.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/IntentOptions.java create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java rename src/main/java/io/appium/java_client/android/options/app/{SupportsAppDurationOption.java => SupportsAppWaitDurationOption.java} (95%) create mode 100644 src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/localization/AppLocale.java create mode 100644 src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsEspressoServerLaunchTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsForceEspressoRebuildOption.java create mode 100644 src/main/java/io/appium/java_client/android/options/server/SupportsShowGradleLogOption.java diff --git a/src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java b/src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java new file mode 100644 index 000000000..ce473a607 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java @@ -0,0 +1,77 @@ +/* + * 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.options; + +import com.google.gson.GsonBuilder; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public abstract class BaseMapOptionData> { + protected Map options; + + public BaseMapOptionData() { + } + + public BaseMapOptionData(Map options) { + this.options = options; + } + + /** + * Sets the given value on the data object. + * + * @param key Key name. + * @param value The actual value to set. + * @return self instance for chaining. + */ + public T assignOptionValue(String key, Object value) { + if (options == null) { + options = new HashMap<>(); + } + options.put(key, value); + //noinspection unchecked + return (T) this; + } + + /** + * Retrieves a value with the given name from a data object. + * This method does not perform any type transformation, but rather + * just tries to cast the received value to the given type, so + * be careful while providing a very specific result type value to + * not get a type cast error. + * + * @param name Key name. + * @param The expected value type. + * @return The actual value. + */ + public Optional getOptionValue(String name) { + //noinspection unchecked + return Optional.ofNullable(options) + .map(opts -> (R) opts.getOrDefault(name, null)); + } + + public Map toMap() { + return Optional.ofNullable(options).orElseGet(Collections::emptyMap); + } + + @Override + public String toString() { + return new GsonBuilder().create().toJson(toMap()); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java new file mode 100644 index 000000000..6d3df918d --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java @@ -0,0 +1,211 @@ +/* + * 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.options; + +import io.appium.java_client.android.options.adb.SupportsAdbExecTimeoutOption; +import io.appium.java_client.android.options.adb.SupportsAdbPortOption; +import io.appium.java_client.android.options.adb.SupportsAllowDelayAdbOption; +import io.appium.java_client.android.options.adb.SupportsBuildToolsVersionOption; +import io.appium.java_client.android.options.adb.SupportsClearDeviceLogsOnStartOption; +import io.appium.java_client.android.options.adb.SupportsIgnoreHiddenApiPolicyErrorOption; +import io.appium.java_client.android.options.adb.SupportsLogcatFilterSpecsOption; +import io.appium.java_client.android.options.adb.SupportsLogcatFormatOption; +import io.appium.java_client.android.options.adb.SupportsMockLocationAppOption; +import io.appium.java_client.android.options.adb.SupportsRemoteAdbHostOption; +import io.appium.java_client.android.options.adb.SupportsSkipLogcatCaptureOption; +import io.appium.java_client.android.options.adb.SupportsSuppressKillServerOption; +import io.appium.java_client.android.options.app.SupportsActivityOptionsOption; +import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption; +import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption; +import io.appium.java_client.android.options.app.SupportsAppActivityOption; +import io.appium.java_client.android.options.app.SupportsIntentOptionsOption; +import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; +import io.appium.java_client.android.options.app.SupportsAppPackageOption; +import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption; +import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption; +import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption; +import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption; +import io.appium.java_client.android.options.app.SupportsRemoteAppsCacheLimitOption; +import io.appium.java_client.android.options.app.SupportsUninstallOtherPackagesOption; +import io.appium.java_client.android.options.avd.SupportsAvdArgsOption; +import io.appium.java_client.android.options.avd.SupportsAvdEnvOption; +import io.appium.java_client.android.options.avd.SupportsAvdLaunchTimeoutOption; +import io.appium.java_client.android.options.avd.SupportsAvdOption; +import io.appium.java_client.android.options.avd.SupportsAvdReadyTimeoutOption; +import io.appium.java_client.android.options.avd.SupportsGpsEnabledOption; +import io.appium.java_client.android.options.avd.SupportsNetworkSpeedOption; +import io.appium.java_client.android.options.context.SupportsAutoWebviewTimeoutOption; +import io.appium.java_client.android.options.context.SupportsChromeLoggingPrefsOption; +import io.appium.java_client.android.options.context.SupportsChromeOptionsOption; +import io.appium.java_client.android.options.context.SupportsChromedriverArgsOption; +import io.appium.java_client.android.options.context.SupportsChromedriverChromeMappingFileOption; +import io.appium.java_client.android.options.context.SupportsChromedriverDisableBuildCheckOption; +import io.appium.java_client.android.options.context.SupportsChromedriverExecutableDirOption; +import io.appium.java_client.android.options.context.SupportsChromedriverExecutableOption; +import io.appium.java_client.android.options.context.SupportsChromedriverPortOption; +import io.appium.java_client.android.options.context.SupportsChromedriverPortsOption; +import io.appium.java_client.android.options.context.SupportsChromedriverUseSystemExecutableOption; +import io.appium.java_client.android.options.context.SupportsEnsureWebviewsHavePagesOption; +import io.appium.java_client.android.options.context.SupportsExtractChromeAndroidPackageFromContextNameOption; +import io.appium.java_client.android.options.context.SupportsNativeWebScreenshotOption; +import io.appium.java_client.android.options.context.SupportsRecreateChromeDriverSessionsOption; +import io.appium.java_client.android.options.context.SupportsShowChromedriverLogOption; +import io.appium.java_client.android.options.context.SupportsWebviewDevtoolsPortOption; +import io.appium.java_client.android.options.localization.SupportsAppLocaleOption; +import io.appium.java_client.android.options.localization.SupportsLocaleScriptOption; +import io.appium.java_client.android.options.locking.SupportsSkipUnlockOption; +import io.appium.java_client.android.options.locking.SupportsUnlockKeyOption; +import io.appium.java_client.android.options.locking.SupportsUnlockStrategyOption; +import io.appium.java_client.android.options.locking.SupportsUnlockSuccessTimeoutOption; +import io.appium.java_client.android.options.locking.SupportsUnlockTypeOption; +import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption; +import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption; +import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption; +import io.appium.java_client.android.options.server.SupportsEspressoServerLaunchTimeoutOption; +import io.appium.java_client.android.options.server.SupportsForceEspressoRebuildOption; +import io.appium.java_client.android.options.server.SupportsShowGradleLogOption; +import io.appium.java_client.android.options.server.SupportsSkipServerInstallationOption; +import io.appium.java_client.android.options.server.SupportsSystemPortOption; +import io.appium.java_client.android.options.signing.SupportsKeystoreOptions; +import io.appium.java_client.android.options.signing.SupportsNoSignOption; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAppOption; +import io.appium.java_client.remote.options.SupportsAutoWebViewOption; +import io.appium.java_client.remote.options.SupportsDeviceNameOption; +import io.appium.java_client.remote.options.SupportsIsHeadlessOption; +import io.appium.java_client.remote.options.SupportsLanguageOption; +import io.appium.java_client.remote.options.SupportsLocaleOption; +import io.appium.java_client.remote.options.SupportsOrientationOption; +import io.appium.java_client.remote.options.SupportsOtherAppsOption; +import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption; +import io.appium.java_client.remote.options.SupportsUdidOption; +import org.openqa.selenium.Capabilities; + +import java.util.Map; + +/** + * https://github.com/appium/appium-espresso-driver#capabilities + */ +public class EspressoOptions extends BaseOptions implements + // General options: https://github.com/appium/appium-uiautomator2-driver#general + SupportsDeviceNameOption, + SupportsUdidOption, + // Driver/Server options: https://github.com/appium/appium-uiautomator2-driver#driverserver + SupportsSystemPortOption, + SupportsSkipServerInstallationOption, + SupportsEspressoServerLaunchTimeoutOption, + SupportsForceEspressoRebuildOption, + SupportsShowGradleLogOption, + SupportsOrientationOption, + // App options: https://github.com/appium/appium-uiautomator2-driver#app + SupportsAppOption, + SupportsAppPackageOption, + SupportsAppActivityOption, + SupportsAppWaitActivityOption, + SupportsAppWaitPackageOption, + SupportsAppWaitDurationOption, + SupportsAndroidInstallTimeoutOption, + SupportsIntentOptionsOption, + SupportsActivityOptionsOption, + SupportsAutoGrantPermissionsOption, + SupportsOtherAppsOption, + SupportsUninstallOtherPackagesOption, + SupportsAllowTestPackagesOption, + SupportsRemoteAppsCacheLimitOption, + SupportsEnforceAppInstallOption, + // App localization options: https://github.com/appium/appium-uiautomator2-driver#app-localization + SupportsLocaleScriptOption, + SupportsLanguageOption, + SupportsLocaleOption, + SupportsAppLocaleOption, + // ADB options: https://github.com/appium/appium-uiautomator2-driver#adb + SupportsAdbPortOption, + SupportsRemoteAdbHostOption, + SupportsAdbExecTimeoutOption, + SupportsClearDeviceLogsOnStartOption, + SupportsBuildToolsVersionOption, + SupportsSkipLogcatCaptureOption, + SupportsSuppressKillServerOption, + SupportsIgnoreHiddenApiPolicyErrorOption, + SupportsMockLocationAppOption, + SupportsLogcatFormatOption, + SupportsLogcatFilterSpecsOption, + SupportsAllowDelayAdbOption, + // AVD options: https://github.com/appium/appium-uiautomator2-driver#emulator-android-virtual-device + SupportsAvdOption, + SupportsAvdLaunchTimeoutOption, + SupportsAvdReadyTimeoutOption, + SupportsAvdArgsOption, + SupportsAvdEnvOption, + SupportsNetworkSpeedOption, + SupportsGpsEnabledOption, + SupportsIsHeadlessOption, + // App signing options: https://github.com/appium/appium-uiautomator2-driver#app-signing + SupportsKeystoreOptions, + SupportsNoSignOption, + // Device locking options: https://github.com/appium/appium-uiautomator2-driver#device-locking + SupportsSkipUnlockOption, + SupportsUnlockTypeOption, + SupportsUnlockKeyOption, + SupportsUnlockStrategyOption, + SupportsUnlockSuccessTimeoutOption, + // MJPEG options: https://github.com/appium/appium-uiautomator2-driver#mjpeg + SupportsMjpegServerPortOption, + SupportsMjpegScreenshotUrlOption, + // Web Context options: https://github.com/appium/appium-uiautomator2-driver#web-context + SupportsAutoWebViewOption, + SupportsWebviewDevtoolsPortOption, + SupportsEnsureWebviewsHavePagesOption, + SupportsChromedriverPortOption, + SupportsChromedriverPortsOption, + SupportsChromedriverArgsOption, + SupportsChromedriverExecutableOption, + SupportsChromedriverExecutableDirOption, + SupportsChromedriverChromeMappingFileOption, + SupportsChromedriverUseSystemExecutableOption, + SupportsChromedriverDisableBuildCheckOption, + SupportsAutoWebviewTimeoutOption, + SupportsRecreateChromeDriverSessionsOption, + SupportsNativeWebScreenshotOption, + SupportsExtractChromeAndroidPackageFromContextNameOption, + SupportsShowChromedriverLogOption, + SupportsChromeOptionsOption, + SupportsChromeLoggingPrefsOption, + // Other options: https://github.com/appium/appium-uiautomator2-driver#other + SupportsDisableSuppressAccessibilityServiceOption, + SupportsSkipLogCaptureOption { + public EspressoOptions() { + setCommonOptions(); + } + + public EspressoOptions(Capabilities source) { + super(source); + setCommonOptions(); + } + + public EspressoOptions(Map source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setPlatformName(MobilePlatform.ANDROID); + setAutomationName(AutomationName.ESPRESSO); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index dc4b7a74c..14eddf9eb 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -31,7 +31,7 @@ import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption; import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption; import io.appium.java_client.android.options.app.SupportsAppActivityOption; -import io.appium.java_client.android.options.app.SupportsAppDurationOption; +import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; import io.appium.java_client.android.options.app.SupportsAppPackageOption; import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption; import io.appium.java_client.android.options.app.SupportsAppWaitForLaunchOption; @@ -130,7 +130,7 @@ public class UiAutomator2Options extends BaseOptions implem SupportsAppActivityOption, SupportsAppWaitActivityOption, SupportsAppWaitPackageOption, - SupportsAppDurationOption, + SupportsAppWaitDurationOption, SupportsAndroidInstallTimeoutOption, SupportsAppWaitForLaunchOption, SupportsIntentCategoryOption, diff --git a/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java b/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java new file mode 100644 index 000000000..e0cc553a0 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java @@ -0,0 +1,53 @@ +/* + * 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.options.app; + +import io.appium.java_client.android.options.BaseMapOptionData; + +import java.util.Map; +import java.util.Optional; + +public class ActivityOptions extends BaseMapOptionData { + public ActivityOptions() { + super(); + } + + public ActivityOptions(Map options) { + super(options); + } + + /** + * Display id which you want to assign to launch the main app activity on. + * This might be useful if the device under test supports multiple displays. + * + * @param id Display identifier. + * @return self instance for chaining. + */ + public ActivityOptions withLaunchDisplayId(int id) { + return assignOptionValue("launchDisplayId", id); + } + + /** + * Get display id which you want to assign to launch the main app activity on. + * + * @return Display identifier. + */ + public Optional getLaunchDisplayId() { + Optional result = getOptionValue("launchDisplayId"); + return result.map((v) -> Integer.parseInt(String.valueOf(v))); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java new file mode 100644 index 000000000..2ba619aac --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java @@ -0,0 +1,421 @@ +/* + * 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.options.app; + +import io.appium.java_client.android.options.BaseMapOptionData; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class IntentOptions extends BaseMapOptionData { + public IntentOptions() { + super(); + } + + public IntentOptions(Map options) { + super(options); + } + + /** + * An intent action name. Application-specific actions should be prefixed with + * the vendor's package name. + * + * @param action E.g. ACTION_MAIN. + * @return self instance for chaining. + */ + public IntentOptions withAction(String action) { + return assignOptionValue("action", action); + } + + /** + * Get the action name. + * + * @return Action name. + */ + public Optional getAction() { + return getOptionValue("action"); + } + + /** + * Set an intent data URI. + * + * @param data E.g. content://contacts/people/1. + * @return self instance for chaining. + */ + public IntentOptions withData(String data) { + return assignOptionValue("data", data); + } + + /** + * Get intent data URI. + * + * @return Intent data URI. + */ + public Optional getData() { + return getOptionValue("data"); + } + + /** + * Intent MIME type. + * + * @param type E.g. image/png. + * @return self instance for chaining. + */ + public IntentOptions withType(String type) { + return assignOptionValue("type", type); + } + + /** + * Get an intent type. + * + * @return Intent type. + */ + public Optional getType() { + return getOptionValue("type"); + } + + /** + * Set intent categories. + * + * @param categories One or more comma-separated Intent categories. + * @return self instance for chaining. + */ + public IntentOptions withCategories(String categories) { + return assignOptionValue("categories", categories); + } + + /** + * Get intent categories. + * + * @return Intent categories. + */ + public Optional getCategories() { + return getOptionValue("categories"); + } + + /** + * Set intent component name with package name prefix + * to create an explicit intent. + * + * @param component E.g. com.example.app/.ExampleActivity. + * @return self instance for chaining. + */ + public IntentOptions withComponent(String component) { + return assignOptionValue("component", component); + } + + /** + * Get intent component name. + * + * @return Intent component name. + */ + public Optional getComponent() { + return getOptionValue("component"); + } + + /** + * Single-string value, which represents intent flags set encoded into + * an integer. Could also be provided in hexadecimal format. Check + * https://developer.android.com/reference/android/content/Intent.html#setFlags(int) + * for more details. + * + * @param intFlags E.g. 0x0F. + * @return self instance for chaining. + */ + public IntentOptions withIntFlags(String intFlags) { + return assignOptionValue("intFlags", intFlags); + } + + /** + * Get intent flags. + * + * @return Intent flags encoded into a hexadecimal value. + */ + public Optional getIntFlags() { + return getOptionValue("intFlags"); + } + + /** + * Comma-separated string of intent flag names. + * + * @param flags E.g. 'ACTIVITY_CLEAR_TASK' (the 'FLAG_' prefix is optional). + * @return self instance for chaining. + */ + public IntentOptions withFlags(String flags) { + return assignOptionValue("flags", flags); + } + + /** + * Get intent flag names. + * + * @return Comma-separated string of intent flag names. + */ + public Optional getFlags() { + return getOptionValue("flags"); + } + + /** + * The name of a class inside of the application package that + * will be used as the component for this Intent. + * + * @param className E.g. com.example.app.MainActivity. + * @return self instance for chaining. + */ + public IntentOptions withClassName(String className) { + return assignOptionValue("className", className); + } + + /** + * Get class name. + * + * @return Class name. + */ + public Optional getClassName() { + return getOptionValue("className"); + } + + /** + * Intent string parameters. + * + * @param es Map, where the key is arg parameter name and value is its string value. + * @return self instance for chaining. + */ + public IntentOptions withEs(Map es) { + return assignOptionValue("es", es); + } + + /** + * Get intent string parameters. + * + * @return Intent string parameters mapping. + */ + public Optional> getEs() { + return getOptionValue("es"); + } + + /** + * Intent null parameters. + * + * @param esn List, where keys are parameter names. + * @return self instance for chaining. + */ + public IntentOptions withEsn(List esn) { + return assignOptionValue("esn", esn); + } + + /** + * Get intent null parameters. + * + * @return Intent null parameters. + */ + public Optional> getEsn() { + return getOptionValue("esn"); + } + + /** + * Intent boolean parameters. + * + * @param ez Map, where keys are parameter names and values are booleans. + * @return self instance for chaining. + */ + public IntentOptions withEz(Map ez) { + return assignOptionValue("ez", ez); + } + + /** + * Get intent boolean parameters. + * + * @return Intent boolean parameters. + */ + public Optional> getEz() { + return getOptionValue("ez"); + } + + /** + * Intent integer parameters. + * + * @param ei Map, where keys are parameter names and values are integers. + * @return self instance for chaining. + */ + public IntentOptions withEi(Map ei) { + return assignOptionValue("ei", ei); + } + + private Map convertMapValues(Map map, Function converter) { + return map.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, (entry) -> converter.apply(String.valueOf(entry.getValue()))) + ); + } + + /** + * Get intent integer parameters. + * + * @return Intent integer parameters. + */ + public Optional> getEi() { + Optional> value = getOptionValue("ei"); + return value.map((v) -> convertMapValues(v, Integer::parseInt)); + } + + /** + * Intent long parameters. + * + * @param el Map, where keys are parameter names and values are long numbers. + * @return self instance for chaining. + */ + public IntentOptions withEl(Map el) { + return assignOptionValue("el", el); + } + + /** + * Get intent long parameters. + * + * @return Intent long parameters. + */ + public Optional> getEl() { + Optional> value = getOptionValue("el"); + return value.map((v) -> convertMapValues(v, Long::parseLong)); + } + + /** + * Intent float parameters. + * + * @param ef Map, where keys are parameter names and values are float numbers. + * @return self instance for chaining. + */ + public IntentOptions withEf(Map ef) { + return assignOptionValue("ef", ef); + } + + /** + * Get intent float parameters. + * + * @return Intent float parameters. + */ + public Optional> getEf() { + Optional> value = getOptionValue("ef"); + return value.map((v) -> convertMapValues(v, Float::parseFloat)); + } + + /** + * Intent URI-data parameters. + * + * @param eu Map, where keys are parameter names and values are valid URIs. + * @return self instance for chaining. + */ + public IntentOptions withEu(Map eu) { + return assignOptionValue("eu", eu); + } + + /** + * Get intent URI parameters. + * + * @return Intent URI parameters. + */ + public Optional> getEu() { + return getOptionValue("eu"); + } + + /** + * Intent component name parameters. + * + * @param ecn Map, where keys are parameter names and values are valid component names. + * @return self instance for chaining. + */ + public IntentOptions withEcn(Map ecn) { + return assignOptionValue("ecn", ecn); + } + + /** + * Get intent component name parameters. + * + * @return Intent component name parameters. + */ + public Optional> getEcn() { + return getOptionValue("ecn"); + } + + private static Map mergeValues(Map map) { + return map.entrySet().stream() + .collect( + Collectors.toMap(Map.Entry::getKey, (entry) -> ((List) entry.getValue()).stream() + .map(String::valueOf) + .collect(Collectors.joining(","))) + ); + } + + /** + * Intent integer array parameters. + * + * @param eia Map, where keys are parameter names and values are lists of integers. + * @return self instance for chaining. + */ + public IntentOptions withEia(Map> eia) { + return assignOptionValue("eia", mergeValues(eia)); + } + + /** + * Get intent integer array parameters. + * + * @return Intent integer array parameters. + */ + public Optional> getEia() { + return getOptionValue("eia"); + } + + /** + * Intent long array parameters. + * + * @param ela Map, where keys are parameter names and values are lists of long numbers. + * @return self instance for chaining. + */ + public IntentOptions withEla(Map> ela) { + return assignOptionValue("ela", mergeValues(ela)); + } + + /** + * Get intent long array parameters. + * + * @return Intent long array parameters. + */ + public Optional> getEla() { + return getOptionValue("ela"); + } + + /** + * Intent float array parameters. + * + * @param efa Map, where keys are parameter names and values are lists of float numbers. + * @return self instance for chaining. + */ + public IntentOptions withEfa(Map> efa) { + return assignOptionValue("efa", mergeValues(efa)); + } + + /** + * Get intent float array parameters. + * + * @return Intent float array parameters. + */ + public Optional> getEfa() { + return getOptionValue("efa"); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java new file mode 100644 index 000000000..393ee51c5 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsActivityOptionsOption> extends + Capabilities, CanSetCapability { + String ACTIVITY_OPTIONS_OPTION = "activityOptions"; + + /** + * The mapping of custom options for the main app activity that is going to + * be started. Check + * https://github.com/appium/appium-espresso-driver#activity-options + * for more details. + * + * @param options Activity options. + * @return self instance for chaining. + */ + default T setActivityOptions(ActivityOptions options) { + return amend(ACTIVITY_OPTIONS_OPTION, options.toMap()); + } + + /** + * Get activity options. + * + * @return Activity options. + */ + default Optional getActivityOptions() { + //noinspection unchecked + return Optional.ofNullable(getCapability(ACTIVITY_OPTIONS_OPTION)) + .map((v) -> new ActivityOptions((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitDurationOption.java similarity index 95% rename from src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java rename to src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitDurationOption.java index 3a3bce7b7..77039f70d 100644 --- a/src/main/java/io/appium/java_client/android/options/app/SupportsAppDurationOption.java +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAppWaitDurationOption.java @@ -25,7 +25,7 @@ import static io.appium.java_client.internal.CapabilityHelpers.toDuration; -public interface SupportsAppDurationOption> extends +public interface SupportsAppWaitDurationOption> extends Capabilities, CanSetCapability { String APP_WAIT_DURATION_OPTION = "appWaitDuration"; diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java new file mode 100644 index 000000000..91c2b49a2 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.app; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsIntentOptionsOption> extends + Capabilities, CanSetCapability { + String INTENT_OPTIONS_OPTION = "intentOptions"; + + /** + * The mapping of custom options for the intent that is going to be passed + * to the main app activity. Check + * https://github.com/appium/appium-espresso-driver#intent-options + * for more details. + * + * @param options Intent options. + * @return self instance for chaining. + */ + default T setIntentOptions(IntentOptions options) { + return amend(INTENT_OPTIONS_OPTION, options.toMap()); + } + + /** + * Get intent options. + * + * @return Intent options. + */ + default Optional getIntentOptions() { + //noinspection unchecked + return Optional.ofNullable(getCapability(INTENT_OPTIONS_OPTION)) + .map((v) -> new IntentOptions((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java b/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java new file mode 100644 index 000000000..d7d0209d0 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java @@ -0,0 +1,93 @@ +/* + * 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.options.localization; + +import io.appium.java_client.android.options.BaseMapOptionData; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class AppLocale extends BaseMapOptionData { + public AppLocale() { + super(); + } + + public AppLocale(Map options) { + super(options); + } + + /** + * Language identifier. See + * https://github.com/libyal/libfwnt/wiki/Language-Code-identifiers#language-identifiers + * for the list of available values. + * + * @param lang Language identifier, for example "zh". + * @return self instance for chaining. + */ + public AppLocale withLanguage(String lang) { + return assignOptionValue("language", lang); + } + + /** + * Get the language identifier. + * + * @return Language identifier. + */ + public Optional getLanguage() { + return getOptionValue("language"); + } + + /** + * Allows to set a country identifier. + * + * @param country Country identifier, for example "CN". + * @return self instance for chaining. + */ + public AppLocale withCountry(String country) { + return assignOptionValue("country", country); + } + + /** + * Get the country identifier. + * + * @return Country identifier. + */ + public Optional getCountry() { + return getOptionValue("country"); + } + + /** + * Allows to set an optional language variant value. + * + * @param variant Language variant, for example "Hans". + * @return self instance for chaining. + */ + public AppLocale withVariant(String variant) { + return assignOptionValue("variant", variant); + } + + /** + * Get the language variant. + * + * @return Language variant. + */ + public Optional getVariant() { + return getOptionValue("variant"); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java b/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java new file mode 100644 index 000000000..40447d749 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java @@ -0,0 +1,56 @@ +/* + * 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.options.localization; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsAppLocaleOption> extends + Capabilities, CanSetCapability { + String APP_LOCALE_OPTION = "appLocale"; + + /** + * Sets the locale for the app under test. The main difference between this option + * and the above ones is that this option only changes the locale for the application + * under test and does not affect other parts of the system. Also, it only uses + * public APIs for its purpose. See + * https://github.com/libyal/libfwnt/wiki/Language-Code-identifiers to get the + * list of available language abbreviations. + * Example: {"language": "zh", "country": "CN", "variant": "Hans"}. + * + * @param locale App locale data. + * @return this MobileOptions, for chaining. + */ + default T setAppLocale(AppLocale locale) { + return amend(APP_LOCALE_OPTION, locale.toMap()); + } + + /** + * Get the locale for the app under test. + * + * @return App locale data. + */ + default Optional getAppLocale() { + //noinspection unchecked + return Optional.ofNullable(getCapability(APP_LOCALE_OPTION)) + .map((v) -> new AppLocale((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java new file mode 100644 index 000000000..28763a79a --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java @@ -0,0 +1,293 @@ +/* + * 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.options.server; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class EspressoBuildConfig { + public static final String TOOLS_VERSION = "toolsVersions"; + public static final String ADDITIONAL_APP_DEPENDENCIES = "additionalAppDependencies"; + public static final String ADDITIONAL_ANDROID_TEST_DEPENDENCIES + = "additionalAndroidTestDependencies"; + + private JsonObject json; + + public EspressoBuildConfig() { + } + + public EspressoBuildConfig(JsonObject json) { + this.json = json; + } + + public EspressoBuildConfig(String json) { + this(JsonParser.parseString(json).getAsJsonObject()); + } + + private EspressoBuildConfig assignToolsVersionsField(String name, Object value) { + if (json == null) { + json = new JsonObject(); + } + boolean hasTools = json.has(TOOLS_VERSION); + JsonObject toolsVersions = hasTools + ? json.getAsJsonObject(TOOLS_VERSION) + : new JsonObject(); + if (value instanceof Number) { + toolsVersions.addProperty(name, (Number) value); + } else { + toolsVersions.addProperty(name, String.valueOf(value)); + } + if (!hasTools) { + json.add(TOOLS_VERSION, toolsVersions); + } + return this; + } + + private Optional getToolsVersionsFieldValue(String name) { + //noinspection unchecked + return json == null || !json.has(TOOLS_VERSION) + ? Optional.empty() + : Optional.ofNullable((R) json.getAsJsonObject(TOOLS_VERSION).get(name)); + } + + /** + * Set Gradle version. + * By default, the version from the build.gradle is used. + * + * @param version E.g. "6.3". + * @return self instance for chaining. + */ + public EspressoBuildConfig withGradleVersion(String version) { + return assignToolsVersionsField("gradle", version); + } + + /** + * Get Gradle version. + * + * @return Gradle version. + */ + public Optional getGradleVersion() { + return getToolsVersionsFieldValue("gradle"); + } + + /** + * Set Gradle plugin version. It must correspond to the Gradle version + * (if provided). By default, the version from the build.gradle is used. + * + * @param version E.g. "4.1.1" + * @return self instance for chaining. + */ + public EspressoBuildConfig withAndroidGradlePluginVersion(String version) { + return assignToolsVersionsField("androidGradlePlugin", version); + } + + /** + * Get Gradle plugin version. + * + * @return Gradle plugin version. + */ + public Optional getAndroidGradlePluginVersion() { + return getToolsVersionsFieldValue("androidGradlePlugin"); + } + + /** + * Set Android build tools version to compile the server with. + * By default, the version from the build.gradle is used. + * + * @param version E.g. "28.0.3". + * @return self instance for chaining. + */ + public EspressoBuildConfig withBuildToolsVersion(String version) { + return assignToolsVersionsField("buildTools", version); + } + + /** + * Get Android build tools version. + * + * @return Android build tools version. + */ + public Optional getBuildToolsVersion() { + return getToolsVersionsFieldValue("buildTools"); + } + + /** + * Set Android SDK version to compile the server for. + * By default, the version from the app build.gradle is used. + * + * @param version E.g. "28" + * @return self instance for chaining. + */ + public EspressoBuildConfig withCompileSdkVersion(String version) { + return assignToolsVersionsField("compileSdk", version); + } + + /** + * Get the target Android SDK version. + * + * @return Android SDK version. + */ + public Optional getCompileSdkVersion() { + return getToolsVersionsFieldValue("compileSdk"); + } + + /** + * Set the minimum Android SDK version to compile the server for. + * By default, the version from the app build.gradle is used. + * + * @param apiLevel E.g. 18. + * @return self instance for chaining. + */ + public EspressoBuildConfig withMinSdk(int apiLevel) { + return assignToolsVersionsField("minSdk", apiLevel); + } + + /** + * Get the minimum Android SDK version. + * + * @return Minimum Android SDK version. + */ + public Optional getMinSdkVersion() { + Optional result = getToolsVersionsFieldValue("minSdk"); + return result.map((v) -> Integer.parseInt(String.valueOf(v))); + } + + /** + * Set the target Android SDK version to compile the server for. + * By default, the version from the app build.gradle is used. + * + * @param apiLevel E.g. 28. + * @return self instance for chaining. + */ + public EspressoBuildConfig withTargetSdk(int apiLevel) { + return assignToolsVersionsField("targetSdk", apiLevel); + } + + /** + * Get the target Android SDK version. + * + * @return Target Android SDK version. + */ + public Optional getTargetSdkVersion() { + Optional result = getToolsVersionsFieldValue("targetSdk"); + return result.map((v) -> Integer.parseInt(String.valueOf(v))); + } + + /** + * Kotlin version to compile the server for. + * By default, the version from the build.gradle is used. + * + * @param version E.g. "1.5.10". + * @return self instance for chaining. + */ + public EspressoBuildConfig withKotlinVersion(String version) { + return assignToolsVersionsField("kotlin", version); + } + + /** + * Get the target Kotlin version. + * + * @return Kotlin version. + */ + public Optional getKotlinVersion() { + return getToolsVersionsFieldValue("kotlin"); + } + + private EspressoBuildConfig assignDependenciesField(String name, List value) { + if (json == null) { + json = new JsonObject(); + } + boolean hasField = json.has(name); + JsonArray dependencies = hasField + ? json.getAsJsonArray(name) + : new JsonArray(); + while (dependencies.size() > 0) { + dependencies.remove(0); + } + value.forEach(dependencies::add); + if (!hasField) { + json.add(name, dependencies); + } + return this; + } + + private Optional> getDependenciesValue(String name) { + return json == null + ? Optional.empty() + : Optional.ofNullable(json.getAsJsonArray(name)) + .map((v) -> { + List result = new ArrayList<>(); + v.forEach((x) -> result.add(String.valueOf(x))); + return result; + }); + } + + /** + * Set a non-empty array of dependent module names with their versions. + * The scripts add all these items as "implementation" lines of dependencies + * category in the app build.gradle script. + * + * @param dependencies E.g. ["xerces.xercesImpl:2.8.0", "xerces.xmlParserAPIs:2.6.2"]. + * @return self instance for chaining. + */ + public EspressoBuildConfig withAdditionalAppDependencies(List dependencies) { + return assignDependenciesField(ADDITIONAL_APP_DEPENDENCIES, dependencies); + } + + /** + * Get the array of dependent application module names with their versions. + * + * @return Dependent module names with their versions. + */ + public Optional> getAdditionalAppDependencies() { + return getDependenciesValue(ADDITIONAL_APP_DEPENDENCIES); + } + + /** + * Set a non-empty array of dependent module names with their versions. + * The scripts add all these items as "androidTestImplementation" lines of + * dependencies category in the app build.gradle script. + * + * @param dependencies E.g. ["xerces.xercesImpl:2.8.0", "xerces.xmlParserAPIs:2.6.2"]. + * @return self instance for chaining. + */ + public EspressoBuildConfig withAdditionalAndroidTestDependencies(List dependencies) { + return assignDependenciesField(ADDITIONAL_ANDROID_TEST_DEPENDENCIES, dependencies); + } + + /** + * Get the array of dependent Android test module names with their versions. + * + * @return Dependent module names with their versions. + */ + public Optional> getAdditionalAndroidTestDependencies() { + return getDependenciesValue(ADDITIONAL_ANDROID_TEST_DEPENDENCIES); + } + + public JsonObject toJson() { + return Optional.ofNullable(json).orElseGet(JsonObject::new); + } + + @Override + public String toString() { + return toJson().toString(); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java new file mode 100644 index 000000000..9444bc9ef --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java @@ -0,0 +1,69 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.internal.Either; + +import java.util.Optional; + +public interface SupportsEspressoBuildConfigOption> extends + Capabilities, CanSetCapability { + String ESPRESSO_BUILD_CONFIG_OPTION = "espressoBuildConfig"; + + /** + * This config allows to customize several important properties of + * Espresso server. Refer to + * https://github.com/appium/appium-espresso-driver#espresso-build-config + * for more information on how to properly construct such config. + * + * @param configPath The path to the config file on the server file system. + * @return self instance for chaining. + */ + default T setEspressoBuildConfig(String configPath) { + return amend(ESPRESSO_BUILD_CONFIG_OPTION, configPath); + } + + /** + * This config allows to customize several important properties of + * Espresso server. Refer to + * https://github.com/appium/appium-espresso-driver#espresso-build-config + * for more information on how to properly construct such config. + * + * @param config Config instance. + * @return self instance for chaining. + */ + default T setEspressoBuildConfig(EspressoBuildConfig config) { + return amend(ESPRESSO_BUILD_CONFIG_OPTION, config.toJson().toString()); + } + + /** + * Get the Espresso build config. + * + * @return Either the config itself or a path to a JSON file on the server FS. + */ + default Optional> getEspressoBuildConfig() { + return Optional.ofNullable(getCapability(ESPRESSO_BUILD_CONFIG_OPTION)) + .map(String::valueOf) + .map((v) -> v.trim().startsWith("{") + ? Either.left(new EspressoBuildConfig(v)) + : Either.right(v) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoServerLaunchTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoServerLaunchTimeoutOption.java new file mode 100644 index 000000000..41bc66ee5 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoServerLaunchTimeoutOption.java @@ -0,0 +1,53 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsEspressoServerLaunchTimeoutOption> extends + Capabilities, CanSetCapability { + String ESPRESSO_SERVER_LAUNCH_TIMEOUT_OPTION = "espressoServerLaunchTimeout"; + + /** + * Set the maximum timeout to wait util Espresso is listening on the device. + * 45000 ms by default + * + * @param timeout Timeout value. + * @return self instance for chaining. + */ + default T setUiautomator2ServerInstallTimeout(Duration timeout) { + return amend(ESPRESSO_SERVER_LAUNCH_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait until Espresso server is listening on the device. + * + * @return The timeout value. + */ + default Optional getUiautomator2ServerInstallTimeout() { + return Optional.ofNullable( + toDuration(getCapability(ESPRESSO_SERVER_LAUNCH_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsForceEspressoRebuildOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsForceEspressoRebuildOption.java new file mode 100644 index 000000000..843d25ddc --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsForceEspressoRebuildOption.java @@ -0,0 +1,63 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsForceEspressoRebuildOption> extends + Capabilities, CanSetCapability { + String FORCE_ESPRESSO_REBUILD_OPTION = "forceEspressoRebuild"; + + /** + * Enforces Espresso server rebuild on a new session startup. + * + * @return self instance for chaining. + */ + default T forceEspressoRebuild() { + return amend(FORCE_ESPRESSO_REBUILD_OPTION, true); + } + + /** + * Whether to always enforce Espresso server rebuild (true). + * By default, Espresso caches the already built server apk and only rebuilds + * it when it is necessary, because rebuilding process needs extra time. + * false by default. + * + * @param value True to force Espresso server rebuild on a new session startup. + * @return self instance for chaining. + */ + default T setForceEspressoRebuild(boolean value) { + return amend(FORCE_ESPRESSO_REBUILD_OPTION, value); + } + + /** + * Get to force Espresso server rebuild on a new session startup. + * + * @return True or false. + */ + default Optional doesForceEspressoRebuild() { + return Optional.ofNullable( + toSafeBoolean(getCapability(FORCE_ESPRESSO_REBUILD_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsShowGradleLogOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsShowGradleLogOption.java new file mode 100644 index 000000000..dabd0f0ec --- /dev/null +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsShowGradleLogOption.java @@ -0,0 +1,61 @@ +/* + * 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.options.server; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShowGradleLogOption> extends + Capabilities, CanSetCapability { + String SHOW_GRADLE_LOG_OPTION = "showGradleLog"; + + /** + * Enforces inclusion of the Gradle log to the regular server logs. + * + * @return self instance for chaining. + */ + default T showGradleLog() { + return amend(SHOW_GRADLE_LOG_OPTION, true); + } + + /** + * Whether to include Gradle log to the regular server logs while + * building Espresso server. false by default. + * + * @param value Whether to include Gradle log to the regular server logs. + * @return self instance for chaining. + */ + default T setShowGradleLog(boolean value) { + return amend(SHOW_GRADLE_LOG_OPTION, value); + } + + /** + * Get whether to include Gradle log to the regular server log. + * + * @return True or false. + */ + default Optional doesShowGradleLog() { + return Optional.ofNullable( + toSafeBoolean(getCapability(SHOW_GRADLE_LOG_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java index 088f040fc..ad572b3f6 100644 --- a/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsSkipServerInstallationOption.java @@ -29,7 +29,7 @@ public interface SupportsSkipServerInstallationOption> String SKIP_SERVER_INSTALLATION_OPTION = "skipServerInstallation"; /** - * Enables skipping of the UiAutomator2 Server component installation + * Enables skipping of the server components installation * on the device under test and all the related checks. * This could help to speed up the session startup if you know for sure the * correct server version is installed on the device. @@ -43,7 +43,7 @@ default T skipServerInstallation() { } /** - * Set whether to skip the UiAutomator2 Server component installation + * Set whether to skip the server components installation * on the device under test and all the related checks. * This could help to speed up the session startup if you know for sure the * correct server version is installed on the device. @@ -58,7 +58,7 @@ default T setSkipServerInstallation(boolean value) { } /** - * Get whether to skip the UiAutomator2 Server component installation + * Get whether to skip the server components installation * on the device under test and all the related checks. * * @return True or false. diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java index cf638ff9f..925b8ea3d 100644 --- a/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsSystemPortOption.java @@ -29,8 +29,9 @@ public interface SupportsSystemPortOption> extends String SYSTEM_PORT_OPTION = "systemPort"; /** - * The number of the port the UiAutomator2 server is listening on. - * By default, the first free port from 8200..8299 range is selected. + * The number of the port the UiAutomator2 or Espresso server is listening on. + * By default, the first free port from 8200..8299 range is selected for UIA2 + * and 8300..8399 range is selected for Espresso. * It is recommended to set this value if you are running parallel * tests on the same machine. * diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java index 3d6bd39e6..c961841f8 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsEventTimingsOption.java @@ -31,7 +31,7 @@ public interface SupportsEventTimingsOption> extends * * @return self instance for chaining. */ - default T setEventTimings() { + default T eventTimings() { return setEventTimings(true); } diff --git a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java index 2e3b73448..191055553 100644 --- a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java @@ -24,6 +24,8 @@ import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; + import static org.junit.Assert.assertNotNull; public class AndroidViewMatcherTest extends BaseEspressoTest { @@ -35,7 +37,7 @@ public void testFindByViewMatcher() { "args", ImmutableList.of("Animation"), "class", "androidx.test.espresso.matcher.ViewMatchers" )); - final WebDriverWait wait = new WebDriverWait(driver, 10); + final WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); assertNotNull(wait.until(ExpectedConditions .presenceOfElementLocated(AppiumBy.androidViewMatcher(selector)))); } diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 065794566..997b83a23 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -44,7 +44,7 @@ public class BaseAndroidTest { UiAutomator2Options options = new UiAutomator2Options() .setDeviceName("Android Emulator") .setApp(apiDemosApk().toAbsolutePath().toString()) - .setEventTimings(); + .eventTimings(); driver = new AndroidDriver(service.getUrl(), options); } diff --git a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java index 6d9cd7671..6375ff58e 100644 --- a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java +++ b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java @@ -16,13 +16,11 @@ package io.appium.java_client.android; -import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.android.options.EspressoOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.openqa.selenium.remote.DesiredCapabilities; import static io.appium.java_client.TestResources.apiDemosApk; @@ -43,12 +41,11 @@ public class BaseEspressoTest { "An appium server node is not started!"); } - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ESPRESSO); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, apiDemosApk().toAbsolutePath().toString()); - capabilities.setCapability("eventTimings", true); - driver = new AndroidDriver(service.getUrl(), capabilities); + EspressoOptions options = new EspressoOptions() + .setDeviceName("Android Emulator") + .setApp(apiDemosApk().toAbsolutePath().toString()) + .eventTimings(); + driver = new AndroidDriver(service.getUrl(), options); } /** From 853ef49b73c2b7524ac324781c779c429700312c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Oct 2021 14:33:20 +0300 Subject: [PATCH 021/501] build(deps): bump org.owasp.dependencycheck from 6.3.2 to 6.4.1.1 (#1533) Bumps org.owasp.dependencycheck from 6.3.2 to 6.4.1.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 847dbd2d3..b26a68384 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.3.2' + id 'org.owasp.dependencycheck' version '6.4.1.1' id 'com.github.johnrengelman.shadow' version '7.1.0' } From 3fd3bac870da613673b180dbb2ff6be0e40f0a86 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 29 Oct 2021 15:21:19 +0200 Subject: [PATCH 022/501] feat: Add Windows driver options (#1564) --- .../android/options/app/ActivityOptions.java | 2 +- .../android/options/app/IntentOptions.java | 2 +- .../options/localization/AppLocale.java | 4 +- .../options/BaseMapOptionData.java | 4 +- .../windows/options/RunScript.java | 69 +++++++++++++++++++ .../options/SupportsAppArgumentsOption.java | 48 +++++++++++++ .../SupportsAppTopLevelWindowOption.java | 50 ++++++++++++++ .../options/SupportsAppWorkingDirOption.java | 49 +++++++++++++ .../SupportsCreateSessionTimeoutOption.java | 55 +++++++++++++++ ...SupportsMsExperimentalWebDriverOption.java | 59 ++++++++++++++++ .../SupportsMsWaitForAppLaunchOption.java | 55 +++++++++++++++ .../options/SupportsPostrunOption.java | 55 +++++++++++++++ .../windows/options/SupportsPrerunOption.java | 55 +++++++++++++++ .../options/SupportsSystemPortOption.java | 52 ++++++++++++++ .../windows/options/WindowsOptions.java | 59 ++++++++++++++++ 15 files changed, 611 insertions(+), 7 deletions(-) rename src/main/java/io/appium/java_client/{android => remote}/options/BaseMapOptionData.java (96%) create mode 100644 src/main/java/io/appium/java_client/windows/options/RunScript.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsAppTopLevelWindowOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsAppWorkingDirOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsCreateSessionTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsMsExperimentalWebDriverOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsMsWaitForAppLaunchOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsSystemPortOption.java create mode 100644 src/main/java/io/appium/java_client/windows/options/WindowsOptions.java diff --git a/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java b/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java index e0cc553a0..de328149f 100644 --- a/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java +++ b/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java @@ -16,7 +16,7 @@ package io.appium.java_client.android.options.app; -import io.appium.java_client.android.options.BaseMapOptionData; +import io.appium.java_client.remote.options.BaseMapOptionData; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java index 2ba619aac..e651a4b91 100644 --- a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java +++ b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java @@ -16,7 +16,7 @@ package io.appium.java_client.android.options.app; -import io.appium.java_client.android.options.BaseMapOptionData; +import io.appium.java_client.remote.options.BaseMapOptionData; import java.util.List; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java b/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java index d7d0209d0..f8f0147f7 100644 --- a/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java +++ b/src/main/java/io/appium/java_client/android/options/localization/AppLocale.java @@ -16,10 +16,8 @@ package io.appium.java_client.android.options.localization; -import io.appium.java_client.android.options.BaseMapOptionData; +import io.appium.java_client.remote.options.BaseMapOptionData; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java b/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java similarity index 96% rename from src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java rename to src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java index ce473a607..004d1bdf5 100644 --- a/src/main/java/io/appium/java_client/android/options/BaseMapOptionData.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appium.java_client.android.options; +package io.appium.java_client.remote.options; import com.google.gson.GsonBuilder; @@ -24,7 +24,7 @@ import java.util.Optional; public abstract class BaseMapOptionData> { - protected Map options; + private Map options; public BaseMapOptionData() { } diff --git a/src/main/java/io/appium/java_client/windows/options/RunScript.java b/src/main/java/io/appium/java_client/windows/options/RunScript.java new file mode 100644 index 000000000..e31fa38fc --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/RunScript.java @@ -0,0 +1,69 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseMapOptionData; + +import java.util.Map; +import java.util.Optional; + +public class RunScript extends BaseMapOptionData { + public RunScript() { + } + + public RunScript(Map options) { + super(options); + } + + /** + * Allows to provide a multiline PowerShell script. + * + * @param script A valid PowerShell script. + * @return self instance for chaining. + */ + public RunScript withScript(String script) { + return assignOptionValue("script", script); + } + + /** + * Get a multiline PowerShell script. + * + * @return PowerShell script. + */ + public Optional getScript() { + return getOptionValue("script"); + } + + /** + * Allows to provide a single-line PowerShell script. + * + * @param command A valid PowerShell script. + * @return self instance for chaining. + */ + public RunScript withCommand(String command) { + return assignOptionValue("command", command); + } + + /** + * Get a single-line PowerShell script. + * + * @return PowerShell script. + */ + public Optional getCommand() { + return getOptionValue("command"); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java new file mode 100644 index 000000000..e5a8f55c3 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java @@ -0,0 +1,48 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.net.URL; +import java.util.Optional; + +public interface SupportsAppArgumentsOption> extends + Capabilities, CanSetCapability { + String APP_ARGUMENTS_OPTION = "appArguments"; + + /** + * Application arguments string. + * + * @param args E.g. "/?" + * @return self instance for chaining. + */ + default T setAppArguments(String args) { + return amend(APP_ARGUMENTS_OPTION, args); + } + + /** + * Get application arguments. + * + * @return Application arguments. + */ + default Optional setAppArguments() { + return Optional.ofNullable((String) getCapability(APP_ARGUMENTS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsAppTopLevelWindowOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsAppTopLevelWindowOption.java new file mode 100644 index 000000000..8490398f1 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsAppTopLevelWindowOption.java @@ -0,0 +1,50 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppTopLevelWindowOption> extends + Capabilities, CanSetCapability { + String APP_TOP_LEVEL_WINDOW_OPTION = "appTopLevelWindow"; + + /** + * Set the hexadecimal handle of an existing application top level + * window to attach to, for example 0x12345 (should be of string type). + * Either this capability or app one must be provided on session startup. + * + * @param identifier E.g. "0x12345". + * @return self instance for chaining. + */ + default T setAppTopLevelWindow(String identifier) { + return amend(APP_TOP_LEVEL_WINDOW_OPTION, identifier); + } + + /** + * Get the hexadecimal handle of an existing application top level + * window to attach to. + * + * @return Top level window handle. + */ + default Optional getAppTopLevelWindow() { + return Optional.ofNullable((String) getCapability(APP_TOP_LEVEL_WINDOW_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsAppWorkingDirOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsAppWorkingDirOption.java new file mode 100644 index 000000000..bc3e1e074 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsAppWorkingDirOption.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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAppWorkingDirOption> extends + Capabilities, CanSetCapability { + String APP_WORKING_DIR_OPTION = "appWorkingDir"; + + /** + * Full path to the folder, which is going to be set as the working + * dir for the application under test. This is only applicable for classic apps. + * + * @param path Existing folder path on the server file system. + * @return self instance for chaining. + */ + default T setAppWorkingDir(String path) { + return amend(APP_WORKING_DIR_OPTION, path); + } + + /** + * Get the full path to the folder, which is going to be set as the working + * dir for the application under test. + * + * @return Folder path on the server file system. + */ + default Optional getAppWorkingDir() { + return Optional.ofNullable((String) getCapability(APP_WORKING_DIR_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsCreateSessionTimeoutOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsCreateSessionTimeoutOption.java new file mode 100644 index 000000000..334209fe8 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsCreateSessionTimeoutOption.java @@ -0,0 +1,55 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsCreateSessionTimeoutOption> extends + Capabilities, CanSetCapability { + String CREATE_SESSION_TIMEOUT_OPTION = "createSessionTimeout"; + + /** + * Set the timeout used to retry Appium Windows Driver session startup. + * This capability could be used as a workaround for the long startup times + * of UWP applications (aka Failed to locate opened application window + * with appId: TestCompany.my_app4!App, and processId: 8480). Default value is 20000ms. + * + * @param timeout The timeout value. + * @return self instance for chaining. + */ + default T setCreateSessionTimeout(Duration timeout) { + return amend(CREATE_SESSION_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout used to retry Appium Windows Driver session startup. + * + * @return The timeout value. + */ + default Optional getCreateSessionTimeout() { + return Optional.ofNullable( + toDuration(getCapability(CREATE_SESSION_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsMsExperimentalWebDriverOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsMsExperimentalWebDriverOption.java new file mode 100644 index 000000000..a4415707a --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsMsExperimentalWebDriverOption.java @@ -0,0 +1,59 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsMsExperimentalWebDriverOption> extends + Capabilities, CanSetCapability { + String MS_EXPERIMENTAL_WEBDRIVER_OPTION = "ms:experimental-webdriver"; + + /** + * Enforce to enable experimental driver features and optimizations. + * + * @return self instance for chaining. + */ + default T experimentalWebDriver() { + return amend(MS_EXPERIMENTAL_WEBDRIVER_OPTION, true); + } + + /** + * Enables experimental features and optimizations. See Appium Windows + * Driver release notes for more details on this capability. false by default. + * + * @param value Whether to enable experimental features and optimizations. + * @return self instance for chaining. + */ + default T setExperimentalWebDriver(boolean value) { + return amend(MS_EXPERIMENTAL_WEBDRIVER_OPTION, value); + } + + /** + * Get whether to enable experimental features and optimizations. + * + * @return True or false. + */ + default Optional isExperimentalWebDriver() { + return Optional.ofNullable(toSafeBoolean(getCapability(MS_EXPERIMENTAL_WEBDRIVER_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsMsWaitForAppLaunchOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsMsWaitForAppLaunchOption.java new file mode 100644 index 000000000..2066616ce --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsMsWaitForAppLaunchOption.java @@ -0,0 +1,55 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsMsWaitForAppLaunchOption> extends + Capabilities, CanSetCapability { + String MS_WAIT_FOR_APP_LAUNCH_OPTION = "ms:waitForAppLaunch"; + + /** + * Similar to createSessionTimeout, but is + * applied on the server side. Enables Appium Windows Driver to wait for + * a defined amount of time after an app launch is initiated prior to + * attaching to the application session. The limit for this is 50 seconds. + * + * @param timeout The timeout value. + * @return self instance for chaining. + */ + default T setWaitForAppLaunch(Duration timeout) { + return amend(MS_WAIT_FOR_APP_LAUNCH_OPTION, timeout.getSeconds()); + } + + /** + * Get the timeout used to retry Appium Windows Driver session startup. + * + * @return The timeout value. + */ + default Optional doesWaitForAppLaunch() { + return Optional.ofNullable( + toDuration(getCapability(MS_WAIT_FOR_APP_LAUNCH_OPTION), Duration::ofSeconds) + ); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java new file mode 100644 index 000000000..b766820c3 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java @@ -0,0 +1,55 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsPostrunOption> extends + Capabilities, CanSetCapability { + String POSTRUN_OPTION = "postrun"; + + /** + * An object containing either script or command key. The value of + * each key must be a valid PowerShell script or command to be + * executed after an WinAppDriver session is finished. + * See + * https://github.com/appium/appium-windows-driver#power-shell-commands-execution + * for more details. + * + * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. + * @return self instance for chaining. + */ + default T setPostrun(RunScript script) { + return amend(POSTRUN_OPTION, script.toMap()); + } + + /** + * Get the postrun script. + * + * @return Postrun script. + */ + default Optional getPostrun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(POSTRUN_OPTION)) + .map((v) -> new RunScript((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java new file mode 100644 index 000000000..d3722da48 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java @@ -0,0 +1,55 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsPrerunOption> extends + Capabilities, CanSetCapability { + String PRERUN_OPTION = "prerun"; + + /** + * An object containing either script or command key. The value of + * each key must be a valid PowerShell script or command to be + * executed prior to the WinAppDriver session startup. + * See + * https://github.com/appium/appium-windows-driver#power-shell-commands-execution + * for more details. + * + * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. + * @return self instance for chaining. + */ + default T setPrerun(RunScript script) { + return amend(PRERUN_OPTION, script.toMap()); + } + + /** + * Get the prerun script. + * + * @return Prerun script. + */ + default Optional getPrerun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(PRERUN_OPTION)) + .map((v) -> new RunScript((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsSystemPortOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsSystemPortOption.java new file mode 100644 index 000000000..65ab9fb31 --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/SupportsSystemPortOption.java @@ -0,0 +1,52 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsSystemPortOption> extends + Capabilities, CanSetCapability { + String SYSTEM_PORT_OPTION = "systemPort"; + + /** + * The port number to execute Appium Windows Driver server listener on, + * for example 5556. The port must not be occupied. The default starting port + * number for a new Appium Windows Driver session is 4724. If this port is + * already busy then the next free port will be automatically selected. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setSystemPort(int port) { + return amend(SYSTEM_PORT_OPTION, port); + } + + /** + * Get the port number to execute Appium Windows Driver server listener on. + * + * @return System port value. + */ + default Optional getSystemPort() { + return Optional.ofNullable(toInteger(getCapability(SYSTEM_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java new file mode 100644 index 000000000..0d25a1ece --- /dev/null +++ b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java @@ -0,0 +1,59 @@ +/* + * 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.windows.options; + +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAppOption; +import org.openqa.selenium.Capabilities; + +import java.util.Map; + +/** + * https://github.com/appium/appium-windows-driver#usage + */ +public class WindowsOptions extends BaseOptions implements + SupportsAppOption, + SupportsAppArgumentsOption, + SupportsAppTopLevelWindowOption, + SupportsAppWorkingDirOption, + SupportsCreateSessionTimeoutOption, + SupportsMsWaitForAppLaunchOption, + SupportsMsExperimentalWebDriverOption, + SupportsSystemPortOption, + SupportsPrerunOption, + SupportsPostrunOption { + public WindowsOptions() { + setCommonOptions(); + } + + public WindowsOptions(Capabilities source) { + super(source); + setCommonOptions(); + } + + public WindowsOptions(Map source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setPlatformName(MobilePlatform.WINDOWS); + setAutomationName(AutomationName.WINDOWS); + } +} From 73c44c62329fb025b7306c287c903b8e8354fcae Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 29 Oct 2021 17:14:01 +0300 Subject: [PATCH 023/501] refactor: change prefix to `AppiumBy` in locator `toString` implementation (#1559) --- src/main/java/io/appium/java_client/AppiumBy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 0f578b0b0..98730e1ad 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -48,7 +48,7 @@ protected AppiumBy(String selector, String locatorString, String locatorName) { } @Override public String toString() { - return String.format("By.%s: %s", locatorName, remoteParameters.value()); + return String.format("AppiumBy.%s: %s", locatorName, remoteParameters.value()); } /** From 7013e5620cc80421837397da39e40891ca83caa7 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 29 Oct 2021 18:21:49 +0200 Subject: [PATCH 024/501] feat: Add Mac2 driver options (#1565) --- .../java_client/mac/options/Mac2Options.java | 60 ++++++++++++++++ .../java_client/mac/options/RunScript.java | 69 +++++++++++++++++++ .../mac/options/SupportsArgumentsOption.java | 50 ++++++++++++++ .../options/SupportsBootstrapRootOption.java | 50 ++++++++++++++ .../mac/options/SupportsBundleIdOption.java | 53 ++++++++++++++ .../options/SupportsEnvironmentOption.java | 52 ++++++++++++++ .../mac/options/SupportsPostrunOption.java | 54 +++++++++++++++ .../mac/options/SupportsPrerunOption.java | 54 +++++++++++++++ .../SupportsServerStartupTimeoutOption.java | 54 +++++++++++++++ .../options/SupportsShowServerLogsOption.java | 59 ++++++++++++++++ .../options/SupportsSkipAppKillOption.java | 61 ++++++++++++++++ .../mac/options/SupportsSystemHostOption.java | 51 ++++++++++++++ .../mac/options/SupportsSystemPortOption.java | 50 ++++++++++++++ .../SupportsWebDriverAgentMacUrlOption.java | 63 +++++++++++++++++ 14 files changed, 780 insertions(+) create mode 100644 src/main/java/io/appium/java_client/mac/options/Mac2Options.java create mode 100644 src/main/java/io/appium/java_client/mac/options/RunScript.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsArgumentsOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsBootstrapRootOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsBundleIdOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsServerStartupTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsShowServerLogsOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsSkipAppKillOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsSystemHostOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsSystemPortOption.java create mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsWebDriverAgentMacUrlOption.java diff --git a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java new file mode 100644 index 000000000..47214f677 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java @@ -0,0 +1,60 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.remote.options.BaseOptions; +import org.openqa.selenium.Capabilities; + +import java.util.Map; + +/** + * https://github.com/appium/appium-mac2-driver#capabilities + */ +public class Mac2Options extends BaseOptions implements + SupportsSystemPortOption, + SupportsSystemHostOption, + SupportsWebDriverAgentMacUrlOption, + SupportsBootstrapRootOption, + SupportsBundleIdOption, + SupportsArgumentsOption, + SupportsEnvironmentOption, + SupportsServerStartupTimeoutOption, + SupportsSkipAppKillOption, + SupportsShowServerLogsOption, + SupportsPrerunOption, + SupportsPostrunOption { + public Mac2Options() { + setCommonOptions(); + } + + public Mac2Options(Capabilities source) { + super(source); + setCommonOptions(); + } + + public Mac2Options(Map source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setPlatformName(MobilePlatform.MAC); + setAutomationName(AutomationName.MAC2); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/RunScript.java b/src/main/java/io/appium/java_client/mac/options/RunScript.java new file mode 100644 index 000000000..4960d7e86 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/RunScript.java @@ -0,0 +1,69 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseMapOptionData; + +import java.util.Map; +import java.util.Optional; + +public class RunScript extends BaseMapOptionData { + public RunScript() { + } + + public RunScript(Map options) { + super(options); + } + + /** + * Allows to provide a multiline AppleScript. + * + * @param script A valid AppleScript. + * @return self instance for chaining. + */ + public RunScript withScript(String script) { + return assignOptionValue("script", script); + } + + /** + * Get a multiline AppleScript. + * + * @return AppleScript snippet. + */ + public Optional getScript() { + return getOptionValue("script"); + } + + /** + * Allows to provide a single-line AppleScript. + * + * @param command A valid AppleScript. + * @return self instance for chaining. + */ + public RunScript withCommand(String command) { + return assignOptionValue("command", command); + } + + /** + * Get a single-line AppleScript. + * + * @return AppleScript snippet. + */ + public Optional getCommand() { + return getOptionValue("command"); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsArgumentsOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsArgumentsOption.java new file mode 100644 index 000000000..8d8c427f5 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsArgumentsOption.java @@ -0,0 +1,50 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.List; +import java.util.Optional; + +public interface SupportsArgumentsOption> extends + Capabilities, CanSetCapability { + String ARGUMENTS_OPTION = "arguments"; + + /** + * Array of application command line arguments. This capability is + * only going to be applied if the application is not running on session startup. + * + * @param arguments E.g. ["--help"]. + * @return self instance for chaining. + */ + default T setArguments(List arguments) { + return amend(ARGUMENTS_OPTION, arguments); + } + + /** + * Get the array of application command line arguments. + * + * @return Application arguments. + */ + default Optional> getArguments() { + //noinspection unchecked + return Optional.ofNullable((List) getCapability(ARGUMENTS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsBootstrapRootOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsBootstrapRootOption.java new file mode 100644 index 000000000..cb3245148 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsBootstrapRootOption.java @@ -0,0 +1,50 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsBootstrapRootOption> extends + Capabilities, CanSetCapability { + String BOOTSTRAP_ROOT_OPTION = "bootstrapRoot"; + + /** + * The full path to WebDriverAgentMac root folder where Xcode project + * of the server sources lives. By default, this project is located in + * the same folder where the corresponding driver Node.js module lives. + * + * @param path The full path to WebDriverAgentMac root folder. + * @return self instance for chaining. + */ + default T setBootstrapRoot(String path) { + return amend(BOOTSTRAP_ROOT_OPTION, path); + } + + /** + * Get the full path to WebDriverAgentMac root folder where Xcode project + * of the server sources lives. + * + * @return The full path to WebDriverAgentMac root folder. + */ + default Optional getBootstrapRoot() { + return Optional.ofNullable((String) getCapability(BOOTSTRAP_ROOT_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsBundleIdOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsBundleIdOption.java new file mode 100644 index 000000000..d19420c8f --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsBundleIdOption.java @@ -0,0 +1,53 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsBundleIdOption> extends + Capabilities, CanSetCapability { + String BUNDLE_ID_OPTION = "bundleId"; + + /** + * The bundle identifier of the application to automate, for example + * com.apple.TextEdit. This is an optional capability. If it is not provided + * then the session will be started without an application under test + * (actually, it will be Finder). If the application with the given + * identifier is not installed then an error will be thrown on session + * startup. If the application is already running then it will be moved to + * the foreground. + * + * @param identifier A valid application bundle identifier. + * @return self instance for chaining. + */ + default T setBundleId(String identifier) { + return amend(BUNDLE_ID_OPTION, identifier); + } + + /** + * Get the bundle identifier of the application to automate. + * + * @return Application bundle identifier. + */ + default Optional getBundleId() { + return Optional.ofNullable((String) getCapability(BUNDLE_ID_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java new file mode 100644 index 000000000..17a2d05f9 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java @@ -0,0 +1,52 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.List; +import java.util.Optional; + +public interface SupportsEnvironmentOption> extends + Capabilities, CanSetCapability { + String ENVIRONMENT_OPTION = "environment"; + + /** + * A dictionary of environment variables (name->value) that are going to be passed + * to the application under test on top of environment variables inherited from + * the parent process. This capability is only going to be applied if the application + * is not running on session startup. + * + * @param arguments E.g. ["--help"]. + * @return self instance for chaining. + */ + default T setEnvironment(List arguments) { + return amend(ENVIRONMENT_OPTION, arguments); + } + + /** + * Get the application environment variables mapping. + * + * @return Application environment mapping. + */ + default Optional> getEnvironment() { + //noinspection unchecked + return Optional.ofNullable((List) getCapability(ENVIRONMENT_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java new file mode 100644 index 000000000..69430019b --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java @@ -0,0 +1,54 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsPostrunOption> extends + Capabilities, CanSetCapability { + String POSTRUN_OPTION = "postrun"; + + /** + * An object containing either script or command key. The value of + * each key must be a valid AppleScript script or command to be + * executed after Mac2Driver session is stopped. See + * https://github.com/appium/appium-mac2-driver#applescript-commands-execution + * for more details. + * + * @param script A valid AppleScript snippet. + * @return self instance for chaining. + */ + default T setPostrun(RunScript script) { + return amend(POSTRUN_OPTION, script.toMap()); + } + + /** + * Get the postrun script. + * + * @return Postrun script. + */ + default Optional getPostrun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(POSTRUN_OPTION)) + .map((v) -> new RunScript((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java new file mode 100644 index 000000000..61b8d0897 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java @@ -0,0 +1,54 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsPrerunOption> extends + Capabilities, CanSetCapability { + String PRERUN_OPTION = "prerun"; + + /** + * An object containing either script or command key. The value of + * each key must be a valid AppleScript script or command to be + * executed after before Mac2Driver session is started. See + * https://github.com/appium/appium-mac2-driver#applescript-commands-execution + * for more details. + * + * @param script A valid AppleScript snippet. + * @return self instance for chaining. + */ + default T setPrerun(RunScript script) { + return amend(PRERUN_OPTION, script.toMap()); + } + + /** + * Get the prerun script. + * + * @return Prerun script. + */ + default Optional getPrerun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(PRERUN_OPTION)) + .map((v) -> new RunScript((Map) v)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsServerStartupTimeoutOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsServerStartupTimeoutOption.java new file mode 100644 index 000000000..97d052928 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsServerStartupTimeoutOption.java @@ -0,0 +1,54 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + +public interface SupportsServerStartupTimeoutOption> extends + Capabilities, CanSetCapability { + String SERVER_STARTUP_TIMEOUT_OPTION = "serverStartupTimeout"; + + /** + * The timeout to wait util the WebDriverAgentMac + * project is built and started. 120000ms by default + * + * @param timeout The timeout value. + * @return self instance for chaining. + */ + default T setServerStartupTimeout(Duration timeout) { + return amend(SERVER_STARTUP_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the timeout to wait util the WebDriverAgentMac + * project is built and started. + * + * @return The timeout value. + */ + default Optional getServerStartupTimeout() { + return Optional.ofNullable( + toDuration(getCapability(SERVER_STARTUP_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsShowServerLogsOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsShowServerLogsOption.java new file mode 100644 index 000000000..f91a32d97 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsShowServerLogsOption.java @@ -0,0 +1,59 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsShowServerLogsOption> extends + Capabilities, CanSetCapability { + String SHOW_SERVER_LOGS_OPTION = "showServerLogs"; + + /** + * Enforce showing of WDA server logs in the Appium log.. + * + * @return self instance for chaining. + */ + default T showServerLogs() { + return amend(SHOW_SERVER_LOGS_OPTION, true); + } + + /** + * Set it to true in order to include xcodebuild output to the Appium + * server log. false by default. + * + * @param value Whether to show WDA server logs in the Appium log. + * @return self instance for chaining. + */ + default T setShowServerLogs(boolean value) { + return amend(SHOW_SERVER_LOGS_OPTION, value); + } + + /** + * Get whether to show WDA server logs in the Appium log. + * + * @return True or false. + */ + default Optional doesShowServerLogs() { + return Optional.ofNullable(toSafeBoolean(getCapability(SHOW_SERVER_LOGS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsSkipAppKillOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsSkipAppKillOption.java new file mode 100644 index 000000000..5c166b80a --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsSkipAppKillOption.java @@ -0,0 +1,61 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSkipAppKillOption> extends + Capabilities, CanSetCapability { + String SKIP_APP_KILL_OPTION = "skipAppKill"; + + /** + * Enforces skipping the termination of the application under test + * when the testing session quits. + * + * @return self instance for chaining. + */ + default T skipAppKill() { + return amend(SKIP_APP_KILL_OPTION, true); + } + + /** + * Set whether to skip the termination of the application under test + * when the testing session quits. false by default. This capability + * is only going to be applied if bundleId is set. + * + * @param value True to skip the termination of the application under test. + * @return self instance for chaining. + */ + default T setSkipAppKill(boolean value) { + return amend(SKIP_APP_KILL_OPTION, value); + } + + /** + * Get whether to skip the termination of the application under test. + * + * @return True or false. + */ + default Optional doesSkipAppKill() { + return Optional.ofNullable(toSafeBoolean(getCapability(SKIP_APP_KILL_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsSystemHostOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsSystemHostOption.java new file mode 100644 index 000000000..8f6a92cc1 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsSystemHostOption.java @@ -0,0 +1,51 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSystemHostOption> extends + Capabilities, CanSetCapability { + String SYSTEM_HOST_OPTION = "systemHost"; + + /** + * The name of the host for the internal server to listen on. + * If not provided then Mac2Driver will use the default host + * address 127.0.0.1. You could set it to 0.0.0.0 to make the + * server listening on all available network interfaces. + * It is also possible to set the particular interface name, for example en1. + * + * @param host Host name. + * @return self instance for chaining. + */ + default T setSystemHost(String host) { + return amend(SYSTEM_HOST_OPTION, host); + } + + /** + * Get the name of the host for the internal server to listen on. + * + * @return System host value. + */ + default Optional getSystemHost() { + return Optional.ofNullable((String) getCapability(SYSTEM_HOST_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsSystemPortOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsSystemPortOption.java new file mode 100644 index 000000000..bf648a7bb --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsSystemPortOption.java @@ -0,0 +1,50 @@ +/* + * 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.mac.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsSystemPortOption> extends + Capabilities, CanSetCapability { + String SYSTEM_PORT_OPTION = "systemPort"; + + /** + * The number of the port for the internal server to listen on. + * If not provided then Mac2Driver will use the default port 10100. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setSystemPort(int port) { + return amend(SYSTEM_PORT_OPTION, port); + } + + /** + * Get the number of the port for the internal server to listen on. + * + * @return System port value. + */ + default Optional getSystemPort() { + return Optional.ofNullable(toInteger(getCapability(SYSTEM_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsWebDriverAgentMacUrlOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsWebDriverAgentMacUrlOption.java new file mode 100644 index 000000000..9f968c9c0 --- /dev/null +++ b/src/main/java/io/appium/java_client/mac/options/SupportsWebDriverAgentMacUrlOption.java @@ -0,0 +1,63 @@ +/* + * 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.mac.options; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.net.URL; +import java.util.Optional; + +public interface SupportsWebDriverAgentMacUrlOption> extends + Capabilities, CanSetCapability { + String WEB_DRIVER_AGENT_MAC_URL_OPTION = "webDriverAgentMacUrl"; + + /** + * Set the URL Appium will connect to an existing WebDriverAgentMac + * instance at this URL instead of starting a new one. + * + * @param url E.g. "http://192.168.10.1:10101" + * @return self instance for chaining. + */ + default T setWebDriverAgentMacUrl(URL url) { + return amend(WEB_DRIVER_AGENT_MAC_URL_OPTION, url.toString()); + } + + /** + * Set the URL Appium will connect to an existing WebDriverAgentMac + * instance at this URL instead of starting a new one. + * + * @param url E.g. "http://192.168.10.1:10101" + * @return self instance for chaining. + */ + default T setWebDriverAgentMacUrl(String url) { + return amend(WEB_DRIVER_AGENT_MAC_URL_OPTION, url); + } + + /** + * Get the URL Appium will connect to an existing WebDriverAgentMac + * instance. + * + * @return Server URL. + */ + default Optional getWebDriverAgentMacUrl() { + return Optional.ofNullable(getCapability(WEB_DRIVER_AGENT_MAC_URL_OPTION)) + .map(CapabilityHelpers::toUrl); + } +} From 45c74fbf6fd87fd27cfbda9f7d5af0df5b12b052 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 29 Oct 2021 23:25:25 +0300 Subject: [PATCH 025/501] build: enable dependencies caching (#1567) --- .github/workflows/gradle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ce066fb6f..e12ca5be8 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -20,5 +20,6 @@ jobs: with: distribution: 'zulu' java-version: 8 + cache: 'gradle' - name: Build with Gradle run: ./gradlew clean build -x signMavenJavaPublication -x test -x checkstyleTest From e9a2cbce32b5fa4b5af1ff03d5822247bdbca658 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sat, 30 Oct 2021 03:03:25 +0300 Subject: [PATCH 026/501] build: remove redundant exclusion of Gradle task `signMavenJavaPublication` (#1568) --- .github/workflows/gradle.yml | 2 +- azure-pipelines.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e12ca5be8..d02903e8f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -22,4 +22,4 @@ jobs: java-version: 8 cache: 'gradle' - name: Build with Gradle - run: ./gradlew clean build -x signMavenJavaPublication -x test -x checkstyleTest + run: ./gradlew clean build -x test -x checkstyleTest diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 91256cf5c..3f0b0dd1c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -42,7 +42,7 @@ jobs: jdkArchitectureOption: 'x64' publishJUnitResults: true tasks: 'build' - options: 'uiAutomationTest -x checkstyleTest -x test -x signMavenJavaPublication' + options: 'uiAutomationTest -x checkstyleTest -x test' - job: iOS_E2E_Tests # timeoutInMinutes: '90' steps: @@ -60,4 +60,4 @@ jobs: jdkArchitectureOption: 'x64' publishJUnitResults: true tasks: 'build' - options: 'xcuiTest -x checkstyleTest -x test -x signMavenJavaPublication' + options: 'xcuiTest -x checkstyleTest -x test' From c3e891638350f385a6dba6c4d29cc1af65057dc7 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 31 Oct 2021 13:03:46 +0100 Subject: [PATCH 027/501] chore: Include more tests into the pipeline (#1566) --- azure-pipelines.yml | 13 +- build.gradle | 23 ++- .../android/options/EspressoOptions.java | 2 + .../android/options/app/ActivityOptions.java | 3 +- .../options/server/EspressoBuildConfig.java | 93 +++--------- .../SupportsEspressoBuildConfigOption.java | 2 +- .../signing/SupportsKeystoreOptions.java | 2 +- .../ios/options/other/CommandTimeouts.java | 77 ++++++++++ .../other/SupportsCommandTimeoutsOption.java | 41 ++--- .../simulator/PasteboardSyncState.java | 16 ++ .../ios/options/simulator/Permissions.java | 63 ++++++++ .../simulator/SupportsPermissionsOption.java | 47 ++---- .../{RunScript.java => AppleScriptData.java} | 24 +-- .../java_client/mac/options/Mac2Options.java | 57 ++++++- .../mac/options/SupportsPostrunOption.java | 54 ------- .../mac/options/SupportsPrerunOption.java | 54 ------- .../remote/options/BaseMapOptionData.java | 15 +- .../remote/options/SupportsPostrunOption.java | 30 ++++ .../remote/options/SupportsPrerunOption.java | 30 ++++ .../remote/options/SystemScript.java | 45 ++++++ .../{RunScript.java => PowerShellData.java} | 24 +-- .../options/SupportsPostrunOption.java | 55 ------- .../windows/options/SupportsPrerunOption.java | 55 ------- .../windows/options/WindowsOptions.java | 59 +++++++- .../drivers/options/OptionsBuildingTest.java | 143 ++++++++++++++++++ .../local/AppiumDriverLocalServiceTest.java | 40 ----- ...ava => StartingAppLocallyAndroidTest.java} | 91 +---------- .../local/StartingAppLocallyIosTest.java | 107 +++++++++++++ .../java_client/touch/FailsWithMatcher.java | 2 +- .../java_client/touch/TouchOptionsTests.java | 3 +- 30 files changed, 755 insertions(+), 515 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ios/options/other/CommandTimeouts.java create mode 100644 src/main/java/io/appium/java_client/ios/options/simulator/Permissions.java rename src/main/java/io/appium/java_client/mac/options/{RunScript.java => AppleScriptData.java} (72%) delete mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java delete mode 100644 src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsPostrunOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsPrerunOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SystemScript.java rename src/main/java/io/appium/java_client/windows/options/{RunScript.java => PowerShellData.java} (73%) delete mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java delete mode 100644 src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java create mode 100644 src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java delete mode 100644 src/test/java/io/appium/java_client/service/local/AppiumDriverLocalServiceTest.java rename src/test/java/io/appium/java_client/service/local/{StartingAppLocallyTest.java => StartingAppLocallyAndroidTest.java} (57%) create mode 100644 src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3f0b0dd1c..67d36f46e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,7 +19,6 @@ variables: jobs: - job: Android_E2E_Tests -# timeoutInMinutes: '90' steps: - template: .azure-templates/bootstrap_steps.yml - script: | @@ -61,3 +60,15 @@ jobs: publishJUnitResults: true tasks: 'build' options: 'xcuiTest -x checkstyleTest -x test' +- job: Misc_Tests + steps: + - task: Gradle@2 + inputs: + gradleWrapperFile: 'gradlew' + gradleOptions: '-Xmx3072m' + javaHomeOption: 'JDKVersion' + jdkVersionOption: "$(JDK_VERSION)" + jdkArchitectureOption: 'x64' + publishJUnitResults: true + tasks: 'build' + options: 'miscTest -x checkstyleTest -x test -x signMavenJavaPublication' diff --git a/build.gradle b/build.gradle index b26a68384..4cd6ab8de 100644 --- a/build.gradle +++ b/build.gradle @@ -189,15 +189,11 @@ task xcuiTest( type: Test ) { testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { - includeTestsMatching '*.appium.element.generation.ios.*' - includeTestsMatching '*.appium.AppiumFluentWaitTest' includeTestsMatching 'io.appium.java_client.ios.*' includeTestsMatching '*.pagefactory_tests.XCUITModeTest' includeTestsMatching '*.pagefactory_tests.widget.tests.combined.*' includeTestsMatching '*.pagefactory_tests.widget.tests.ios.*' - includeTestsMatching '*.StartingAppLocallyTest.startingIOSAppWithCapabilitiesAndServiceTest' - includeTestsMatching '*.StartingAppLocallyTest.startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest' - exclude '**/UIAutomationTest.class' + includeTestsMatching 'io.appium.java_client.service.local.StartingAppLocallyIosTest' exclude '**/IOSScreenRecordTest.class' exclude '**/ImagesComparisonTest.class' } @@ -211,5 +207,22 @@ task uiAutomationTest( type: Test ) { includeTestsMatching 'io.appium.java_client.android.SettingTest' includeTestsMatching 'io.appium.java_client.android.ClipboardTest' includeTestsMatching '*.AndroidAppStringsTest' + includeTestsMatching '*.pagefactory_tests.widget.tests.android.*' + includeTestsMatching '*.pagefactory_tests.widget.tests.AndroidPageObjectTest' + includeTestsMatching 'io.appium.java_client.service.local.StartingAppLocallyAndroidTest' + includeTestsMatching 'io.appium.java_client.service.local.ServerBuilderTest' + includeTestsMatching 'io.appium.java_client.service.local.ThreadSafetyTest' + } +} + +task miscTest( type: Test ) { + useJUnit() + testLogging.showStandardStreams = true + testLogging.exceptionFormat = 'full' + filter { + includeTestsMatching 'io.appium.java_client.touch.*' + includeTestsMatching 'io.appium.java_client.events.*' + includeTestsMatching 'io.appium.java_client.remote.*' + includeTestsMatching 'io.appium.java_client.drivers.options.*' } } diff --git a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java index 6d3df918d..0baebf02f 100644 --- a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java +++ b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java @@ -75,6 +75,7 @@ import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption; import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption; import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption; +import io.appium.java_client.android.options.server.SupportsEspressoBuildConfigOption; import io.appium.java_client.android.options.server.SupportsEspressoServerLaunchTimeoutOption; import io.appium.java_client.android.options.server.SupportsForceEspressoRebuildOption; import io.appium.java_client.android.options.server.SupportsShowGradleLogOption; @@ -113,6 +114,7 @@ public class EspressoOptions extends BaseOptions implements SupportsForceEspressoRebuildOption, SupportsShowGradleLogOption, SupportsOrientationOption, + SupportsEspressoBuildConfigOption, // App options: https://github.com/appium/appium-uiautomator2-driver#app SupportsAppOption, SupportsAppPackageOption, diff --git a/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java b/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java index de328149f..6a3db25d7 100644 --- a/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java +++ b/src/main/java/io/appium/java_client/android/options/app/ActivityOptions.java @@ -16,6 +16,7 @@ package io.appium.java_client.android.options.app; +import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.remote.options.BaseMapOptionData; import java.util.Map; @@ -48,6 +49,6 @@ public ActivityOptions withLaunchDisplayId(int id) { */ public Optional getLaunchDisplayId() { Optional result = getOptionValue("launchDisplayId"); - return result.map((v) -> Integer.parseInt(String.valueOf(v))); + return result.map(CapabilityHelpers::toInteger); } } diff --git a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java index 28763a79a..209cdcac2 100644 --- a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java +++ b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java @@ -16,57 +16,42 @@ package io.appium.java_client.android.options.server; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseMapOptionData; -import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; -public class EspressoBuildConfig { +public class EspressoBuildConfig extends BaseMapOptionData { public static final String TOOLS_VERSION = "toolsVersions"; public static final String ADDITIONAL_APP_DEPENDENCIES = "additionalAppDependencies"; public static final String ADDITIONAL_ANDROID_TEST_DEPENDENCIES = "additionalAndroidTestDependencies"; - private JsonObject json; - public EspressoBuildConfig() { - } - - public EspressoBuildConfig(JsonObject json) { - this.json = json; + super(); } public EspressoBuildConfig(String json) { - this(JsonParser.parseString(json).getAsJsonObject()); + super(json); } private EspressoBuildConfig assignToolsVersionsField(String name, Object value) { - if (json == null) { - json = new JsonObject(); - } - boolean hasTools = json.has(TOOLS_VERSION); - JsonObject toolsVersions = hasTools - ? json.getAsJsonObject(TOOLS_VERSION) - : new JsonObject(); - if (value instanceof Number) { - toolsVersions.addProperty(name, (Number) value); - } else { - toolsVersions.addProperty(name, String.valueOf(value)); - } - if (!hasTools) { - json.add(TOOLS_VERSION, toolsVersions); + Optional> toolsVersionsOptional = getOptionValue(TOOLS_VERSION); + Map toolsVersions = toolsVersionsOptional.orElseGet(HashMap::new); + toolsVersions.put(name, value); + if (!toolsVersionsOptional.isPresent()) { + assignOptionValue(TOOLS_VERSION, toolsVersions); } return this; } private Optional getToolsVersionsFieldValue(String name) { + Optional> toolsVersionsOptional = getOptionValue(TOOLS_VERSION); //noinspection unchecked - return json == null || !json.has(TOOLS_VERSION) - ? Optional.empty() - : Optional.ofNullable((R) json.getAsJsonObject(TOOLS_VERSION).get(name)); + return toolsVersionsOptional.map((v) -> (R) v.getOrDefault(name, null)); } /** @@ -167,7 +152,7 @@ public EspressoBuildConfig withMinSdk(int apiLevel) { */ public Optional getMinSdkVersion() { Optional result = getToolsVersionsFieldValue("minSdk"); - return result.map((v) -> Integer.parseInt(String.valueOf(v))); + return result.map(CapabilityHelpers::toInteger); } /** @@ -188,7 +173,7 @@ public EspressoBuildConfig withTargetSdk(int apiLevel) { */ public Optional getTargetSdkVersion() { Optional result = getToolsVersionsFieldValue("targetSdk"); - return result.map((v) -> Integer.parseInt(String.valueOf(v))); + return result.map(CapabilityHelpers::toInteger); } /** @@ -211,35 +196,6 @@ public Optional getKotlinVersion() { return getToolsVersionsFieldValue("kotlin"); } - private EspressoBuildConfig assignDependenciesField(String name, List value) { - if (json == null) { - json = new JsonObject(); - } - boolean hasField = json.has(name); - JsonArray dependencies = hasField - ? json.getAsJsonArray(name) - : new JsonArray(); - while (dependencies.size() > 0) { - dependencies.remove(0); - } - value.forEach(dependencies::add); - if (!hasField) { - json.add(name, dependencies); - } - return this; - } - - private Optional> getDependenciesValue(String name) { - return json == null - ? Optional.empty() - : Optional.ofNullable(json.getAsJsonArray(name)) - .map((v) -> { - List result = new ArrayList<>(); - v.forEach((x) -> result.add(String.valueOf(x))); - return result; - }); - } - /** * Set a non-empty array of dependent module names with their versions. * The scripts add all these items as "implementation" lines of dependencies @@ -249,7 +205,7 @@ private Optional> getDependenciesValue(String name) { * @return self instance for chaining. */ public EspressoBuildConfig withAdditionalAppDependencies(List dependencies) { - return assignDependenciesField(ADDITIONAL_APP_DEPENDENCIES, dependencies); + return assignOptionValue(ADDITIONAL_APP_DEPENDENCIES, dependencies); } /** @@ -258,7 +214,7 @@ public EspressoBuildConfig withAdditionalAppDependencies(List dependenci * @return Dependent module names with their versions. */ public Optional> getAdditionalAppDependencies() { - return getDependenciesValue(ADDITIONAL_APP_DEPENDENCIES); + return getOptionValue(ADDITIONAL_APP_DEPENDENCIES); } /** @@ -270,7 +226,7 @@ public Optional> getAdditionalAppDependencies() { * @return self instance for chaining. */ public EspressoBuildConfig withAdditionalAndroidTestDependencies(List dependencies) { - return assignDependenciesField(ADDITIONAL_ANDROID_TEST_DEPENDENCIES, dependencies); + return assignOptionValue(ADDITIONAL_ANDROID_TEST_DEPENDENCIES, dependencies); } /** @@ -279,15 +235,6 @@ public EspressoBuildConfig withAdditionalAndroidTestDependencies(List de * @return Dependent module names with their versions. */ public Optional> getAdditionalAndroidTestDependencies() { - return getDependenciesValue(ADDITIONAL_ANDROID_TEST_DEPENDENCIES); - } - - public JsonObject toJson() { - return Optional.ofNullable(json).orElseGet(JsonObject::new); - } - - @Override - public String toString() { - return toJson().toString(); + return getOptionValue(ADDITIONAL_ANDROID_TEST_DEPENDENCIES); } } diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java index 9444bc9ef..93eb19831 100644 --- a/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java @@ -50,7 +50,7 @@ default T setEspressoBuildConfig(String configPath) { * @return self instance for chaining. */ default T setEspressoBuildConfig(EspressoBuildConfig config) { - return amend(ESPRESSO_BUILD_CONFIG_OPTION, config.toJson().toString()); + return amend(ESPRESSO_BUILD_CONFIG_OPTION, config.toString()); } /** diff --git a/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java b/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java index 4a79dbc67..5fbfcc2ce 100644 --- a/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java +++ b/src/main/java/io/appium/java_client/android/options/signing/SupportsKeystoreOptions.java @@ -38,7 +38,7 @@ public interface SupportsKeystoreOptions> extends * @param keystoreConfig The keystore config to use. * @return self instance for chaining. */ - default T useKeystore(KeystoreConfig keystoreConfig) { + default T setKeystoreConfig(KeystoreConfig keystoreConfig) { return amend(USE_KEYSTORE_OPTION, true) .amend(KEYSTORE_PATH_OPTION, keystoreConfig.getPath()) .amend(KEYSTORE_PASSWORD_OPTION, keystoreConfig.getPassword()) diff --git a/src/main/java/io/appium/java_client/ios/options/other/CommandTimeouts.java b/src/main/java/io/appium/java_client/ios/options/other/CommandTimeouts.java new file mode 100644 index 000000000..36b435a90 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/other/CommandTimeouts.java @@ -0,0 +1,77 @@ +/* + * 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.options.other; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseMapOptionData; + +import java.time.Duration; +import java.util.Map; +import java.util.Optional; + +public class CommandTimeouts extends BaseMapOptionData { + public static final String DEFAULT_COMMAND = "default"; + + public CommandTimeouts() { + } + + public CommandTimeouts(Map timeouts) { + super(timeouts); + } + + public CommandTimeouts(String json) { + super(json); + } + + /** + * Sets the timeout for the particular Appium command that + * is proxied to WDA. + * Command names you can find in logs, look for + * "Executing command 'command_name'" records. + * Timeout value is expected to contain max milliseconds to wait for + * the given WDA command to be executed before terminating the session forcefully. + * + * @param commandName The command name. + * @param timeout Command timeout. + * @return self instance for chaining. + */ + public CommandTimeouts withCommandTimeout(String commandName, Duration timeout) { + return assignOptionValue(commandName, timeout.toMillis()); + } + + /** + * Sets the default timeout for all Appium commands that + * are proxied to WDA. + * + * @param timeout Commands timeout. + * @return self instance for chaining. + */ + public CommandTimeouts withDefaultCommandTimeout(Duration timeout) { + return withCommandTimeout(DEFAULT_COMMAND, timeout); + } + + /** + * Get the command timeout. + * + * @param commandName The command name + * @return Timeout value. + */ + public Optional getCommandTimeout(String commandName) { + Optional result = getOptionValue(commandName); + return result.map(CapabilityHelpers::toDuration); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java index 42935504b..0afd1a9a8 100644 --- a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java @@ -16,14 +16,16 @@ package io.appium.java_client.ios.options.other; -import com.google.gson.JsonObject; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.internal.Either; import java.time.Duration; import java.util.Optional; +import static io.appium.java_client.internal.CapabilityHelpers.toDuration; + public interface SupportsCommandTimeoutsOption> extends Capabilities, CanSetCapability { String COMMAND_TIMEOUTS_OPTION = "commandTimeouts"; @@ -31,33 +33,19 @@ public interface SupportsCommandTimeoutsOption> extends /** * Custom timeout(s) in milliseconds for WDA backend commands execution. * This might be useful if WDA backend freezes unexpectedly or requires too - * much time to fail and blocks automated test execution. The value is expected - * to be of type string and can either contain max milliseconds to wait for - * each WDA command to be executed before terminating the session forcefully - * or a valid JSON string, where keys are internal Appium command names (you - * can find these in logs, look for "Executing command 'command_name'" records) - * and values are timeouts in milliseconds. You can also set the 'default' key - * to assign the timeout for all other commands not explicitly enumerated as - * JSON keys. + * much time to fail and blocks automated test execution. * - * @param timeouts E.g. '{"findElement": 40000, "findElements": 40000}'. + * @param timeouts Command timeouts. * @return self instance for chaining. */ - default T setCommandTimeouts(JsonObject timeouts) { + default T setCommandTimeouts(CommandTimeouts timeouts) { return amend(COMMAND_TIMEOUTS_OPTION, timeouts.toString()); } /** - * Custom timeout(s) in milliseconds for WDA backend commands execution. + * Custom timeout for all WDA backend commands execution. * This might be useful if WDA backend freezes unexpectedly or requires too - * much time to fail and blocks automated test execution. The value is expected - * to be of type string and can either contain max milliseconds to wait for - * each WDA command to be executed before terminating the session forcefully - * or a valid JSON string, where keys are internal Appium command names (you - * can find these in logs, look for "Executing command 'command_name'" records) - * and values are timeouts in milliseconds. You can also set the 'default' key - * to assign the timeout for all other commands not explicitly enumerated as - * JSON keys. + * much time to fail and blocks automated test execution. * * @param timeout The timeout value for all commands. * @return self instance for chaining. @@ -69,11 +57,14 @@ default T setCommandTimeouts(Duration timeout) { /** * Get custom timeout(s) in milliseconds for WDA backend commands execution. * - * @return Command timeouts. + * @return Either a global timeout duration or detailed command timeouts. */ - default Optional getCommandTimeouts() { - return Optional.ofNullable( - (String) getCapability(COMMAND_TIMEOUTS_OPTION) - ); + default Optional> getCommandTimeouts() { + return Optional.ofNullable(getCapability(COMMAND_TIMEOUTS_OPTION)) + .map(String::valueOf) + .map((v) -> v.trim().startsWith("{") + ? Either.left(new CommandTimeouts(v)) + : Either.right(toDuration(v)) + ); } } diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java b/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java index 2252a37bf..885229dd8 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/PasteboardSyncState.java @@ -1,3 +1,19 @@ +/* + * 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.options.simulator; public enum PasteboardSyncState { diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/Permissions.java b/src/main/java/io/appium/java_client/ios/options/simulator/Permissions.java new file mode 100644 index 000000000..53094e5ab --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/simulator/Permissions.java @@ -0,0 +1,63 @@ +/* + * 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.options.simulator; + +import io.appium.java_client.remote.options.BaseMapOptionData; + +import java.util.Map; +import java.util.Optional; + +public class Permissions extends BaseMapOptionData { + public Permissions() { + } + + public Permissions(Map permissions) { + super(permissions); + } + + public Permissions(String json) { + super(json); + } + + /** + * Since Xcode SDK 11.4 Apple provides native APIs to interact with + * application settings. Check the output of `xcrun simctl privacy booted` + * command to get the list of available permission names. Use yes, no + * and unset as values in order to grant, revoke or reset the corresponding + * permission. Below Xcode SDK 11.4 it is required that applesimutils package + * is installed and available in PATH. The list of available service names + * and statuses can be found at https://github.com/wix/AppleSimulatorUtils. + * For example: {"com.apple.mobilecal": {"calendar": "YES"}} + * + * @param bundleId The app identifier to change permissions for. + * @param mapping Permissions mapping, where keys are perm names and vales are YES/NO. + * @return self instance for chaining. + */ + public Permissions withAppPermissions(String bundleId, Map mapping) { + return assignOptionValue(bundleId, mapping); + } + + /** + * Get permissions mapping for the given app bundle identifier. + * + * @param bundleId App bundle identifier. + * @return Permissions mapping. + */ + public Optional> getAppPermissions(String bundleId) { + return getOptionValue(bundleId); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java index 2aca0a82a..e3a4b36c2 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java @@ -16,7 +16,6 @@ package io.appium.java_client.ios.options.simulator; -import com.google.gson.JsonObject; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; @@ -28,49 +27,23 @@ public interface SupportsPermissionsOption> extends String PERMISSIONS_OPTION = "permissions"; /** - * Allows to set permissions for the specified application bundle on - * Simulator only. The capability value is expected to be a valid JSON - * with {"bundleId1": {"serviceName1": "serviceStatus1", ...}, ...} - * format. Since Xcode SDK 11.4 Apple provides native APIs to interact with - * application settings. Check the output of xcrun simctl privacy booted - * command to get the list of available permission names. Use yes, no - * and unset as values in order to grant, revoke or reset the corresponding - * permission. Below Xcode SDK 11.4 it is required that applesimutils package - * is installed and available in PATH. The list of available service names - * and statuses can be found at https://github.com/wix/AppleSimulatorUtils. + * Allows setting of permissions for the specified application bundle on + * Simulator only. * - * @param json For example {"com.apple.mobilecal": {"calendar": "YES"}} + * @param permissions Permissions mapping. * @return self instance for chaining. */ - default T setPermissions(JsonObject json) { - return amend(PERMISSIONS_OPTION, json.toString()); + default T setPermissions(Permissions permissions) { + return amend(PERMISSIONS_OPTION, permissions.toString()); } /** - * Allows to set permissions for the specified application bundle on - * Simulator only. The capability value is expected to be a valid JSON - * string with {"bundleId1": {"serviceName1": "serviceStatus1", ...}, ...} - * format. Since Xcode SDK 11.4 Apple provides native APIs to interact with - * application settings. Check the output of xcrun simctl privacy booted - * command to get the list of available permission names. Use yes, no - * and unset as values in order to grant, revoke or reset the corresponding - * permission. Below Xcode SDK 11.4 it is required that applesimutils package - * is installed and available in PATH. The list of available service names - * and statuses can be found at https://github.com/wix/AppleSimulatorUtils. + * Get Simulator permissions. * - * @param json For example {"com.apple.mobilecal": {"calendar": "YES"}} - * @return self instance for chaining. - */ - default T setPermissions(String json) { - return amend(PERMISSIONS_OPTION, json); - } - - /** - * Get Simulator permissions.. - * - * @return Permissions json. + * @return Permissions object. */ - default Optional getPermissions() { - return Optional.ofNullable((String) getCapability(PERMISSIONS_OPTION)); + default Optional getPermissions() { + return Optional.ofNullable(getCapability(PERMISSIONS_OPTION)) + .map((v) -> new Permissions(String.valueOf(v))); } } diff --git a/src/main/java/io/appium/java_client/mac/options/RunScript.java b/src/main/java/io/appium/java_client/mac/options/AppleScriptData.java similarity index 72% rename from src/main/java/io/appium/java_client/mac/options/RunScript.java rename to src/main/java/io/appium/java_client/mac/options/AppleScriptData.java index 4960d7e86..91b74aa98 100644 --- a/src/main/java/io/appium/java_client/mac/options/RunScript.java +++ b/src/main/java/io/appium/java_client/mac/options/AppleScriptData.java @@ -16,16 +16,16 @@ package io.appium.java_client.mac.options; -import io.appium.java_client.remote.options.BaseMapOptionData; +import io.appium.java_client.remote.options.SystemScript; import java.util.Map; import java.util.Optional; -public class RunScript extends BaseMapOptionData { - public RunScript() { +public class AppleScriptData extends SystemScript { + public AppleScriptData() { } - public RunScript(Map options) { + public AppleScriptData(Map options) { super(options); } @@ -35,8 +35,9 @@ public RunScript(Map options) { * @param script A valid AppleScript. * @return self instance for chaining. */ - public RunScript withScript(String script) { - return assignOptionValue("script", script); + @Override + public AppleScriptData withScript(String script) { + return super.withScript(script); } /** @@ -44,8 +45,9 @@ public RunScript withScript(String script) { * * @return AppleScript snippet. */ + @Override public Optional getScript() { - return getOptionValue("script"); + return super.getScript(); } /** @@ -54,8 +56,9 @@ public Optional getScript() { * @param command A valid AppleScript. * @return self instance for chaining. */ - public RunScript withCommand(String command) { - return assignOptionValue("command", command); + @Override + public AppleScriptData withCommand(String command) { + return super.withCommand(command); } /** @@ -63,7 +66,8 @@ public RunScript withCommand(String command) { * * @return AppleScript snippet. */ + @Override public Optional getCommand() { - return getOptionValue("command"); + return super.getCommand(); } } diff --git a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java index 47214f677..37e31575a 100644 --- a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java +++ b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java @@ -19,9 +19,12 @@ import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsPostrunOption; +import io.appium.java_client.remote.options.SupportsPrerunOption; import org.openqa.selenium.Capabilities; import java.util.Map; +import java.util.Optional; /** * https://github.com/appium/appium-mac2-driver#capabilities @@ -37,8 +40,8 @@ public class Mac2Options extends BaseOptions implements SupportsServerStartupTimeoutOption, SupportsSkipAppKillOption, SupportsShowServerLogsOption, - SupportsPrerunOption, - SupportsPostrunOption { + SupportsPrerunOption, + SupportsPostrunOption { public Mac2Options() { setCommonOptions(); } @@ -57,4 +60,54 @@ private void setCommonOptions() { setPlatformName(MobilePlatform.MAC); setAutomationName(AutomationName.MAC2); } + + /** + * An object containing either script or command key. The value of + * each key must be a valid AppleScript script or command to be + * executed after before Mac2Driver session is started. See + * https://github.com/appium/appium-mac2-driver#applescript-commands-execution + * for more details. + * + * @param script A valid AppleScript snippet. + * @return self instance for chaining. + */ + public Mac2Options setPrerun(AppleScriptData script) { + return amend(PRERUN_OPTION, script.toMap()); + } + + /** + * Get the prerun script. + * + * @return Prerun script. + */ + public Optional getPrerun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(PRERUN_OPTION)) + .map((v) -> new AppleScriptData((Map) v)); + } + + /** + * An object containing either script or command key. The value of + * each key must be a valid AppleScript script or command to be + * executed after Mac2Driver session is stopped. See + * https://github.com/appium/appium-mac2-driver#applescript-commands-execution + * for more details. + * + * @param script A valid AppleScript snippet. + * @return self instance for chaining. + */ + public Mac2Options setPostrun(AppleScriptData script) { + return amend(POSTRUN_OPTION, script.toMap()); + } + + /** + * Get the postrun script. + * + * @return Postrun script. + */ + public Optional getPostrun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(POSTRUN_OPTION)) + .map((v) -> new AppleScriptData((Map) v)); + } } diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java deleted file mode 100644 index 69430019b..000000000 --- a/src/main/java/io/appium/java_client/mac/options/SupportsPostrunOption.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.mac.options; - -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; -import org.openqa.selenium.Capabilities; - -import java.util.Map; -import java.util.Optional; - -public interface SupportsPostrunOption> extends - Capabilities, CanSetCapability { - String POSTRUN_OPTION = "postrun"; - - /** - * An object containing either script or command key. The value of - * each key must be a valid AppleScript script or command to be - * executed after Mac2Driver session is stopped. See - * https://github.com/appium/appium-mac2-driver#applescript-commands-execution - * for more details. - * - * @param script A valid AppleScript snippet. - * @return self instance for chaining. - */ - default T setPostrun(RunScript script) { - return amend(POSTRUN_OPTION, script.toMap()); - } - - /** - * Get the postrun script. - * - * @return Postrun script. - */ - default Optional getPostrun() { - //noinspection unchecked - return Optional.ofNullable(getCapability(POSTRUN_OPTION)) - .map((v) -> new RunScript((Map) v)); - } -} diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java deleted file mode 100644 index 61b8d0897..000000000 --- a/src/main/java/io/appium/java_client/mac/options/SupportsPrerunOption.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.mac.options; - -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; -import org.openqa.selenium.Capabilities; - -import java.util.Map; -import java.util.Optional; - -public interface SupportsPrerunOption> extends - Capabilities, CanSetCapability { - String PRERUN_OPTION = "prerun"; - - /** - * An object containing either script or command key. The value of - * each key must be a valid AppleScript script or command to be - * executed after before Mac2Driver session is started. See - * https://github.com/appium/appium-mac2-driver#applescript-commands-execution - * for more details. - * - * @param script A valid AppleScript snippet. - * @return self instance for chaining. - */ - default T setPrerun(RunScript script) { - return amend(PRERUN_OPTION, script.toMap()); - } - - /** - * Get the prerun script. - * - * @return Prerun script. - */ - default Optional getPrerun() { - //noinspection unchecked - return Optional.ofNullable(getCapability(PRERUN_OPTION)) - .map((v) -> new RunScript((Map) v)); - } -} diff --git a/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java b/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java index 004d1bdf5..a7b75e3d7 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java @@ -16,7 +16,8 @@ package io.appium.java_client.remote.options; -import com.google.gson.GsonBuilder; +import com.google.gson.Gson; +import com.google.gson.JsonObject; import java.util.Collections; import java.util.HashMap; @@ -25,6 +26,7 @@ public abstract class BaseMapOptionData> { private Map options; + private static final Gson gson = new Gson(); public BaseMapOptionData() { } @@ -33,6 +35,11 @@ public BaseMapOptionData(Map options) { this.options = options; } + public BaseMapOptionData(String json) { + //noinspection unchecked + this((Map) gson.fromJson(json, Map.class)); + } + /** * Sets the given value on the data object. * @@ -70,8 +77,12 @@ public Map toMap() { return Optional.ofNullable(options).orElseGet(Collections::emptyMap); } + public JsonObject toJson() { + return gson.toJsonTree(toMap()).getAsJsonObject(); + } + @Override public String toString() { - return new GsonBuilder().create().toJson(toMap()); + return gson.toJson(toMap()); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsPostrunOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsPostrunOption.java new file mode 100644 index 000000000..e055cb69f --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsPostrunOption.java @@ -0,0 +1,30 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsPostrunOption, S extends SystemScript> + extends Capabilities, CanSetCapability { + String POSTRUN_OPTION = "postrun"; + + T setPostrun(S script); + + Optional getPostrun(); +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsPrerunOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsPrerunOption.java new file mode 100644 index 000000000..a44d2c53f --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsPrerunOption.java @@ -0,0 +1,30 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsPrerunOption, S extends SystemScript> + extends Capabilities, CanSetCapability { + String PRERUN_OPTION = "prerun"; + + T setPrerun(S script); + + Optional getPrerun(); +} diff --git a/src/main/java/io/appium/java_client/remote/options/SystemScript.java b/src/main/java/io/appium/java_client/remote/options/SystemScript.java new file mode 100644 index 000000000..901d8e220 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SystemScript.java @@ -0,0 +1,45 @@ +/* + * 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.remote.options; + +import java.util.Map; +import java.util.Optional; + +public abstract class SystemScript> extends BaseMapOptionData { + public SystemScript() { + } + + public SystemScript(Map options) { + super(options); + } + + public T withScript(String script) { + return assignOptionValue("script", script); + } + + public Optional getScript() { + return getOptionValue("script"); + } + + public T withCommand(String command) { + return assignOptionValue("command", command); + } + + public Optional getCommand() { + return getOptionValue("command"); + } +} diff --git a/src/main/java/io/appium/java_client/windows/options/RunScript.java b/src/main/java/io/appium/java_client/windows/options/PowerShellData.java similarity index 73% rename from src/main/java/io/appium/java_client/windows/options/RunScript.java rename to src/main/java/io/appium/java_client/windows/options/PowerShellData.java index e31fa38fc..6dc97f495 100644 --- a/src/main/java/io/appium/java_client/windows/options/RunScript.java +++ b/src/main/java/io/appium/java_client/windows/options/PowerShellData.java @@ -16,16 +16,16 @@ package io.appium.java_client.windows.options; -import io.appium.java_client.remote.options.BaseMapOptionData; +import io.appium.java_client.remote.options.SystemScript; import java.util.Map; import java.util.Optional; -public class RunScript extends BaseMapOptionData { - public RunScript() { +public class PowerShellData extends SystemScript { + public PowerShellData() { } - public RunScript(Map options) { + public PowerShellData(Map options) { super(options); } @@ -35,8 +35,9 @@ public RunScript(Map options) { * @param script A valid PowerShell script. * @return self instance for chaining. */ - public RunScript withScript(String script) { - return assignOptionValue("script", script); + @Override + public PowerShellData withScript(String script) { + return super.withScript(script); } /** @@ -44,8 +45,9 @@ public RunScript withScript(String script) { * * @return PowerShell script. */ + @Override public Optional getScript() { - return getOptionValue("script"); + return super.getScript(); } /** @@ -54,8 +56,9 @@ public Optional getScript() { * @param command A valid PowerShell script. * @return self instance for chaining. */ - public RunScript withCommand(String command) { - return assignOptionValue("command", command); + @Override + public PowerShellData withCommand(String command) { + return super.withCommand(command); } /** @@ -63,7 +66,8 @@ public RunScript withCommand(String command) { * * @return PowerShell script. */ + @Override public Optional getCommand() { - return getOptionValue("command"); + return super.getCommand(); } } diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java deleted file mode 100644 index b766820c3..000000000 --- a/src/main/java/io/appium/java_client/windows/options/SupportsPostrunOption.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.windows.options; - -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; -import org.openqa.selenium.Capabilities; - -import java.util.Map; -import java.util.Optional; - -public interface SupportsPostrunOption> extends - Capabilities, CanSetCapability { - String POSTRUN_OPTION = "postrun"; - - /** - * An object containing either script or command key. The value of - * each key must be a valid PowerShell script or command to be - * executed after an WinAppDriver session is finished. - * See - * https://github.com/appium/appium-windows-driver#power-shell-commands-execution - * for more details. - * - * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. - * @return self instance for chaining. - */ - default T setPostrun(RunScript script) { - return amend(POSTRUN_OPTION, script.toMap()); - } - - /** - * Get the postrun script. - * - * @return Postrun script. - */ - default Optional getPostrun() { - //noinspection unchecked - return Optional.ofNullable(getCapability(POSTRUN_OPTION)) - .map((v) -> new RunScript((Map) v)); - } -} diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java deleted file mode 100644 index d3722da48..000000000 --- a/src/main/java/io/appium/java_client/windows/options/SupportsPrerunOption.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.windows.options; - -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; -import org.openqa.selenium.Capabilities; - -import java.util.Map; -import java.util.Optional; - -public interface SupportsPrerunOption> extends - Capabilities, CanSetCapability { - String PRERUN_OPTION = "prerun"; - - /** - * An object containing either script or command key. The value of - * each key must be a valid PowerShell script or command to be - * executed prior to the WinAppDriver session startup. - * See - * https://github.com/appium/appium-windows-driver#power-shell-commands-execution - * for more details. - * - * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. - * @return self instance for chaining. - */ - default T setPrerun(RunScript script) { - return amend(PRERUN_OPTION, script.toMap()); - } - - /** - * Get the prerun script. - * - * @return Prerun script. - */ - default Optional getPrerun() { - //noinspection unchecked - return Optional.ofNullable(getCapability(PRERUN_OPTION)) - .map((v) -> new RunScript((Map) v)); - } -} diff --git a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java index 0d25a1ece..8a1f0eb8f 100644 --- a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java +++ b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java @@ -20,9 +20,12 @@ import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.remote.options.SupportsAppOption; +import io.appium.java_client.remote.options.SupportsPostrunOption; +import io.appium.java_client.remote.options.SupportsPrerunOption; import org.openqa.selenium.Capabilities; import java.util.Map; +import java.util.Optional; /** * https://github.com/appium/appium-windows-driver#usage @@ -36,8 +39,8 @@ public class WindowsOptions extends BaseOptions implements SupportsMsWaitForAppLaunchOption, SupportsMsExperimentalWebDriverOption, SupportsSystemPortOption, - SupportsPrerunOption, - SupportsPostrunOption { + SupportsPrerunOption, + SupportsPostrunOption { public WindowsOptions() { setCommonOptions(); } @@ -56,4 +59,56 @@ private void setCommonOptions() { setPlatformName(MobilePlatform.WINDOWS); setAutomationName(AutomationName.WINDOWS); } + + /** + * An object containing either script or command key. The value of + * each key must be a valid PowerShell script or command to be + * executed prior to the WinAppDriver session startup. + * See + * https://github.com/appium/appium-windows-driver#power-shell-commands-execution + * for more details. + * + * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. + * @return self instance for chaining. + */ + public WindowsOptions setPrerun(PowerShellData script) { + return amend(PRERUN_OPTION, script.toMap()); + } + + /** + * Get the prerun script. + * + * @return Prerun script. + */ + public Optional getPrerun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(PRERUN_OPTION)) + .map((v) -> new PowerShellData((Map) v)); + } + + /** + * An object containing either script or command key. The value of + * each key must be a valid PowerShell script or command to be + * executed after an WinAppDriver session is finished. + * See + * https://github.com/appium/appium-windows-driver#power-shell-commands-execution + * for more details. + * + * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. + * @return self instance for chaining. + */ + public WindowsOptions setPostrun(PowerShellData script) { + return amend(POSTRUN_OPTION, script.toMap()); + } + + /** + * Get the postrun script. + * + * @return Postrun script. + */ + public Optional getPostrun() { + //noinspection unchecked + return Optional.ofNullable(getCapability(POSTRUN_OPTION)) + .map((v) -> new PowerShellData((Map) v)); + } } diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java new file mode 100644 index 000000000..9b12ceda9 --- /dev/null +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -0,0 +1,143 @@ +/* + * 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.drivers.options; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.android.options.EspressoOptions; +import io.appium.java_client.android.options.UiAutomator2Options; +import io.appium.java_client.android.options.localization.AppLocale; +import io.appium.java_client.android.options.server.EspressoBuildConfig; +import io.appium.java_client.android.options.signing.KeystoreConfig; +import io.appium.java_client.ios.options.XCUITestOptions; +import io.appium.java_client.ios.options.other.CommandTimeouts; +import io.appium.java_client.ios.options.simulator.Permissions; +import io.appium.java_client.mac.options.AppleScriptData; +import io.appium.java_client.mac.options.Mac2Options; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.windows.options.PowerShellData; +import io.appium.java_client.windows.options.WindowsOptions; +import org.junit.Test; +import org.openqa.selenium.Platform; + +import java.net.MalformedURLException; +import java.net.URL; +import java.time.Duration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@SuppressWarnings("ConstantConditions") +public class OptionsBuildingTest { + @Test + public void canBuildXcuiTestOptions() throws MalformedURLException { + XCUITestOptions options = new XCUITestOptions(); + assertEquals(Platform.IOS, options.getPlatformName()); + assertEquals(AutomationName.IOS_XCUI_TEST, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .noReset() + .setWdaBaseUrl("http://localhost:8000") + .setPermissions(new Permissions() + .withAppPermissions("com.apple.MobileSafari", + ImmutableMap.of("calendar", "YES"))) + .setSafariSocketChunkSize(10) + .setCommandTimeouts(new CommandTimeouts() + .withCommandTimeout("yolo", Duration.ofSeconds(1))); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertEquals(new URL("http://localhost:8000"), options.getWdaBaseUrl().orElse(null)); + assertNotNull(options.getPermissions() + .map((v) -> v.getAppPermissions("com.apple.MobileSafari")) + .orElse(null)); + assertEquals(10L, (long) options.getSafariSocketChunkSize().orElse(0)); + assertEquals(1L, options.getCommandTimeouts().orElse(null).left() + .getCommandTimeout("yolo").orElse(null).getSeconds()); + } + + @Test + public void canBuildUiAutomator2Options() throws MalformedURLException { + UiAutomator2Options options = new UiAutomator2Options(); + assertEquals(Platform.ANDROID, options.getPlatformName()); + assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .noReset() + .setAdbExecTimeout(Duration.ofSeconds(3)) + .suppressKillServer() + .setMjpegScreenshotUrl(new URL("http://yolo.com")) + .setKeystoreConfig(new KeystoreConfig("path", "password", "keyAlias", "keyPassword")); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertEquals(Duration.ofSeconds(3), options.getAdbExecTimeout().orElse(null)); + assertEquals(new URL("http://yolo.com"), options.getMjpegScreenshotUrl().orElse(null)); + assertEquals("path", options.getKeystoreConfig().orElse(null).getPath()); + assertEquals("keyAlias", options.getKeystoreConfig().orElse(null).getKeyAlias()); + assertTrue(options.doesSuppressKillServer().orElse(false)); + } + + @Test + public void canBuildEspressoOptions() { + EspressoOptions options = new EspressoOptions(); + assertEquals(Platform.ANDROID, options.getPlatformName()); + assertEquals(AutomationName.ESPRESSO, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .forceEspressoRebuild() + .setAppLocale(new AppLocale() + .withCountry("CN") + .withLanguage("zh") + .withVariant("hans")) + .setEspressoBuildConfig(new EspressoBuildConfig() + .withAdditionalAppDependencies(ImmutableList.of( + "com.dep1:1.2.3", + "com.dep2:1.2.3" + )) + ); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertEquals("CN", options.getAppLocale().orElse(null).getCountry().orElse(null)); + assertEquals(2, options.getEspressoBuildConfig().orElse(null) + .left().getAdditionalAppDependencies().orElse(null).size()); + assertTrue(options.doesForceEspressoRebuild().orElse(false)); + } + + @Test + public void canBuildWindowsOptions() { + WindowsOptions options = new WindowsOptions(); + assertEquals(Platform.WINDOWS, options.getPlatformName()); + assertEquals(AutomationName.WINDOWS, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .setPrerun(new PowerShellData().withScript("yolo prescript")) + .setPostrun(new PowerShellData().withCommand("yolo command")); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertEquals("yolo prescript", options.getPrerun().orElse(null).getScript().orElse(null)); + assertEquals("yolo command", options.getPostrun().orElse(null).getCommand().orElse(null)); + } + + @Test + public void canBuildMac2Options() { + Mac2Options options = new Mac2Options(); + assertEquals(Platform.MAC, options.getPlatformName()); + assertEquals(AutomationName.MAC2, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .skipAppKill() + .setPrerun(new AppleScriptData().withScript("yolo prescript")) + .setPostrun(new AppleScriptData().withCommand("yolo command")); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertEquals("yolo prescript", options.getPrerun().orElse(null).getScript().orElse(null)); + assertEquals("yolo command", options.getPostrun().orElse(null).getCommand().orElse(null)); + assertTrue(options.doesSkipAppKill().orElse(false)); + assertFalse(options.doesEventTimings().isPresent()); + } +} diff --git a/src/test/java/io/appium/java_client/service/local/AppiumDriverLocalServiceTest.java b/src/test/java/io/appium/java_client/service/local/AppiumDriverLocalServiceTest.java deleted file mode 100644 index e6d51247b..000000000 --- a/src/test/java/io/appium/java_client/service/local/AppiumDriverLocalServiceTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.appium.java_client.service.local; - -import static io.appium.java_client.service.local.AppiumDriverLocalService.parseSlf4jContextFromLogMessage; -import static org.junit.Assert.assertEquals; -import static org.slf4j.LoggerFactory.getLogger; -import static org.slf4j.event.Level.DEBUG; -import static org.slf4j.event.Level.INFO; - -import org.junit.Test; -import org.slf4j.event.Level; - -public class AppiumDriverLocalServiceTest { - - @Test - public void canParseSlf4jLoggerContext() { - assertLoggerContext(INFO, "appium.service.androidbootstrap", - "[AndroidBootstrap] [BOOTSTRAP LOG] [debug] json loading complete."); - assertLoggerContext(INFO, "appium.service.adb", - "[ADB] Cannot read version codes of "); - assertLoggerContext(INFO, "appium.service.xcuitest", - "[XCUITest] Determining device to run tests on: udid: '1234567890', real device: true"); - assertLoggerContext(INFO, "appium.service", - "no-prefix log message."); - assertLoggerContext(INFO, "appium.service", - "no-prefix log [not-a-logger-name] message."); - assertLoggerContext(DEBUG, "appium.service.mjsonwp", - "[debug] [MJSONWP] Calling AppiumDriver.getStatus() with args: []"); - assertLoggerContext(DEBUG, "appium.service.xcuitest", - "[debug] [XCUITest] Xcode version set to 'x.y.z' "); - assertLoggerContext(DEBUG, "appium.service.jsonwpproxy", - "[debug] [JSONWP Proxy] Proxying [GET /status] to [GET http://localhost:18218/status] with no body"); - } - - private void assertLoggerContext(Level expectedLevel, String expectedLoggerName, String logMessage) { - Slf4jLogMessageContext ctx = parseSlf4jContextFromLogMessage(logMessage); - assertEquals(expectedLoggerName, ctx.getName()); - assertEquals(expectedLevel, ctx.getLevel()); - assertEquals(getLogger(expectedLoggerName), ctx.getLogger()); - } -} diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java similarity index 57% rename from src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java rename to src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index 467d6c21f..ee7eb82e2 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -16,19 +16,8 @@ package io.appium.java_client.service.local; -import static io.appium.java_client.TestResources.apiDemosApk; -import static io.appium.java_client.TestResources.uiCatalogAppZip; -import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.options.UiAutomator2Options; -import io.appium.java_client.ios.BaseIOSTest; -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.MobilePlatform; @@ -36,11 +25,16 @@ import io.github.bonigarcia.wdm.WebDriverManager; import org.junit.Test; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.Platform; import java.time.Duration; -public class StartingAppLocallyTest { +import static io.appium.java_client.TestResources.apiDemosApk; +import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class StartingAppLocallyAndroidTest { @Test public void startingAndroidAppWithCapabilitiesOnlyTest() { @@ -118,75 +112,4 @@ public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { driver.quit(); } } - - @Test - public void startingIOSAppWithCapabilitiesOnlyTest() { - XCUITestOptions options = new XCUITestOptions() - .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) - .setDeviceName(BaseIOSTest.DEVICE_NAME) - .setApp(uiCatalogAppZip().toAbsolutePath().toString()) - .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); - IOSDriver driver = new IOSDriver(options); - try { - XCUITestOptions caps = new XCUITestOptions(driver.getCapabilities()); - - assertEquals(AutomationName.IOS_XCUI_TEST, caps.getAutomationName().orElse(null)); - assertEquals(Platform.IOS, caps.getPlatformName()); - assertNotNull(caps.getDeviceName().orElse(null)); - assertEquals(BaseIOSTest.PLATFORM_VERSION, caps.getPlatformVersion().orElse(null)); - assertEquals(uiCatalogAppZip().toAbsolutePath().toString(), caps.getApp().orElse(null)); - } finally { - driver.quit(); - } - } - - - @Test - public void startingIOSAppWithCapabilitiesAndServiceTest() { - XCUITestOptions options = new XCUITestOptions() - .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) - .setDeviceName(BaseIOSTest.DEVICE_NAME) - .setApp(uiCatalogAppZip().toAbsolutePath().toString()) - .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); - - AppiumServiceBuilder builder = new AppiumServiceBuilder() - .withArgument(GeneralServerFlag.SESSION_OVERRIDE) - .withArgument(GeneralServerFlag.STRICT_CAPS); - - IOSDriver driver = new IOSDriver(builder, options); - try { - Capabilities caps = driver.getCapabilities(); - assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) - .toString().equalsIgnoreCase(MobilePlatform.IOS)); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); - } finally { - driver.quit(); - } - } - - @Test - public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { - XCUITestOptions serverOptions = new XCUITestOptions() - .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) - .setDeviceName(BaseIOSTest.DEVICE_NAME) - .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); - - XCUITestOptions clientOptions = new XCUITestOptions() - .setApp(uiCatalogAppZip().toAbsolutePath().toString()); - - AppiumServiceBuilder builder = new AppiumServiceBuilder() - .withArgument(GeneralServerFlag.SESSION_OVERRIDE) - .withArgument(GeneralServerFlag.STRICT_CAPS) - .withCapabilities(serverOptions); - - IOSDriver driver = new IOSDriver(builder, clientOptions); - try { - XCUITestOptions caps = new XCUITestOptions(driver.getCapabilities()); - assertEquals(Platform.IOS, caps.getPlatformName()); - assertNotNull(caps.getDeviceName().orElse(null)); - assertFalse(driver.isBrowser()); - } finally { - driver.quit(); - } - } } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java new file mode 100644 index 000000000..b7bc4786c --- /dev/null +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -0,0 +1,107 @@ +/* + * 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.service.local; + +import static io.appium.java_client.TestResources.uiCatalogAppZip; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import io.appium.java_client.ios.BaseIOSTest; +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.remote.MobilePlatform; +import io.appium.java_client.service.local.flags.GeneralServerFlag; +import org.junit.Test; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; + +public class StartingAppLocallyIosTest { + @Test + public void startingIOSAppWithCapabilitiesOnlyTest() { + XCUITestOptions options = new XCUITestOptions() + .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) + .setDeviceName(BaseIOSTest.DEVICE_NAME) + .setApp(uiCatalogAppZip().toAbsolutePath().toString()) + .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); + IOSDriver driver = new IOSDriver(options); + try { + XCUITestOptions caps = new XCUITestOptions(driver.getCapabilities()); + + assertEquals(AutomationName.IOS_XCUI_TEST, caps.getAutomationName().orElse(null)); + assertEquals(Platform.IOS, caps.getPlatformName()); + assertNotNull(caps.getDeviceName().orElse(null)); + assertEquals(BaseIOSTest.PLATFORM_VERSION, caps.getPlatformVersion().orElse(null)); + assertEquals(uiCatalogAppZip().toAbsolutePath().toString(), caps.getApp().orElse(null)); + } finally { + driver.quit(); + } + } + + + @Test + public void startingIOSAppWithCapabilitiesAndServiceTest() { + XCUITestOptions options = new XCUITestOptions() + .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) + .setDeviceName(BaseIOSTest.DEVICE_NAME) + .setApp(uiCatalogAppZip().toAbsolutePath().toString()) + .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); + + AppiumServiceBuilder builder = new AppiumServiceBuilder() + .withArgument(GeneralServerFlag.SESSION_OVERRIDE) + .withArgument(GeneralServerFlag.STRICT_CAPS); + + IOSDriver driver = new IOSDriver(builder, options); + try { + Capabilities caps = driver.getCapabilities(); + assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) + .toString().equalsIgnoreCase(MobilePlatform.IOS)); + assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + } finally { + driver.quit(); + } + } + + @Test + public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { + XCUITestOptions serverOptions = new XCUITestOptions() + .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) + .setDeviceName(BaseIOSTest.DEVICE_NAME) + .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); + + XCUITestOptions clientOptions = new XCUITestOptions() + .setApp(uiCatalogAppZip().toAbsolutePath().toString()); + + AppiumServiceBuilder builder = new AppiumServiceBuilder() + .withArgument(GeneralServerFlag.SESSION_OVERRIDE) + .withArgument(GeneralServerFlag.STRICT_CAPS) + .withCapabilities(serverOptions); + + IOSDriver driver = new IOSDriver(builder, clientOptions); + try { + XCUITestOptions caps = new XCUITestOptions(driver.getCapabilities()); + assertEquals(Platform.IOS, caps.getPlatformName()); + assertNotNull(caps.getDeviceName().orElse(null)); + assertFalse(driver.isBrowser()); + } finally { + driver.quit(); + } + } +} diff --git a/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java b/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java index 93c1dd804..f4ac4bec8 100644 --- a/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java +++ b/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java @@ -22,7 +22,7 @@ public static Matcher failsWith( public static Matcher failsWith( final Class throwableType, final Matcher throwableMatcher) { - return new FailsWithMatcher<>(allOf(instanceOf(throwableType), throwableMatcher)); + return new FailsWithMatcher(allOf(instanceOf(throwableType), throwableMatcher)); } @Override diff --git a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java index 4476ed33e..1500e2f81 100644 --- a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java +++ b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java @@ -18,7 +18,6 @@ import io.appium.java_client.touch.offset.PointOption; import org.junit.Test; import org.openqa.selenium.Point; -import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; import java.util.ArrayList; @@ -31,7 +30,7 @@ public class TouchOptionsTests { @Test(expected = IllegalArgumentException.class) public void invalidEmptyPointOptionsShouldFailOnBuild() { - new PointOption().build(); + new PointOption<>().build(); fail("The exception throwing was expected"); } From ac1729f29837b17fe0370b459b08d3095eb4ccf8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 31 Oct 2021 19:17:42 +0100 Subject: [PATCH 028/501] refactor: Tune setting of default platform names (#1570) --- .../io/appium/java_client/AppiumDriver.java | 74 ++++++++++++++----- .../java_client/android/AndroidDriver.java | 62 ++++++++-------- .../io/appium/java_client/ios/IOSDriver.java | 57 +++++++------- .../io/appium/java_client/mac/Mac2Driver.java | 62 +++++++--------- .../java_client/windows/WindowsDriver.java | 45 ++++++----- 5 files changed, 163 insertions(+), 137 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 31f68b353..ba932c959 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -16,9 +16,11 @@ package io.appium.java_client; +import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; import static org.apache.commons.lang3.StringUtils.isBlank; +import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; import io.appium.java_client.remote.MobileCapabilityType; @@ -81,61 +83,93 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { this.remoteAddress = executor.getAddressOfRemoteServer(); } - public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities) { + public AppiumDriver(URL remoteAddress, Capabilities capabilities) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, remoteAddress), - desiredCapabilities); + capabilities); } public AppiumDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { + Capabilities capabilities) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, remoteAddress, - httpClientFactory), desiredCapabilities); + httpClientFactory), capabilities); } - public AppiumDriver(AppiumDriverLocalService service, Capabilities desiredCapabilities) { + public AppiumDriver(AppiumDriverLocalService service, Capabilities capabilities) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, service), - desiredCapabilities); + capabilities); } public AppiumDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { + Capabilities capabilities) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, service, httpClientFactory), - desiredCapabilities); + capabilities); } - public AppiumDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) { - this(builder.build(), desiredCapabilities); + public AppiumDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + this(builder.build(), capabilities); } public AppiumDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - this(builder.build(), httpClientFactory, desiredCapabilities); + Capabilities capabilities) { + this(builder.build(), httpClientFactory, capabilities); } - public AppiumDriver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { + public AppiumDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { this(AppiumDriverLocalService.buildDefaultService(), httpClientFactory, - desiredCapabilities); + capabilities); } - public AppiumDriver(Capabilities desiredCapabilities) { - this(AppiumDriverLocalService.buildDefaultService(), desiredCapabilities); + public AppiumDriver(Capabilities capabilities) { + this(AppiumDriverLocalService.buildDefaultService(), capabilities); } /** - * Changes platform name if it is not set and returns new capabilities. + * Changes platform name if it is not set and returns merged capabilities. * * @param originalCapabilities the given {@link Capabilities}. * @param defaultName a {@link MobileCapabilityType#PLATFORM_NAME} value which has * to be set up * @return {@link Capabilities} with changed mobile platform name value or the original capabilities */ - protected static Capabilities updateDefaultPlatformName(Capabilities originalCapabilities, - String defaultName) { - return originalCapabilities.getCapability(PLATFORM_NAME) == null + protected static Capabilities ensurePlatformName(Capabilities originalCapabilities, + String defaultName) { + String currentName = (String) originalCapabilities.getCapability(PLATFORM_NAME); + return isBlank(currentName) ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) : originalCapabilities; } + /** + * Changes platform and automation names if they are not set + * and returns merged capabilities. + * + * @param originalCapabilities the given {@link Capabilities}. + * @param defaultPlatformName a {@link MobileCapabilityType#PLATFORM_NAME} value which has + * to be set up + * @param defaultAutomationName The default automation name to set up for this class + * @return {@link Capabilities} with changed mobile platform name value or the original capabilities + */ + protected static Capabilities ensurePlatformAndAutomationNames( + Capabilities originalCapabilities, String defaultPlatformName, String defaultAutomationName) { + MutableCapabilities toMerge = new MutableCapabilities(); + String currentPlatformName = (String) originalCapabilities.getCapability(PLATFORM_NAME); + if (isBlank(currentPlatformName)) { + toMerge.setCapability(PLATFORM_NAME, defaultPlatformName); + } + String currentAutomationName = CapabilityHelpers.getCapability( + originalCapabilities, MobileCapabilityType.AUTOMATION_NAME, String.class); + if (isBlank(currentAutomationName)) { + toMerge.setCapability(originalCapabilities.getCapabilityNames() + .contains(MobileCapabilityType.AUTOMATION_NAME) + ? MobileCapabilityType.AUTOMATION_NAME + : APPIUM_PREFIX + MobileCapabilityType.AUTOMATION_NAME, + defaultAutomationName); + } + return toMerge.getCapabilityNames().isEmpty() + ? originalCapabilities + : originalCapabilities.merge(toMerge); + } + @Override public ExecuteMethod getExecuteMethod() { return executeMethod; 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 50280c161..5ad9001c4 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -38,7 +38,6 @@ import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; import io.appium.java_client.android.nativekey.PressesKey; import io.appium.java_client.battery.HasBattery; -import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.SupportsContextSwitching; import io.appium.java_client.remote.SupportsLocation; import io.appium.java_client.remote.SupportsRotation; @@ -47,6 +46,7 @@ import io.appium.java_client.service.local.AppiumServiceBuilder; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; @@ -87,8 +87,7 @@ public class AndroidDriver extends AppiumDriver implements ExecuteCDPCommand, CanReplaceElementValue, SupportsExtendedGeolocationCommands { - - private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; + private static final String ANDROID_PLATFORM = Platform.ANDROID.name(); private StringWebSocketClient logcatClient; @@ -101,17 +100,17 @@ public class AndroidDriver extends AppiumDriver implements * @param capabilities take a look at {@link Capabilities} */ public AndroidDriver(HttpCommandExecutor executor, Capabilities capabilities) { - super(executor, updateDefaultPlatformName(capabilities, ANDROID_PLATFORM)); + super(executor, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** * Creates a new instance based on Appium server URL and {@code capabilities}. * * @param remoteAddress is the address of remotely/locally started Appium server - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(URL remoteAddress, Capabilities desiredCapabilities) { - super(remoteAddress, updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** @@ -119,22 +118,21 @@ public AndroidDriver(URL remoteAddress, Capabilities desiredCapabilities) { * * @param remoteAddress is the address of remotely/locally started Appium server * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(remoteAddress, httpClientFactory, - updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver( + URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** * Creates a new instance based on Appium driver local service and {@code capabilities}. * * @param service take a look at {@link AppiumDriverLocalService} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(AppiumDriverLocalService service, Capabilities desiredCapabilities) { - super(service, updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** @@ -142,22 +140,21 @@ public AndroidDriver(AppiumDriverLocalService service, Capabilities desiredCapab * * @param service take a look at {@link AppiumDriverLocalService} * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(service, httpClientFactory, - updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver( + AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(service, httpClientFactory, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** * Creates a new instance based on Appium service builder and {@code capabilities}. * * @param builder take a look at {@link AppiumServiceBuilder} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) { - super(builder, updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** @@ -165,31 +162,30 @@ public AndroidDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilit * * @param builder take a look at {@link AppiumServiceBuilder} * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ public AndroidDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(builder, httpClientFactory, - updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + Capabilities capabilities) { + super(builder, httpClientFactory, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** * Creates a new instance based on HTTP client factory and {@code capabilities}. * * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { - super(httpClientFactory, updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** * Creates a new instance based on {@code capabilities}. * - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public AndroidDriver(Capabilities desiredCapabilities) { - super(updateDefaultPlatformName(desiredCapabilities, ANDROID_PLATFORM)); + public AndroidDriver(Capabilities capabilities) { + super(ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** 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 70fe3c46d..771474fb6 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -32,7 +32,6 @@ import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.battery.HasBattery; -import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.remote.SupportsContextSwitching; import io.appium.java_client.remote.SupportsLocation; import io.appium.java_client.remote.SupportsRotation; @@ -42,6 +41,7 @@ import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.Alert; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; @@ -77,8 +77,7 @@ public class IOSDriver extends AppiumDriver implements HasIOSClipboard, ListensToSyslogMessages, HasBattery { - - private static final String IOS_DEFAULT_PLATFORM = MobilePlatform.IOS; + private static final String PLATFORM_NAME = Platform.IOS.name(); private StringWebSocketClient syslogClient; @@ -91,17 +90,17 @@ public class IOSDriver extends AppiumDriver implements * @param capabilities take a look at {@link Capabilities} */ public IOSDriver(HttpCommandExecutor executor, Capabilities capabilities) { - super(executor, updateDefaultPlatformName(capabilities, IOS_DEFAULT_PLATFORM)); + super(executor, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** * Creates a new instance based on Appium server URL and {@code capabilities}. * * @param remoteAddress is the address of remotely/locally started Appium server - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public IOSDriver(URL remoteAddress, Capabilities desiredCapabilities) { - super(remoteAddress, updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + public IOSDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** @@ -109,22 +108,21 @@ public IOSDriver(URL remoteAddress, Capabilities desiredCapabilities) { * * @param remoteAddress is the address of remotely/locally started Appium server * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ public IOSDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(remoteAddress, httpClientFactory, - updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** * Creates a new instance based on Appium driver local service and {@code capabilities}. * * @param service take a look at {@link AppiumDriverLocalService} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public IOSDriver(AppiumDriverLocalService service, Capabilities desiredCapabilities) { - super(service, updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + public IOSDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** @@ -132,21 +130,21 @@ public IOSDriver(AppiumDriverLocalService service, Capabilities desiredCapabilit * * @param service take a look at {@link AppiumDriverLocalService} * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ public IOSDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(service, httpClientFactory, updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + Capabilities capabilities) { + super(service, httpClientFactory, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** * Creates a new instance based on Appium service builder and {@code capabilities}. * * @param builder take a look at {@link AppiumServiceBuilder} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public IOSDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) { - super(builder, updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + public IOSDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** @@ -154,31 +152,30 @@ public IOSDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) * * @param builder take a look at {@link AppiumServiceBuilder} * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ public IOSDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(builder, httpClientFactory, - updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + Capabilities capabilities) { + super(builder, httpClientFactory, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** * Creates a new instance based on HTTP client factory and {@code capabilities}. * * @param httpClientFactory take a look at {@link HttpClient.Factory} - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public IOSDriver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { - super(httpClientFactory, updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + public IOSDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensurePlatformName(capabilities, PLATFORM_NAME)); } /** * Creates a new instance based on {@code capabilities}. * - * @param desiredCapabilities take a look at {@link Capabilities} + * @param capabilities take a look at {@link Capabilities} */ - public IOSDriver(Capabilities desiredCapabilities) { - super(updateDefaultPlatformName(desiredCapabilities, IOS_DEFAULT_PLATFORM)); + public IOSDriver(Capabilities capabilities) { + super(ensurePlatformName(capabilities, PLATFORM_NAME)); } @Override public TargetLocator switchTo() { diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index 9ad2b368c..56a309a88 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -17,22 +17,17 @@ package io.appium.java_client.mac; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.ImmutableCapabilities; +import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; -import static io.appium.java_client.remote.MobilePlatform.MAC; -import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; - /** * Mac2Driver is an officially supported Appium driver * created to automate Mac OS apps. The driver uses W3C @@ -44,53 +39,50 @@ */ public class Mac2Driver extends AppiumDriver implements CanRecordScreen { + private static final String PLATFORM_NAME = Platform.MAC.name(); + private static final String AUTOMATION_NAME = AutomationName.MAC2; + public Mac2Driver(HttpCommandExecutor executor, Capabilities capabilities) { - super(executor, prepareCaps(capabilities)); + super(executor, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public Mac2Driver(URL remoteAddress, Capabilities desiredCapabilities) { - super(remoteAddress, prepareCaps(desiredCapabilities)); + public Mac2Driver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public Mac2Driver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { - super(remoteAddress, httpClientFactory, prepareCaps(desiredCapabilities)); + public Mac2Driver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public Mac2Driver(AppiumDriverLocalService service, Capabilities desiredCapabilities) { - super(service, prepareCaps(desiredCapabilities)); + public Mac2Driver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } public Mac2Driver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(service, httpClientFactory, prepareCaps(desiredCapabilities)); + Capabilities capabilities) { + super(service, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public Mac2Driver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) { - super(builder, prepareCaps(desiredCapabilities)); + public Mac2Driver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } public Mac2Driver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(builder, httpClientFactory, prepareCaps(desiredCapabilities)); - } - - public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { - super(httpClientFactory, prepareCaps(desiredCapabilities)); + Capabilities capabilities) { + super(builder, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public Mac2Driver(Capabilities desiredCapabilities) { - super(prepareCaps(desiredCapabilities)); + public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - private static Capabilities prepareCaps(Capabilities originalCaps) { - String automationName = CapabilityHelpers.getCapability(originalCaps, - MobileCapabilityType.AUTOMATION_NAME, String.class); - return (originalCaps.getCapability(PLATFORM_NAME) == null - || !AutomationName.MAC2.equalsIgnoreCase(automationName)) - ? originalCaps.merge(new ImmutableCapabilities( - PLATFORM_NAME, MAC, - MobileCapabilityType.AUTOMATION_NAME, AutomationName.MAC2 - )) - : originalCaps; + public Mac2Driver(Capabilities capabilities) { + super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } } diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 032ce91cd..5cb449d8b 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -16,14 +16,14 @@ package io.appium.java_client.windows; -import static io.appium.java_client.remote.MobilePlatform.WINDOWS; - import io.appium.java_client.AppiumDriver; import io.appium.java_client.HidesKeyboardWithKeyName; +import io.appium.java_client.remote.AutomationName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; @@ -33,42 +33,49 @@ public class WindowsDriver extends AppiumDriver implements PressesKeyCode, HidesKeyboardWithKeyName, CanRecordScreen { + private static final String PLATFORM_NAME = Platform.WINDOWS.name(); + private static final String AUTOMATION_NAME = AutomationName.WINDOWS; public WindowsDriver(HttpCommandExecutor executor, Capabilities capabilities) { - super(executor, updateDefaultPlatformName(capabilities, WINDOWS)); + super(executor, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(URL remoteAddress, Capabilities desiredCapabilities) { - super(remoteAddress, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + public WindowsDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { - super(remoteAddress, httpClientFactory, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + public WindowsDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(AppiumDriverLocalService service, Capabilities desiredCapabilities) { - super(service, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + public WindowsDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } public WindowsDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(service, httpClientFactory, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + Capabilities capabilities) { + super(service, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) { - super(builder, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + public WindowsDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } public WindowsDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, - Capabilities desiredCapabilities) { - super(builder, httpClientFactory, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + Capabilities capabilities) { + super(builder, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) { - super(httpClientFactory, updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(Capabilities desiredCapabilities) { - super(updateDefaultPlatformName(desiredCapabilities, WINDOWS)); + public WindowsDriver(Capabilities capabilities) { + super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } } From a1f802e553b916902c7fc1ddb6ba77063a54f78d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 31 Oct 2021 19:21:45 +0100 Subject: [PATCH 029/501] chore: Deprecate touch actions (#1569) --- .../java_client/PerformsTouchActions.java | 18 ++++++++++++++++-- .../io/appium/java_client/TouchAction.java | 10 ++++++++++ .../android/AndroidTouchAction.java | 11 +++++++++++ .../io/appium/java_client/ios/IOSDriver.java | 1 - .../appium/java_client/ios/IOSTouchAction.java | 11 +++++++++++ .../io/appium/java_client/mac/Mac2Driver.java | 2 ++ .../java_client/windows/WindowsDriver.java | 2 ++ 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/appium/java_client/PerformsTouchActions.java b/src/main/java/io/appium/java_client/PerformsTouchActions.java index fae9c2403..7058375f4 100644 --- a/src/main/java/io/appium/java_client/PerformsTouchActions.java +++ b/src/main/java/io/appium/java_client/PerformsTouchActions.java @@ -22,6 +22,18 @@ import java.util.List; import java.util.Map; +/** + * Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. + */ +@Deprecated +@SuppressWarnings({"unchecked", "rawtypes"}) public interface PerformsTouchActions extends ExecutesMethod { /** * Performs a chain of touch actions, which together can be considered an @@ -36,6 +48,7 @@ public interface PerformsTouchActions extends ExecutesMethod { * touch actions to perform * @return the same touch action object */ + @Deprecated default TouchAction performTouchAction(TouchAction touchAction) { Map> parameters = touchAction.getParameters(); execute(PERFORM_TOUCH_ACTION, parameters); @@ -53,9 +66,10 @@ default TouchAction performTouchAction(TouchAction touchAction) { * * @param multiAction the MultiTouchAction object to perform. */ - default void performMultiTouchAction(MultiTouchAction multiAction) { + @Deprecated + default MultiTouchAction performMultiTouchAction(MultiTouchAction multiAction) { Map> parameters = multiAction.getParameters(); execute(PERFORM_MULTI_TOUCH, parameters); - multiAction.clearActions(); + return multiAction.clearActions(); } } diff --git a/src/main/java/io/appium/java_client/TouchAction.java b/src/main/java/io/appium/java_client/TouchAction.java index 63b889b20..669a32e26 100644 --- a/src/main/java/io/appium/java_client/TouchAction.java +++ b/src/main/java/io/appium/java_client/TouchAction.java @@ -42,7 +42,17 @@ * action.press(element).waitAction(300).moveTo(element1).release().perform(); * Calling perform() sends the action command to the Mobile Driver. Otherwise, * more and more actions can be chained. + * + * Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. */ +@Deprecated public class TouchAction> implements PerformsActions { protected ImmutableList.Builder parameterBuilder; diff --git a/src/main/java/io/appium/java_client/android/AndroidTouchAction.java b/src/main/java/io/appium/java_client/android/AndroidTouchAction.java index e1af310df..20c02a6ca 100644 --- a/src/main/java/io/appium/java_client/android/AndroidTouchAction.java +++ b/src/main/java/io/appium/java_client/android/AndroidTouchAction.java @@ -20,6 +20,17 @@ import io.appium.java_client.TouchAction; +/** + * Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. + */ +@Deprecated public class AndroidTouchAction extends TouchAction { public AndroidTouchAction(PerformsTouchActions performsTouchActions) { 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 771474fb6..cd64de300 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -54,7 +54,6 @@ /** * iOS driver implementation. - * */ public class IOSDriver extends AppiumDriver implements SupportsContextSwitching, diff --git a/src/main/java/io/appium/java_client/ios/IOSTouchAction.java b/src/main/java/io/appium/java_client/ios/IOSTouchAction.java index 8a2c19199..ce6180752 100644 --- a/src/main/java/io/appium/java_client/ios/IOSTouchAction.java +++ b/src/main/java/io/appium/java_client/ios/IOSTouchAction.java @@ -22,6 +22,17 @@ import io.appium.java_client.touch.offset.ElementOption; import io.appium.java_client.touch.offset.PointOption; +/** + * Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. + */ +@Deprecated public class IOSTouchAction extends TouchAction { public IOSTouchAction(PerformsTouchActions performsTouchActions) { diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index 56a309a88..a65497eaa 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -17,6 +17,7 @@ package io.appium.java_client.mac; import io.appium.java_client.AppiumDriver; +import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -38,6 +39,7 @@ * @since Appium 1.20.0 */ public class Mac2Driver extends AppiumDriver implements + PerformsTouchActions, CanRecordScreen { private static final String PLATFORM_NAME = Platform.MAC.name(); private static final String AUTOMATION_NAME = AutomationName.MAC2; diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 5cb449d8b..316081da9 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -18,6 +18,7 @@ import io.appium.java_client.AppiumDriver; import io.appium.java_client.HidesKeyboardWithKeyName; +import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -30,6 +31,7 @@ import java.net.URL; public class WindowsDriver extends AppiumDriver implements + PerformsTouchActions, PressesKeyCode, HidesKeyboardWithKeyName, CanRecordScreen { From bd66144e8a15ec9bbe1af8a4c25087d527b79e90 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 31 Oct 2021 22:06:03 +0100 Subject: [PATCH 030/501] chore: Deprecate legacy app management helpers (#1571) --- .../appium/java_client/InteractsWithApps.java | 29 +------- .../io/appium/java_client/MobileCommand.java | 4 +- .../java_client/PerformsTouchActions.java | 1 + ...nteractsWithFiles.java => PullsFiles.java} | 26 ++----- .../java_client/{ios => }/PushesFiles.java | 23 ++---- .../SupportsLegacyAppManagement.java | 59 +++++++++++++++ .../io/appium/java_client/TouchAction.java | 16 ++-- .../java_client/android/AndroidDriver.java | 7 +- .../java_client/android/PushesFiles.java | 74 ------------------- .../io/appium/java_client/ios/IOSDriver.java | 7 +- .../java_client/windows/WindowsDriver.java | 22 +++++- 11 files changed, 111 insertions(+), 157 deletions(-) rename src/main/java/io/appium/java_client/{InteractsWithFiles.java => PullsFiles.java} (69%) rename src/main/java/io/appium/java_client/{ios => }/PushesFiles.java (72%) create mode 100644 src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java delete mode 100644 src/main/java/io/appium/java_client/android/PushesFiles.java diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index 202360e22..f1a15146e 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -17,13 +17,10 @@ package io.appium.java_client; import static io.appium.java_client.MobileCommand.ACTIVATE_APP; -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.QUERY_APP_STATE; import static io.appium.java_client.MobileCommand.REMOVE_APP; -import static io.appium.java_client.MobileCommand.RESET; import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; import static io.appium.java_client.MobileCommand.TERMINATE_APP; import static io.appium.java_client.MobileCommand.prepareArguments; @@ -40,16 +37,9 @@ import java.util.AbstractMap; import javax.annotation.Nullable; +@SuppressWarnings("rawtypes") public interface InteractsWithApps extends ExecutesMethod { - /** - * Launches the app, which was provided in the capabilities at session creation, - * and (re)starts the session. - */ - default void launchApp() { - execute(LAUNCH_APP); - } - /** * Install an app on the mobile device. * @@ -63,7 +53,7 @@ default void installApp(String appPath) { * Install an app on the mobile device. * * @param appPath path to app to install or a remote URL. - * @param options Set of the corresponding instllation options for + * @param options Set of the corresponding installation options for * the particular platform. */ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) { @@ -86,13 +76,6 @@ default boolean isAppInstalled(String bundleId) { new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, prepareArguments("bundleId", bundleId))); } - /** - * Resets the currently running app together with the session. - */ - default void resetApp() { - execute(RESET); - } - /** * Runs the current app as a background app for the time * requested. This is a synchronous method, it blocks while the @@ -132,14 +115,6 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption new AbstractMap.SimpleEntry<>(REMOVE_APP, prepareArguments(parameters, values))); } - /** - * Close the app which was provided in the capabilities at session creation - * and quits the session. - */ - default void closeApp() { - execute(CLOSE_APP); - } - /** * Activates the given app if it installed, but not running or if it is running in the * background. diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 75435081e..4d20164ad 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -47,8 +47,8 @@ public class MobileCommand { public static final String RUN_APP_IN_BACKGROUND; protected static final String PERFORM_TOUCH_ACTION; protected static final String PERFORM_MULTI_TOUCH; - protected static final String LAUNCH_APP; - protected static final String CLOSE_APP; + public static final String LAUNCH_APP; + public static final String CLOSE_APP; protected static final String GET_DEVICE_TIME; protected static final String GET_SESSION; protected static final String LOG_EVENT; diff --git a/src/main/java/io/appium/java_client/PerformsTouchActions.java b/src/main/java/io/appium/java_client/PerformsTouchActions.java index 7058375f4..0ac7776d6 100644 --- a/src/main/java/io/appium/java_client/PerformsTouchActions.java +++ b/src/main/java/io/appium/java_client/PerformsTouchActions.java @@ -65,6 +65,7 @@ default TouchAction performTouchAction(TouchAction touchAction) { * is called. * * @param multiAction the MultiTouchAction object to perform. + * @return MultiTouchAction instance for chaining. */ @Deprecated default MultiTouchAction performMultiTouchAction(MultiTouchAction multiAction) { diff --git a/src/main/java/io/appium/java_client/InteractsWithFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java similarity index 69% rename from src/main/java/io/appium/java_client/InteractsWithFiles.java rename to src/main/java/io/appium/java_client/PullsFiles.java index d8b6af05a..590e4aaa0 100644 --- a/src/main/java/io/appium/java_client/InteractsWithFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -26,57 +26,41 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; -public interface InteractsWithFiles extends ExecutesMethod { +public interface PullsFiles extends ExecutesMethod { /** - * Pull a file from the simulator/device. - * On iOS the server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. + * Pull a file from the remote system. * On Android the application under test should be * built with debuggable flag enabled in order to get access to its container * on the internal file system. * - * @see iFuse GitHub page6 - * @see osxFuse FAQ - * @see 'Debug Your App' developer article - * * @param remotePath If the path starts with @applicationId// prefix, then the file * will be pulled from the root of the corresponding application container. - * Otherwise the root folder is considered as / on Android and + * Otherwise, the root folder is considered as / on Android and * on iOS it is a media folder root (real devices only). * @return A byte array of Base64 encoded data. */ default byte[] pullFile(String remotePath) { Response response = execute(PULL_FILE, ImmutableMap.of("path", remotePath)); String base64String = response.getValue().toString(); - return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } /** - * Pull a folder content from the simulator/device. - * On iOS the server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. + * Pull a folder content from the remote system. * On Android the application under test should be * built with debuggable flag enabled in order to get access to its container * on the internal file system. * - * @see iFuse GitHub page6 - * @see osxFuse FAQ - * @see 'Debug Your App' developer article - * * @param remotePath If the path starts with @applicationId/ prefix, then the folder * will be pulled from the root of the corresponding application container. - * Otherwise the root folder is considered as / on Android and + * Otherwise, the root folder is considered as / on Android and * on iOS it is a media folder root (real devices only). * @return A byte array of Base64 encoded zip archive data. */ default byte[] pullFolder(String remotePath) { Response response = execute(PULL_FOLDER, ImmutableMap.of("path", remotePath)); String base64String = response.getValue().toString(); - return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } diff --git a/src/main/java/io/appium/java_client/ios/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java similarity index 72% rename from src/main/java/io/appium/java_client/ios/PushesFiles.java rename to src/main/java/io/appium/java_client/PushesFiles.java index 097deacf3..d6da2ca82 100644 --- a/src/main/java/io/appium/java_client/ios/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -14,13 +14,11 @@ * limitations under the License. */ -package io.appium.java_client.ios; +package io.appium.java_client; import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.pushFileCommand; -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; @@ -30,13 +28,7 @@ public interface PushesFiles extends ExecutesMethod { /** - * Saves base64 encoded data as a media file on the remote mobile device. - * The server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. - * - * @see iFuse GitHub page - * @see osxFuse FAQ + * Saves base64 encoded data as a media file on the remote system. * * @param remotePath Path to file to write data to on remote device * Only the filename part matters there on Simulator, so the remote end @@ -53,13 +45,7 @@ default void pushFile(String remotePath, byte[] base64Data) { } /** - * Saves base64 encoded data as a media file on the remote mobile device. - * The server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. - * - * @see iFuse GitHub page - * @see osxFuse FAQ + * Saves base64 encoded data as a media file on the remote system. * * @param remotePath See the documentation on {@link #pushFile(String, byte[])} * @param file Is an existing local file to be written to the remote device @@ -68,7 +54,8 @@ default void pushFile(String remotePath, byte[] base64Data) { 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(String.format("The given file %s doesn't exist", file.getAbsolutePath())); + throw new IOException(String.format("The given file %s doesn't exist", + file.getAbsolutePath())); } pushFile(remotePath, Base64.encodeBase64(FileUtils.readFileToByteArray(file))); } diff --git a/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java b/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java new file mode 100644 index 000000000..7be14ec6d --- /dev/null +++ b/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java @@ -0,0 +1,59 @@ +/* + * 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 static io.appium.java_client.MobileCommand.CLOSE_APP; +import static io.appium.java_client.MobileCommand.LAUNCH_APP; +import static io.appium.java_client.MobileCommand.RESET; + +@Deprecated +public interface SupportsLegacyAppManagement extends ExecutesMethod { + /** + * Launches the app, which was provided in the capabilities at session creation, + * and (re)starts the session. + * + * @deprecated This method is deprecated and will be removed. + * See https://github.com/appium/appium/issues/15807 + */ + @Deprecated + default void launchApp() { + execute(LAUNCH_APP); + } + + /** + * Resets the currently running app together with the session. + * + * @deprecated This method is deprecated and will be removed. + * See https://github.com/appium/appium/issues/15807 + */ + @Deprecated + default void resetApp() { + execute(RESET); + } + + /** + * Close the app which was provided in the capabilities at session creation + * and quits the session. + * + * @deprecated This method is deprecated and will be removed. + * See https://github.com/appium/appium/issues/15807 + */ + @Deprecated + default void closeApp() { + execute(CLOSE_APP); + } +} diff --git a/src/main/java/io/appium/java_client/TouchAction.java b/src/main/java/io/appium/java_client/TouchAction.java index 669a32e26..866e87140 100644 --- a/src/main/java/io/appium/java_client/TouchAction.java +++ b/src/main/java/io/appium/java_client/TouchAction.java @@ -43,14 +43,14 @@ * Calling perform() sends the action command to the Mobile Driver. Otherwise, * more and more actions can be chained. * - * Touch actions are deprecated. - * Please use W3C Actions instead or the corresponding - * extension methods for the driver (if available). - * Check - * - https://www.youtube.com/watch?v=oAJ7jwMNFVU - * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods - * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api - * for more details. + * @deprecated Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. */ @Deprecated public class TouchAction> implements PerformsActions { 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 5ad9001c4..741a4b9f9 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -31,9 +31,11 @@ import io.appium.java_client.HasOnScreenKeyboard; import io.appium.java_client.HidesKeyboard; import io.appium.java_client.InteractsWithApps; -import io.appium.java_client.InteractsWithFiles; +import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PushesFiles; +import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.android.connection.HasNetworkConnection; import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; import io.appium.java_client.android.nativekey.PressesKey; @@ -66,8 +68,9 @@ public class AndroidDriver extends AppiumDriver implements PerformsTouchActions, HidesKeyboard, HasDeviceTime, - InteractsWithFiles, + PullsFiles, InteractsWithApps, + SupportsLegacyAppManagement, HasAppStrings, HasNetworkConnection, PushesFiles, diff --git a/src/main/java/io/appium/java_client/android/PushesFiles.java b/src/main/java/io/appium/java_client/android/PushesFiles.java deleted file mode 100644 index 6fdd73136..000000000 --- a/src/main/java/io/appium/java_client/android/PushesFiles.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.pushFileCommand; - -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, ExecutesMethod { - - /** - * Saves base64 encoded data as a file on the remote mobile device. - * The application under test should be - * built with debuggable flag enabled in order to get access to its container - * on the internal file system. - * - * @see 'Debug Your App' developer article - * - * @param remotePath Path to file to write data to on remote device - * If the path starts with @applicationId/ prefix, then the file - * will be pushed to the root of the corresponding application container. - * @param base64Data Base64 encoded byte array of data to write to remote device - */ - default void pushFile(String remotePath, byte[] base64Data) { - CommandExecutionHelper.execute(this, pushFileCommand(remotePath, base64Data)); - } - - /** - * Saves the given file to the remote mobile device. - * The application under test should be - * built with debugMode flag enabled in order to get access to its container - * on the internal file system. - * - * @see 'Debug Your App' developer article - * - * @param remotePath Path to file to write data to on remote device. - * If the path starts with @applicationId/ prefix, then the file - * will be pushed to the root of the corresponding application container. - * @param file is a file to write to remote device - * @throws IOException when there are problems with a file or current file system - */ - 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/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index cd64de300..01a848b87 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -28,9 +28,11 @@ import io.appium.java_client.HidesKeyboard; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.InteractsWithApps; -import io.appium.java_client.InteractsWithFiles; +import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PushesFiles; +import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.SupportsContextSwitching; import io.appium.java_client.remote.SupportsLocation; @@ -61,8 +63,9 @@ public class IOSDriver extends AppiumDriver implements SupportsLocation, HidesKeyboard, HasDeviceTime, - InteractsWithFiles, + PullsFiles, InteractsWithApps, + SupportsLegacyAppManagement, HasAppStrings, PerformsTouchActions, HidesKeyboardWithKeyName, diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 316081da9..00b21a1ed 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -17,8 +17,10 @@ package io.appium.java_client.windows; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.HidesKeyboardWithKeyName; +import io.appium.java_client.MobileCommand; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PullsFiles; +import io.appium.java_client.PushesFiles; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -32,8 +34,8 @@ public class WindowsDriver extends AppiumDriver implements PerformsTouchActions, - PressesKeyCode, - HidesKeyboardWithKeyName, + PullsFiles, + PushesFiles, CanRecordScreen { private static final String PLATFORM_NAME = Platform.WINDOWS.name(); private static final String AUTOMATION_NAME = AutomationName.WINDOWS; @@ -80,4 +82,18 @@ public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities capabili public WindowsDriver(Capabilities capabilities) { super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + + /** + * Launch the application app under test after it was closed. + */ + public void launchApp() { + execute(MobileCommand.LAUNCH_APP); + } + + /** + * Close the app under test. + */ + public void closeApp() { + execute(MobileCommand.CLOSE_APP); + } } From c8d451e14db89f2fa19c5cfa6a38420d5fde71d1 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 Nov 2021 04:36:37 +0100 Subject: [PATCH 031/501] chore: Remove unused entities (#1572) * chore: Remove unused entities * Tune deprecation notices * Add summary --- .../appium/java_client/MultiTouchAction.java | 10 +++ .../android/AndroidTouchAction.java | 18 ++--- .../java_client/ios/IOSTouchAction.java | 18 ++--- .../java_client/windows/PressesKeyCode.java | 66 ------------------- .../java_client/windows/WindowsKeyCode.java | 41 ------------ 5 files changed, 30 insertions(+), 123 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/windows/PressesKeyCode.java delete mode 100644 src/main/java/io/appium/java_client/windows/WindowsKeyCode.java diff --git a/src/main/java/io/appium/java_client/MultiTouchAction.java b/src/main/java/io/appium/java_client/MultiTouchAction.java index c7bdd6525..ac66594dc 100644 --- a/src/main/java/io/appium/java_client/MultiTouchAction.java +++ b/src/main/java/io/appium/java_client/MultiTouchAction.java @@ -41,7 +41,17 @@ * "execution group", so these can be used to sync up complex actions. * Calling perform() sends the action command to the Mobile Driver. Otherwise, more and * more actions can be chained. + * + * @deprecated Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. */ +@Deprecated public class MultiTouchAction implements PerformsActions { private ImmutableList.Builder actions; diff --git a/src/main/java/io/appium/java_client/android/AndroidTouchAction.java b/src/main/java/io/appium/java_client/android/AndroidTouchAction.java index 20c02a6ca..0fa31cffa 100644 --- a/src/main/java/io/appium/java_client/android/AndroidTouchAction.java +++ b/src/main/java/io/appium/java_client/android/AndroidTouchAction.java @@ -21,14 +21,16 @@ /** - * Touch actions are deprecated. - * Please use W3C Actions instead or the corresponding - * extension methods for the driver (if available). - * Check - * - https://www.youtube.com/watch?v=oAJ7jwMNFVU - * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods - * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api - * for more details. + * Android-specific touch action. + * + * @deprecated Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. */ @Deprecated public class AndroidTouchAction extends TouchAction { diff --git a/src/main/java/io/appium/java_client/ios/IOSTouchAction.java b/src/main/java/io/appium/java_client/ios/IOSTouchAction.java index ce6180752..01a98f9e5 100644 --- a/src/main/java/io/appium/java_client/ios/IOSTouchAction.java +++ b/src/main/java/io/appium/java_client/ios/IOSTouchAction.java @@ -23,14 +23,16 @@ import io.appium.java_client.touch.offset.PointOption; /** - * Touch actions are deprecated. - * Please use W3C Actions instead or the corresponding - * extension methods for the driver (if available). - * Check - * - https://www.youtube.com/watch?v=oAJ7jwMNFVU - * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods - * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api - * for more details. + * iOS-specific touch action. + * + * @deprecated Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. */ @Deprecated public class IOSTouchAction extends TouchAction { diff --git a/src/main/java/io/appium/java_client/windows/PressesKeyCode.java b/src/main/java/io/appium/java_client/windows/PressesKeyCode.java deleted file mode 100644 index e6286d894..000000000 --- a/src/main/java/io/appium/java_client/windows/PressesKeyCode.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.windows; - -import static io.appium.java_client.MobileCommand.longPressKeyCodeCommand; -import static io.appium.java_client.MobileCommand.pressKeyCodeCommand; - -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; - -public interface PressesKeyCode extends ExecutesMethod { - - /** - * Send a key event to the device. - * - * @param key code for the key pressed on the device. - */ - default void pressKeyCode(int key) { - CommandExecutionHelper.execute(this, pressKeyCodeCommand(key)); - } - - /** - * Send a key event along with an Android metastate to an Android device. - * Metastates are things like *shift* to get uppercase characters. - * - * @param key code for the key pressed on the Android device. - * @param metastate metastate for the keypress. - */ - 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. - */ - default void longPressKeyCode(int key) { - CommandExecutionHelper.execute(this, longPressKeyCodeCommand(key)); - } - - /** - * Send a long key event along with an Android metastate to an Android device. - * Metastates are things like *shift* to get uppercase characters. - * - * @param key code for the key pressed on the Android device. - * @param metastate metastate for the keypress. - */ - default void longPressKeyCode(int key, Integer metastate) { - CommandExecutionHelper.execute(this, longPressKeyCodeCommand(key, metastate)); - } -} diff --git a/src/main/java/io/appium/java_client/windows/WindowsKeyCode.java b/src/main/java/io/appium/java_client/windows/WindowsKeyCode.java deleted file mode 100644 index c2968291f..000000000 --- a/src/main/java/io/appium/java_client/windows/WindowsKeyCode.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.windows; - -/** - * Created by STikhomirov on 15.12.2016. - */ -public interface WindowsKeyCode { - int POWER = 0; - int WINDOWS = 1; - int VOLUME_UP = 2; - int VOLUME_DOWN = 3; - int ROTATION_LOCK = 4; - int COUNT_MIN = 5; - int BACK = 5; - int SEARCH = 6; - int CAMERA_FOCUS = 7; - int CAMERA_SHUTTER = 8; - int RINGER_TOGGLE = 9; - int HEAD_SET = 10; - int HWKB_DPLOY = 11; - int CAMERA_LENS = 12; - int OEM_CUSTOM = 13; - int OEM_CUSTOM2 = 14; - int OEM_CUSTOM3 = 15; - int COUNT = 16; -} From b6b60e49192c944871d3e657f63e1af9df7eecfb Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 Nov 2021 10:47:31 +0100 Subject: [PATCH 032/501] feat: Add Gecko driver options (#1573) --- .../io/appium/java_client/AppiumDriver.java | 48 ++++++----- .../appium/java_client/gecko/GeckoDriver.java | 79 +++++++++++++++++++ .../gecko/options/GeckoOptions.java | 66 ++++++++++++++++ .../options/SupportsAndroidStorageOption.java | 49 ++++++++++++ .../options/SupportsMarionettePortOption.java | 54 +++++++++++++ .../SupportsMozFirefoxOptionsOption.java | 49 ++++++++++++ .../options/SupportsSystemPortOption.java | 51 ++++++++++++ .../options/SupportsVerbosityOption.java | 51 ++++++++++++ .../java_client/gecko/options/Verbosity.java | 21 +++++ .../remote/options/BaseOptions.java | 2 +- .../SupportsAcceptInsecureCertsOption.java | 59 ++++++++++++++ .../options/SupportsBrowserVersionOption.java | 37 +++++++++ .../SupportsClearSystemFilesOption.java | 4 +- .../options/SupportsDeviceNameOption.java | 2 +- .../options/SupportsLanguageOption.java | 2 +- .../SupportsPageLoadStrategyOption.java | 49 ++++++++++++ .../remote/options/SupportsProxyOption.java | 51 ++++++++++++ .../options/SupportsSetWindowRectOption.java | 49 ++++++++++++ ...SupportsUnhandledPromptBehaviorOption.java | 47 +++++++++++ .../options/UnhandledPromptBehavior.java | 50 ++++++++++++ 20 files changed, 794 insertions(+), 26 deletions(-) create mode 100644 src/main/java/io/appium/java_client/gecko/GeckoDriver.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/SupportsAndroidStorageOption.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/SupportsMarionettePortOption.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/SupportsMozFirefoxOptionsOption.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/SupportsSystemPortOption.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java create mode 100644 src/main/java/io/appium/java_client/gecko/options/Verbosity.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsAcceptInsecureCertsOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsSetWindowRectOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsUnhandledPromptBehaviorOption.java create mode 100644 src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index ba932c959..abfdf126f 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -17,6 +17,7 @@ package io.appium.java_client; import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; +import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME; import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -129,16 +130,36 @@ public AppiumDriver(Capabilities capabilities) { * @param originalCapabilities the given {@link Capabilities}. * @param defaultName a {@link MobileCapabilityType#PLATFORM_NAME} value which has * to be set up - * @return {@link Capabilities} with changed mobile platform name value or the original capabilities + * @return {@link Capabilities} with changed platform name value or the original capabilities */ - protected static Capabilities ensurePlatformName(Capabilities originalCapabilities, - String defaultName) { + protected static Capabilities ensurePlatformName( + Capabilities originalCapabilities, String defaultName) { String currentName = (String) originalCapabilities.getCapability(PLATFORM_NAME); return isBlank(currentName) ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) : originalCapabilities; } + /** + * Changes automation name if it is not set and returns merged capabilities. + * + * @param originalCapabilities the given {@link Capabilities}. + * @param defaultName a {@link MobileCapabilityType#AUTOMATION_NAME} value which has + * to be set up + * @return {@link Capabilities} with changed mobile automation name value or the original capabilities + */ + protected static Capabilities ensureAutomationName( + Capabilities originalCapabilities, String defaultName) { + String currentAutomationName = CapabilityHelpers.getCapability( + originalCapabilities, AUTOMATION_NAME, String.class); + if (isBlank(currentAutomationName)) { + String capabilityName = originalCapabilities.getCapabilityNames() + .contains(AUTOMATION_NAME) ? AUTOMATION_NAME : APPIUM_PREFIX + AUTOMATION_NAME; + return originalCapabilities.merge(new ImmutableCapabilities(capabilityName, defaultName)); + } + return originalCapabilities; + } + /** * Changes platform and automation names if they are not set * and returns merged capabilities. @@ -147,27 +168,12 @@ protected static Capabilities ensurePlatformName(Capabilities originalCapabiliti * @param defaultPlatformName a {@link MobileCapabilityType#PLATFORM_NAME} value which has * to be set up * @param defaultAutomationName The default automation name to set up for this class - * @return {@link Capabilities} with changed mobile platform name value or the original capabilities + * @return {@link Capabilities} with changed platform/automation name value or the original capabilities */ protected static Capabilities ensurePlatformAndAutomationNames( Capabilities originalCapabilities, String defaultPlatformName, String defaultAutomationName) { - MutableCapabilities toMerge = new MutableCapabilities(); - String currentPlatformName = (String) originalCapabilities.getCapability(PLATFORM_NAME); - if (isBlank(currentPlatformName)) { - toMerge.setCapability(PLATFORM_NAME, defaultPlatformName); - } - String currentAutomationName = CapabilityHelpers.getCapability( - originalCapabilities, MobileCapabilityType.AUTOMATION_NAME, String.class); - if (isBlank(currentAutomationName)) { - toMerge.setCapability(originalCapabilities.getCapabilityNames() - .contains(MobileCapabilityType.AUTOMATION_NAME) - ? MobileCapabilityType.AUTOMATION_NAME - : APPIUM_PREFIX + MobileCapabilityType.AUTOMATION_NAME, - defaultAutomationName); - } - return toMerge.getCapabilityNames().isEmpty() - ? originalCapabilities - : originalCapabilities.merge(toMerge); + Capabilities capsWithPlatformFixed = ensurePlatformName(originalCapabilities, defaultPlatformName); + return ensureAutomationName(capsWithPlatformFixed, defaultAutomationName); } @Override diff --git a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java new file mode 100644 index 000000000..bd85fcfc9 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java @@ -0,0 +1,79 @@ +/* + * 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.gecko; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.HttpClient; + +import java.net.URL; + +/** + * GeckoDriver is an officially supported Appium driver + * created to automate Mobile browsers and web views based on + * the Gecko engine. The driver uses W3C + * WebDriver protocol and is built on top of Mozilla's geckodriver + * server. Read https://github.com/appium/appium-geckodriver + * for more details on how to configure and use it. + * + * @since Appium 1.20.0 + */ +public class GeckoDriver extends AppiumDriver { + private static final String AUTOMATION_NAME = AutomationName.GECKO; + + public GeckoDriver(HttpCommandExecutor executor, Capabilities capabilities) { + super(executor, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, + Capabilities capabilities) { + super(service, httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, + Capabilities capabilities) { + super(builder, httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public GeckoDriver(Capabilities capabilities) { + super(ensureAutomationName(capabilities, AUTOMATION_NAME)); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java b/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java new file mode 100644 index 000000000..084400142 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java @@ -0,0 +1,66 @@ +/* + * 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.gecko.options; + +import io.appium.java_client.mac.options.SupportsSystemPortOption; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAcceptInsecureCertsOption; +import io.appium.java_client.remote.options.SupportsBrowserNameOption; +import io.appium.java_client.remote.options.SupportsBrowserVersionOption; +import io.appium.java_client.remote.options.SupportsPageLoadStrategyOption; +import io.appium.java_client.remote.options.SupportsProxyOption; +import io.appium.java_client.remote.options.SupportsSetWindowRectOption; +import io.appium.java_client.remote.options.SupportsUnhandledPromptBehaviorOption; +import org.openqa.selenium.Capabilities; + +import java.util.Map; + +/** + * https://github.com/appium/appium-geckodriver#usage + */ +public class GeckoOptions extends BaseOptions implements + SupportsBrowserNameOption, + SupportsBrowserVersionOption, + SupportsMarionettePortOption, + SupportsSystemPortOption, + SupportsVerbosityOption, + SupportsAndroidStorageOption, + SupportsMozFirefoxOptionsOption, + SupportsAcceptInsecureCertsOption, + SupportsPageLoadStrategyOption, + SupportsSetWindowRectOption, + SupportsProxyOption, + SupportsUnhandledPromptBehaviorOption { + public GeckoOptions() { + setCommonOptions(); + } + + public GeckoOptions(Capabilities source) { + super(source); + setCommonOptions(); + } + + public GeckoOptions(Map source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setAutomationName(AutomationName.GECKO); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/SupportsAndroidStorageOption.java b/src/main/java/io/appium/java_client/gecko/options/SupportsAndroidStorageOption.java new file mode 100644 index 000000000..b85438271 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/SupportsAndroidStorageOption.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.gecko.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsAndroidStorageOption> extends + Capabilities, CanSetCapability { + String ANDROID_STORAGE_OPTION = "androidStorage"; + + /** + * See + * https://firefox-source-docs.mozilla.org/testing/geckodriver + * /Flags.html#code-android-storage-var-android-storage-var-code + * + * @param storage One of supported Android storage types. + * @return self instance for chaining. + */ + default T setAndroidStorage(String storage) { + return amend(ANDROID_STORAGE_OPTION, storage); + } + + /** + * Get the currently set storage type. + * + * @return String representing the name of the device. + */ + default Optional getAndroidStorage() { + return Optional.ofNullable((String) getCapability(ANDROID_STORAGE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/SupportsMarionettePortOption.java b/src/main/java/io/appium/java_client/gecko/options/SupportsMarionettePortOption.java new file mode 100644 index 000000000..75bbcbf60 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/SupportsMarionettePortOption.java @@ -0,0 +1,54 @@ +/* + * 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.gecko.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsMarionettePortOption> extends + Capabilities, CanSetCapability { + String MARIONETTE_PORT_OPTION = "marionettePort"; + + /** + * Selects the port for Geckodriver’s connection to the Marionette + * remote protocol. The existing Firefox instance must have Marionette + * enabled. To enable the remote protocol in Firefox, you can pass the + * -marionette flag. Unless the marionette.port preference has been + * user-set, Marionette will listen on port 2828, which is the default + * value for this capability. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setMarionettePort(int port) { + return amend(MARIONETTE_PORT_OPTION, port); + } + + /** + * Get the number of the port for the Marionette server to listen on. + * + * @return Marionette port value. + */ + default Optional getMarionettePort() { + return Optional.ofNullable(toInteger(getCapability(MARIONETTE_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/SupportsMozFirefoxOptionsOption.java b/src/main/java/io/appium/java_client/gecko/options/SupportsMozFirefoxOptionsOption.java new file mode 100644 index 000000000..16b2d9579 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/SupportsMozFirefoxOptionsOption.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.gecko.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsMozFirefoxOptionsOption> extends + Capabilities, CanSetCapability { + String MOZ_FIREFOX_OPTIONS_OPTION = "moz:firefoxOptions"; + + /** + * See https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions. + * + * @param options Firefox options mapping. + * @return self instance for chaining. + */ + default T setMozFirefoxOptions(Map options) { + return amend(MOZ_FIREFOX_OPTIONS_OPTION, options); + } + + /** + * Get Firefox options mapping. + * + * @return Firefox options mapping. + */ + default Optional> getMozFirefoxOptions() { + //noinspection unchecked + return Optional.ofNullable((Map) getCapability(MOZ_FIREFOX_OPTIONS_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/SupportsSystemPortOption.java b/src/main/java/io/appium/java_client/gecko/options/SupportsSystemPortOption.java new file mode 100644 index 000000000..db89a31f4 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/SupportsSystemPortOption.java @@ -0,0 +1,51 @@ +/* + * 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.gecko.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsSystemPortOption> extends + Capabilities, CanSetCapability { + String SYSTEM_PORT_OPTION = "systemPort"; + + /** + * The number of the port for the driver to listen on. Must be unique + * for each session. If not provided then Appium will try to detect + * it automatically. + * + * @param port port number in range 0..65535 + * @return self instance for chaining. + */ + default T setSystemPort(int port) { + return amend(SYSTEM_PORT_OPTION, port); + } + + /** + * Get the number of the port for the internal server to listen on. + * + * @return System port value. + */ + default Optional getSystemPort() { + return Optional.ofNullable(toInteger(getCapability(SYSTEM_PORT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java b/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java new file mode 100644 index 000000000..60e479079 --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java @@ -0,0 +1,51 @@ +/* + * 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.gecko.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsVerbosityOption> extends + Capabilities, CanSetCapability { + String VERBOSITY_OPTION = "verbosity"; + + /** + * The verbosity level of driver logging. + * By default, minimum verbosity is applied. + * + * @param verbosity Verbosity value. + * @return self instance for chaining. + */ + default T setVerbosity(Verbosity verbosity) { + return amend(VERBOSITY_OPTION, verbosity.name().toLowerCase()); + } + + /** + * Get the verbosity level of driver logging. + * + * @return Verbosity value. + */ + default Optional getVerbosity() { + return Optional.ofNullable(getCapability(VERBOSITY_OPTION)) + .map(String::valueOf) + .map(String::toUpperCase) + .map(Verbosity::valueOf); + } +} diff --git a/src/main/java/io/appium/java_client/gecko/options/Verbosity.java b/src/main/java/io/appium/java_client/gecko/options/Verbosity.java new file mode 100644 index 000000000..f9a5c599e --- /dev/null +++ b/src/main/java/io/appium/java_client/gecko/options/Verbosity.java @@ -0,0 +1,21 @@ +/* + * 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.gecko.options; + +public enum Verbosity { + DEBUG, TRACE +} diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index bfa8c3cc4..b54057314 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -81,7 +81,7 @@ public BaseOptions(Capabilities source) { * Set the kind of mobile device or emulator to use. * * @param platform the kind of mobile device or emulator to use. - * @return this MobileOptions, for chaining. + * @return self instance for chaining. * @see CapabilityType#PLATFORM_NAME */ public T setPlatformName(String platform) { diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAcceptInsecureCertsOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAcceptInsecureCertsOption.java new file mode 100644 index 000000000..5146d7991 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAcceptInsecureCertsOption.java @@ -0,0 +1,59 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAcceptInsecureCertsOption> extends + Capabilities, CanSetCapability { + String ACCEPT_INSECURE_CERTS_OPTION = "acceptInsecureCerts"; + + /** + * Enforces untrusted and self-signed TLS certificates are + * implicitly trusted on navigation for the duration of the session. + * + * @return self instance for chaining. + */ + default T acceptInsecureCerts() { + return setAcceptInsecureCerts(true); + } + + /** + * Set whether untrusted and self-signed TLS certificates are + * implicitly trusted on navigation for the duration of the session. + * + * @param bool True or false. + * @return self instance for chaining. + */ + default T setAcceptInsecureCerts(boolean bool) { + return amend(ACCEPT_INSECURE_CERTS_OPTION, bool); + } + + /** + * Get whether untrusted and self-signed TLS certificates are + * implicitly trusted on navigation for the duration of the session. + * + * @return true or false. + */ + default Optional doesAcceptInsecureCerts() { + return Optional.ofNullable(toSafeBoolean(getCapability(ACCEPT_INSECURE_CERTS_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java new file mode 100644 index 000000000..4eece6cdb --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java @@ -0,0 +1,37 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsBrowserVersionOption> extends + Capabilities, CanSetCapability { + String BROWSER_VERSION_OPTION = "browserVersion"; + + /** + * Provide the version number of the browser to automate if there are multiple + * versions installed on the same machine where the driver is running. + * + * @param version Browser version to use. + * @return self instance for chaining. + */ + default T setBrowserVersion(String version) { + return amend(BROWSER_VERSION_OPTION, version); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java index 0d652a1da..d30001f3e 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsClearSystemFilesOption.java @@ -29,7 +29,7 @@ public interface SupportsClearSystemFilesOption> extend /** * Set the app to delete any generated files at the end of a session. * - * @return this MobileOptions, for chaining. + * @return self instance for chaining. */ default T clearSystemFiles() { return setClearSystemFiles(true); @@ -39,7 +39,7 @@ default T clearSystemFiles() { * Set whether the app deletes generated files at the end of a session. * * @param bool is whether the app deletes generated files at the end of a session. - * @return this MobileOptions, for chaining. + * @return self instance for chaining. */ default T setClearSystemFiles(boolean bool) { return amend(CLEAR_SYSTEM_FILES_OPTION, bool); diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java index 729741bbc..f1d268d1a 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsDeviceNameOption.java @@ -28,7 +28,7 @@ public interface SupportsDeviceNameOption> extends * Set the name of the device. * * @param deviceName is the name of the device. - * @return this MobileOptions, for chaining. + * @return self instance for chaining. */ default T setDeviceName(String deviceName) { return amend(DEVICE_NAME_OPTION, deviceName); diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java index 8428d6f45..92b41e9f6 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsLanguageOption.java @@ -28,7 +28,7 @@ public interface SupportsLanguageOption> extends * Set language abbreviation for use in session. * * @param language is the language abbreviation. - * @return this MobileOptions, for chaining. + * @return self instance for chaining. */ default T setLanguage(String language) { return amend(LANGUAGE_OPTION, language); diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java new file mode 100644 index 000000000..752966ef6 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.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.remote.options; + +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.PageLoadStrategy; + +import java.util.Optional; + +public interface SupportsPageLoadStrategyOption> extends + Capabilities, CanSetCapability { + String PAGE_LOAD_STRATEGY_OPTION = "pageLoadStrategy"; + + /** + * Defines the current session’s page load strategy. + * + * @param strategy Page load strategy. + * @return self instance for chaining. + */ + default T setPageLoadStrategy(PageLoadStrategy strategy) { + return amend(PAGE_LOAD_STRATEGY_OPTION, strategy.toString()); + } + + /** + * Get the current session’s page load strategy. + * + * @return Page load strategy. + */ + default Optional getPageLoadStrategy() { + return Optional.ofNullable(getCapability(PAGE_LOAD_STRATEGY_OPTION)) + .map(String::valueOf) + .map(String::toUpperCase) + .map(PageLoadStrategy::valueOf); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java new file mode 100644 index 000000000..cb3de55e7 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java @@ -0,0 +1,51 @@ +/* + * 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.remote.options; + +import com.google.gson.Gson; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Proxy; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsProxyOption> extends + Capabilities, CanSetCapability { + String PROXY_OPTION = "proxy"; + + /** + * Defines the current session’s proxy configuration. + * + * @param proxy Session proxy config. + * @return self instance for chaining. + */ + default T setProxy(Proxy proxy) { + return amend(PROXY_OPTION, proxy.toJson()); + } + + /** + * Get the current session’s proxy configuration. + * + * @return Proxy config. + */ + default Optional getProxy() { + return Optional.ofNullable(getCapability(PROXY_OPTION)) + .map(String::valueOf) + .map((v) -> new Gson().fromJson(v, Map.class)) + .map(Proxy::new); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsSetWindowRectOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsSetWindowRectOption.java new file mode 100644 index 000000000..046fb6cfa --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsSetWindowRectOption.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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSetWindowRectOption> extends + Capabilities, CanSetCapability { + String SET_WINDOW_RECT_OPTION = "setWindowRect"; + + /** + * Indicates whether the remote end supports all + * of the resizing and repositioning commands. + * + * @param bool True or false. + * @return self instance for chaining. + */ + default T setWindowRect(boolean bool) { + return amend(SET_WINDOW_RECT_OPTION, bool); + } + + /** + * Get whether the remote end supports all + * of the resizing and repositioning commands. + * + * @return true or false. + */ + default Optional doesSetWindowRect() { + return Optional.ofNullable(toSafeBoolean(getCapability(SET_WINDOW_RECT_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsUnhandledPromptBehaviorOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsUnhandledPromptBehaviorOption.java new file mode 100644 index 000000000..a6fded38a --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsUnhandledPromptBehaviorOption.java @@ -0,0 +1,47 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsUnhandledPromptBehaviorOption> extends + Capabilities, CanSetCapability { + String UNHANDLED_PROMPT_BEHAVIOR_OPTION = "unhandledPromptBehavior"; + + /** + * Defines the current session’s page load strategy. + * + * @param strategy Page load strategy. + * @return self instance for chaining. + */ + default T setUnhandledPromptBehavior(UnhandledPromptBehavior strategy) { + return amend(UNHANDLED_PROMPT_BEHAVIOR_OPTION, strategy.toString()); + } + + /** + * Get the current session’s page load strategy. + * + * @return Page load strategy. + */ + default Optional getUnhandledPromptBehavior() { + return Optional.ofNullable(getCapability(UNHANDLED_PROMPT_BEHAVIOR_OPTION)) + .map(String::valueOf) + .map(UnhandledPromptBehavior::fromString); + } +} diff --git a/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java b/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java new file mode 100644 index 000000000..0068dfe42 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java @@ -0,0 +1,50 @@ +/* + * 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.remote.options; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public enum UnhandledPromptBehavior { + DISMISS, ACCEPT, + DISMISS_AND_NOTIFY, ACCEPT_AND_NOTIFY, + IGNORE; + + @Override + public String toString() { + return name().toLowerCase().replace("_", " "); + } + + /** + * Converts the given value to an enum member. + * + * @param value The value to convert. + * @return Enum member. + * @throws IllegalArgumentException If the provided value cannot be matched. + */ + public static UnhandledPromptBehavior fromString(String value) { + return Arrays.stream(values()) + .filter((v) -> v.toString().equals(value)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException( + String.format("Unhandled prompt behavior '%s' is not supported. " + + "The only supported values are: %s", value, + Arrays.stream(values()).map(UnhandledPromptBehavior::toString) + .collect(Collectors.joining(","))) + )); + } +} From c2981de264d1693f13a3f6031acb79d275a2eccb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Nov 2021 13:04:26 +0100 Subject: [PATCH 033/501] build(deps): bump gson from 2.8.8 to 2.8.9 (#1574) Bumps [gson](https://github.com/google/gson) from 2.8.8 to 2.8.9. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.8...gson-parent-2.8.9) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4cd6ab8de..b7e92bea8 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ dependencies { strictly "${seleniumVersion}" } } - implementation 'com.google.code.gson:gson:2.8.8' + implementation 'com.google.code.gson:gson:2.8.9' implementation 'commons-codec:commons-codec:1.15' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' From 5bc12273b14154fa2d4010b48cf45fb794b7d788 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 Nov 2021 14:14:32 +0100 Subject: [PATCH 034/501] feat: Add Safari driver options (#1576) --- .../java_client/safari/SafariDriver.java | 87 +++++++++++++++++++ .../safari/options/SafariOptions.java | 71 +++++++++++++++ ...pportsSafariAutomaticInspectionOption.java | 61 +++++++++++++ ...upportsSafariAutomaticProfilingOption.java | 61 +++++++++++++ .../SupportsSafariDeviceNameOption.java | 52 +++++++++++ .../SupportsSafariDeviceTypeOption.java | 50 +++++++++++ .../SupportsSafariDeviceUdidOption.java | 52 +++++++++++ ...portsSafariPlatformBuildVersionOption.java | 50 +++++++++++ .../SupportsSafariPlatformVersionOption.java | 50 +++++++++++ .../SupportsSafariUseSimulatorOption.java | 61 +++++++++++++ .../options/SupportsWebkitWebrtcOption.java | 51 +++++++++++ .../safari/options/WebrtcData.java | 77 ++++++++++++++++ .../drivers/options/OptionsBuildingTest.java | 40 +++++++++ 13 files changed, 763 insertions(+) create mode 100644 src/main/java/io/appium/java_client/safari/SafariDriver.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SafariOptions.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticInspectionOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticProfilingOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceNameOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceTypeOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceUdidOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformBuildVersionOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformVersionOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsSafariUseSimulatorOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/SupportsWebkitWebrtcOption.java create mode 100644 src/main/java/io/appium/java_client/safari/options/WebrtcData.java diff --git a/src/main/java/io/appium/java_client/safari/SafariDriver.java b/src/main/java/io/appium/java_client/safari/SafariDriver.java new file mode 100644 index 000000000..c32d36b05 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/SafariDriver.java @@ -0,0 +1,87 @@ +/* + * 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.safari; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; +import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.HttpClient; + +import java.net.URL; + +/** + * GeckoDriver is an officially supported Appium driver + * created to automate mobile Safari browser. The driver uses W3C + * WebDriver protocol and is built on top of Apple's safaridriver + * server. Read https://github.com/appium/appium-safari-driver + * for more details on how to configure and use it. + * + * @since Appium 1.20.0 + */ +public class SafariDriver extends AppiumDriver { + private static final String PLATFORM_NAME = Platform.IOS.toString(); + private static final String AUTOMATION_NAME = AutomationName.SAFARI; + + public SafariDriver(HttpCommandExecutor executor, Capabilities capabilities) { + super(executor, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, + Capabilities capabilities) { + super(service, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, + Capabilities capabilities) { + super(builder, httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + public SafariDriver(Capabilities capabilities) { + super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SafariOptions.java b/src/main/java/io/appium/java_client/safari/options/SafariOptions.java new file mode 100644 index 000000000..fa170587b --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SafariOptions.java @@ -0,0 +1,71 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsAcceptInsecureCertsOption; +import io.appium.java_client.remote.options.SupportsBrowserNameOption; +import io.appium.java_client.remote.options.SupportsBrowserVersionOption; +import io.appium.java_client.remote.options.SupportsPageLoadStrategyOption; +import io.appium.java_client.remote.options.SupportsProxyOption; +import io.appium.java_client.remote.options.SupportsSetWindowRectOption; +import io.appium.java_client.remote.options.SupportsUnhandledPromptBehaviorOption; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.Platform; + +import java.util.Map; + +/** + * https://github.com/appium/appium-safari-driver#usage + */ +public class SafariOptions extends BaseOptions implements + SupportsBrowserNameOption, + SupportsBrowserVersionOption, + SupportsSafariPlatformVersionOption, + SupportsSafariPlatformBuildVersionOption, + SupportsSafariUseSimulatorOption, + SupportsSafariDeviceTypeOption, + SupportsSafariDeviceNameOption, + SupportsSafariDeviceUdidOption, + SupportsSafariAutomaticInspectionOption, + SupportsSafariAutomaticProfilingOption, + SupportsWebkitWebrtcOption, + SupportsAcceptInsecureCertsOption, + SupportsPageLoadStrategyOption, + SupportsSetWindowRectOption, + SupportsProxyOption, + SupportsUnhandledPromptBehaviorOption { + public SafariOptions() { + setCommonOptions(); + } + + public SafariOptions(Capabilities source) { + super(source); + setCommonOptions(); + } + + public SafariOptions(Map source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setPlatformName(Platform.IOS.toString()); + setAutomationName(AutomationName.SAFARI); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticInspectionOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticInspectionOption.java new file mode 100644 index 000000000..9b6e3ad29 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticInspectionOption.java @@ -0,0 +1,61 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariAutomaticInspectionOption> extends + Capabilities, CanSetCapability { + String SAFARI_AUTOMATIC_INSPECTION_OPTION = "safari:automaticInspection"; + + /** + * Enforces safaridriver to use Automatic Inspection. + * + * @return self instance for chaining. + */ + default T safariAutomaticInspection() { + return amend(SAFARI_AUTOMATIC_INSPECTION_OPTION, true); + } + + /** + * This capability instructs Safari to preload the Web Inspector and JavaScript + * debugger in the background prior to returning a newly-created window. + * To pause the test's execution in JavaScript and bring up Web Inspector's + * Debugger tab, you can simply evaluate a debugger; statement in the test page. + * + * @param bool Whether to use automatic inspection. + * @return self instance for chaining. + */ + default T setSafariAutomaticInspection(boolean bool) { + return amend(SAFARI_AUTOMATIC_INSPECTION_OPTION, bool); + } + + /** + * Get whether to use automatic inspection. + * + * @return true or false. + */ + default Optional doesSafariAutomaticInspection() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_AUTOMATIC_INSPECTION_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticProfilingOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticProfilingOption.java new file mode 100644 index 000000000..3fcc75215 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariAutomaticProfilingOption.java @@ -0,0 +1,61 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariAutomaticProfilingOption> extends + Capabilities, CanSetCapability { + String SAFARI_AUTOMATIC_PROFILING_OPTION = "safari:automaticProfiling"; + + /** + * Enforces safaridriver to use Automatic Inspection. + * + * @return self instance for chaining. + */ + default T safariAutomaticProfiling() { + return amend(SAFARI_AUTOMATIC_PROFILING_OPTION, true); + } + + /** + * This capability instructs Safari to preload the Web Inspector and start + * a Timeline recording in the background prior to returning a newly-created + * window. To view the recording, open the Web Inspector through Safari's + * Develop menu. + * + * @param bool Whether to use automatic profiling. + * @return self instance for chaining. + */ + default T setSafariAutomaticProfiling(boolean bool) { + return amend(SAFARI_AUTOMATIC_PROFILING_OPTION, bool); + } + + /** + * Get whether to use automatic profiling. + * + * @return true or false. + */ + default Optional doesSafariAutomaticProfiling() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_AUTOMATIC_PROFILING_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceNameOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceNameOption.java new file mode 100644 index 000000000..4e814d01f --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceNameOption.java @@ -0,0 +1,52 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariDeviceNameOption> extends + Capabilities, CanSetCapability { + String SAFARI_DEVICE_NAME_OPTION = "safari:deviceName"; + + /** + * safaridriver will only create a session using hosts whose device name + * matches the value of safari:deviceName. Device names are compared + * case-insensitively. NOTE: Device names for connected devices are shown in + * iTunes. If Xcode is installed, device names for connected devices are available + * via the output of instruments(1) and in the Devices and Simulators window + * (accessed in Xcode via "Window -> Devices and Simulators"). + * + * @param deviceName Device name. + * @return self instance for chaining. + */ + default T setSafariDeviceName(String deviceName) { + return amend(SAFARI_DEVICE_NAME_OPTION, deviceName); + } + + /** + * Get the name of the device. + * + * @return String representing the name of the device. + */ + default Optional getSafariDeviceName() { + return Optional.ofNullable((String) getCapability(SAFARI_DEVICE_NAME_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceTypeOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceTypeOption.java new file mode 100644 index 000000000..12179de61 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceTypeOption.java @@ -0,0 +1,50 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariDeviceTypeOption> extends + Capabilities, CanSetCapability { + String SAFARI_DEVICE_TYPE_OPTION = "safari:deviceType"; + + /** + * If the value of safari:deviceType is 'iPhone', safaridriver will only create a session + * using an iPhone device or iPhone simulator. If the value of safari:deviceType is 'iPad', + * safaridriver will only create a session using an iPad device or iPad simulator. + * Values of safari:deviceType are compared case-insensitively. + * + * @param deviceType Device type name. + * @return self instance for chaining. + */ + default T setSafariDeviceType(String deviceType) { + return amend(SAFARI_DEVICE_TYPE_OPTION, deviceType); + } + + /** + * Get the type of the device. + * + * @return String representing the type of the device. + */ + default Optional getSafariDeviceType() { + return Optional.ofNullable((String) getCapability(SAFARI_DEVICE_TYPE_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceUdidOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceUdidOption.java new file mode 100644 index 000000000..80ae57856 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariDeviceUdidOption.java @@ -0,0 +1,52 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariDeviceUdidOption> extends + Capabilities, CanSetCapability { + String SAFARI_DEVICE_UDID_OPTION = "safari:deviceUdid"; + + /** + * safaridriver will only create a session using hosts whose device UDID + * matches the value of safari:deviceUDID. Device UDIDs are compared + * case-insensitively. NOTE: If Xcode is installed, UDIDs for connected + * devices are available via the output of instruments(1) and in the + * Devices and Simulators window (accessed in Xcode via + * "Window -> Devices and Simulators"). + * + * @param deviceUdid Device UDID. + * @return self instance for chaining. + */ + default T setSafariDeviceUdid(String deviceUdid) { + return amend(SAFARI_DEVICE_UDID_OPTION, deviceUdid); + } + + /** + * Get the UDID of the device. + * + * @return String representing the UDID of the device. + */ + default Optional getSafariDeviceUdid() { + return Optional.ofNullable((String) getCapability(SAFARI_DEVICE_UDID_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformBuildVersionOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformBuildVersionOption.java new file mode 100644 index 000000000..d73993fe5 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformBuildVersionOption.java @@ -0,0 +1,50 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariPlatformBuildVersionOption> extends + Capabilities, CanSetCapability { + String SAFARI_PLATFORM_BUILD_VERSION_OPTION = "safari:platformBuildVersion"; + + /** + * safaridriver will only create a session using hosts whose OS build + * version matches the value of safari:platformBuildVersion. Example + * of a macOS build version is '18E193'. On macOS, the OS build version + * can be determined by running the sw_vers(1) utility. + * + * @param version is the platform build version. + * @return self instance for chaining. + */ + default T setSafariPlatformBuildVersion(String version) { + return amend(SAFARI_PLATFORM_BUILD_VERSION_OPTION, version); + } + + /** + * Get the build version of the platform. + * + * @return String representing the platform build version. + */ + default Optional getSafariPlatformBuildVersion() { + return Optional.ofNullable((String) getCapability(SAFARI_PLATFORM_BUILD_VERSION_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformVersionOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformVersionOption.java new file mode 100644 index 000000000..f6800b310 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariPlatformVersionOption.java @@ -0,0 +1,50 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsSafariPlatformVersionOption> extends + Capabilities, CanSetCapability { + String SAFARI_PLATFORM_VERSION_OPTION = "safari:platformVersion"; + + /** + * safaridriver will only create a session using hosts whose OS + * version matches the value of safari:platformVersion. OS version + * numbers are prefix-matched. For example, if the value of safari:platformVersion + * is '12', this will allow hosts with an OS version of '12.0' or '12.1' but not '10.12'. + * + * @param version is the platform version. + * @return self instance for chaining. + */ + default T setSafariPlatformVersion(String version) { + return amend(SAFARI_PLATFORM_VERSION_OPTION, version); + } + + /** + * Get the version of the platform. + * + * @return String representing the platform version. + */ + default Optional getSafariPlatformVersion() { + return Optional.ofNullable((String) getCapability(SAFARI_PLATFORM_VERSION_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsSafariUseSimulatorOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsSafariUseSimulatorOption.java new file mode 100644 index 000000000..948ef0a45 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsSafariUseSimulatorOption.java @@ -0,0 +1,61 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsSafariUseSimulatorOption> extends + Capabilities, CanSetCapability { + String SAFARI_USE_SIMULATOR_OPTION = "safari:useSimulator"; + + /** + * Enforces safaridriver to use iOS Simulator. + * + * @return self instance for chaining. + */ + default T safariUseSimulator() { + return amend(SAFARI_USE_SIMULATOR_OPTION, true); + } + + /** + * If the value of safari:useSimulator is true, safaridriver will only use + * iOS Simulator hosts. If the value of safari:useSimulator is false, safaridriver + * will not use iOS Simulator hosts. NOTE: An Xcode installation is required + * in order to run WebDriver tests on iOS Simulator hosts. + * + * @param bool is whether to use iOS Simulator. + * @return self instance for chaining. + */ + default T setSafariUseSimulator(boolean bool) { + return amend(SAFARI_USE_SIMULATOR_OPTION, bool); + } + + /** + * Get whether to use iOS Simulator. + * + * @return true or false. + */ + default Optional doesSafariUseSimulator() { + return Optional.ofNullable(toSafeBoolean(getCapability(SAFARI_USE_SIMULATOR_OPTION))); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/SupportsWebkitWebrtcOption.java b/src/main/java/io/appium/java_client/safari/options/SupportsWebkitWebrtcOption.java new file mode 100644 index 000000000..e22309f65 --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/SupportsWebkitWebrtcOption.java @@ -0,0 +1,51 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Map; +import java.util.Optional; + +public interface SupportsWebkitWebrtcOption> extends + Capabilities, CanSetCapability { + String WEBKIT_WEB_RTC_OPTION = "webkit:WebRTC"; + + /** + * This capability allows a test to temporarily change Safari's policies + * for WebRTC and Media Capture. + * + * @param webrtcData WebRTC policies. + * @return self instance for chaining. + */ + default T setWebkitWebrtc(WebrtcData webrtcData) { + return amend(WEBKIT_WEB_RTC_OPTION, webrtcData.toMap()); + } + + /** + * Get WebRTC policies. + * + * @return WebRTC policies. + */ + default Optional getWebkitWebrtc() { + //noinspection unchecked + return Optional.ofNullable((Map) getCapability(WEBKIT_WEB_RTC_OPTION)) + .map(WebrtcData::new); + } +} diff --git a/src/main/java/io/appium/java_client/safari/options/WebrtcData.java b/src/main/java/io/appium/java_client/safari/options/WebrtcData.java new file mode 100644 index 000000000..b1343432e --- /dev/null +++ b/src/main/java/io/appium/java_client/safari/options/WebrtcData.java @@ -0,0 +1,77 @@ +/* + * 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.safari.options; + +import io.appium.java_client.remote.options.BaseMapOptionData; + +import java.util.Map; +import java.util.Optional; + +public class WebrtcData extends BaseMapOptionData { + public WebrtcData() { + } + + public WebrtcData(Map options) { + super(options); + } + + /** + * Normally, Safari refuses to allow media capture over insecure connections. + * This restriction is relaxed by default for WebDriver sessions for testing + * purposes (for example, a test web server not configured for HTTPS). When + * this capability is specified, Safari will revert to the normal behavior of + * preventing media capture over insecure connections. + * + * @param disabled True to disable insecure media capture. + * @return self instance for chaining. + */ + public WebrtcData withDisableInsecureMediaCapture(boolean disabled) { + return assignOptionValue("DisableInsecureMediaCapture", disabled); + } + + /** + * Get whether to disable insecure media capture. + * + * @return True or false. + */ + public Optional doesDisableInsecureMediaCapture() { + return getOptionValue("DisableInsecureMediaCapture"); + } + + /** + * To protect a user's privacy, Safari normally filters out WebRTC + * ICE candidates that correspond to internal network addresses when + * capture devices are not in use. This capability suppresses ICE candidate + * filtering so that both internal and external network addresses are + * always sent as ICE candidates. + * + * @param disabled True to disable ICE candidates filtering. + * @return self instance for chaining. + */ + public WebrtcData withDisableIceCandidateFiltering(boolean disabled) { + return assignOptionValue("DisableICECandidateFiltering", disabled); + } + + /** + * Get whether to disable ICE candidates filtering. + * + * @return True or false. + */ + public Optional doesDisableIceCandidateFiltering() { + return getOptionValue("DisableICECandidateFiltering"); + } +} diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java index 9b12ceda9..8b842ee32 100644 --- a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -23,12 +23,16 @@ import io.appium.java_client.android.options.localization.AppLocale; import io.appium.java_client.android.options.server.EspressoBuildConfig; import io.appium.java_client.android.options.signing.KeystoreConfig; +import io.appium.java_client.gecko.options.GeckoOptions; +import io.appium.java_client.gecko.options.Verbosity; import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.ios.options.other.CommandTimeouts; import io.appium.java_client.ios.options.simulator.Permissions; import io.appium.java_client.mac.options.AppleScriptData; import io.appium.java_client.mac.options.Mac2Options; import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.safari.options.SafariOptions; +import io.appium.java_client.safari.options.WebrtcData; import io.appium.java_client.windows.options.PowerShellData; import io.appium.java_client.windows.options.WindowsOptions; import org.junit.Test; @@ -140,4 +144,40 @@ public void canBuildMac2Options() { assertTrue(options.doesSkipAppKill().orElse(false)); assertFalse(options.doesEventTimings().isPresent()); } + + @Test + public void canBuildGeckoOptions() { + GeckoOptions options = new GeckoOptions(); + options.setPlatformName(Platform.MAC.toString()); + assertEquals(Platform.MAC, options.getPlatformName()); + assertEquals(AutomationName.GECKO, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .setVerbosity(Verbosity.TRACE) + .setMozFirefoxOptions(ImmutableMap.of( + "profile", "yolo" + )); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertEquals(Verbosity.TRACE, options.getVerbosity().orElse(null)); + assertEquals("yolo", options.getMozFirefoxOptions().orElse(null) + .get("profile")); + } + + @Test + public void canBuildSafariOptions() { + SafariOptions options = new SafariOptions(); + assertEquals(Platform.IOS, options.getPlatformName()); + assertEquals(AutomationName.SAFARI, options.getAutomationName().orElse(null)); + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .safariUseSimulator() + .setWebkitWebrtc(new WebrtcData() + .withDisableIceCandidateFiltering(true) + .withDisableInsecureMediaCapture(true) + ); + assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); + assertTrue(options.doesSafariUseSimulator().orElse(false)); + assertTrue(options.getWebkitWebrtc().orElse(null) + .doesDisableIceCandidateFiltering().orElse(false)); + assertTrue(options.getWebkitWebrtc().orElse(null) + .doesDisableInsecureMediaCapture().orElse(false)); + } } From de3ded4d2c149cfa8ccf94d0618afd7b7e79e560 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 Nov 2021 14:14:55 +0100 Subject: [PATCH 035/501] refactor!: Remove setElementValue helper (#1577) --- .../io/appium/java_client/AppiumDriver.java | 1 - .../java_client/CanSetElementValue.java | 35 ------------------- .../android/AndroidElementTest.java | 2 +- .../java_client/ios/IOSElementTest.java | 3 +- .../pagefactory_tests/XCUITModeTest.java | 5 ++- 5 files changed, 4 insertions(+), 42 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/CanSetElementValue.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index abfdf126f..6d57cadd2 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -58,7 +58,6 @@ public class AppiumDriver extends RemoteWebDriver implements ComparesImages, ExecutesDriverScript, LogsEvents, - CanSetElementValue, HasBrowserCheck, HasSettings { diff --git a/src/main/java/io/appium/java_client/CanSetElementValue.java b/src/main/java/io/appium/java_client/CanSetElementValue.java deleted file mode 100644 index 45a7916b3..000000000 --- a/src/main/java/io/appium/java_client/CanSetElementValue.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 com.google.common.collect.ImmutableMap; -import org.openqa.selenium.remote.RemoteWebElement; - -public interface CanSetElementValue extends ExecutesMethod { - /** - * Set a value to an element. - * - * @param webElement Web element instance. - * @param value Value to set. - */ - default void setElementValue(RemoteWebElement webElement, String value) { - this.execute(MobileCommand.SET_VALUE, ImmutableMap.of( - "id", webElement.getId(), - "value", value - )); - } -} diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java index 9effaadbd..911dd8150 100644 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidElementTest.java @@ -85,7 +85,7 @@ public class AndroidElementTest extends BaseAndroidTest { driver.startActivity(activity); WebElement editElement = driver .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); - driver.setElementValue((RemoteWebElement) editElement, value); + editElement.sendKeys(value); assertEquals(value, editElement.getText()); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index 1004dc1a0..ca57c4cb4 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -10,7 +10,6 @@ import org.junit.Test; import org.junit.runners.MethodSorters; import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.ui.WebDriverWait; import io.appium.java_client.AppiumBy; @@ -33,7 +32,7 @@ public void setValueTest() { WebElement slider = wait.until( driver1 -> driver1.findElement(AppiumBy.className("XCUIElementTypeSlider"))); - driver.setElementValue((RemoteWebElement) slider, "0%"); + slider.sendKeys("0%"); assertEquals("0%", slider.getAttribute("value")); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java index aa72d203e..b56f67859 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java @@ -36,7 +36,6 @@ import org.junit.Test; import org.junit.runners.MethodSorters; import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.PageFactory; import java.util.List; @@ -141,8 +140,8 @@ public class XCUITModeTest extends AppIOSTest { } @Test public void setValueTest() { - driver.setElementValue((RemoteWebElement) textField1, "2"); - driver.setElementValue((RemoteWebElement) textField2, "4"); + textField1.sendKeys("2"); + textField2.sendKeys("4"); driver.hideKeyboard(); computeButton.click(); assertEquals("6", answer.getText()); From 087df2052abc177cea446825c48e3ab297a8ad6b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 Nov 2021 17:11:36 +0100 Subject: [PATCH 036/501] docs: Add v7->v8 migration guide (#1542) --- docs/v7-to-v8-migration-guide.md | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 docs/v7-to-v8-migration-guide.md diff --git a/docs/v7-to-v8-migration-guide.md b/docs/v7-to-v8-migration-guide.md new file mode 100644 index 000000000..09d119efc --- /dev/null +++ b/docs/v7-to-v8-migration-guide.md @@ -0,0 +1,96 @@ +This is the list of main changes between major versions 7 and 8 of Appium +java client. This list should help you to successfully migrate your +existing automated tests codebase. + + +## Strict W3C specification compatibility + +- Java client now supports Selenium 4, which also means it is +*strictly* W3C compliant. Old JWP-based servers are not supported +anymore, and it won't be possible to use the new client version +with them. Capabilities that enforce the usage of JWP protocol +on Appium drivers don't have any effect anymore. +- The recommended way to provide capabilities for driver creation is +to use specific option builders inherited from +[BaseOptions class](https://github.com/appium/java-client/blob/master/src/main/java/io/appium/java_client/remote/options/BaseOptions.java). +For example +[XCUITestOptions](https://github.com/appium/java-client/blob/master/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java) +to create a XCUITest driver instance or +[UiAutomator2Options](https://github.com/appium/java-client/blob/master/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java) +to create an UiAutomator2 driver instance. +If there is no driver-specific options class for your driver then either use +`BaseOptions` builder as the base class to define your capabilities or request +driver developers to add one. _Do not_ use `DesiredCapabilities` class for this purpose in W3C context. + +## Elements lookup + +- All `findBy*` shortcut methods were removed. Consider using +`findElement[s](By. or AppiumBy.)` instead. +- `MobileBy` class has been deprecated. Consider using +[AppiumBy](https://github.com/appium/java-client/blob/master/src/main/java/io/appium/java_client/AppiumBy.java) +instead. +- All locator names in `AppiumBy` have been aligned to follow the common +(camelCase) naming strategy, e.g. `MobileBy.AccessibilityId` was changed +to `AppiumBy.accessibilityId`. +- The changes made in Selenium 4 broke `class name` selector strategy in Appium. +`AppiumBy.className` should be used instead of Selenium's `By.className` now. + +## Time + +- All methods that use TimeUnit class or where the time is passed as +a simple numeric value were replaced with their alternatives using +[java.time.Duration](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html) +class. + +## Events + +- The current event firing mechanism that Appium java client uses +has been deprecated in favour of the one that Selenium 4 provides +natively. Read [The-event_firing.md](The-event_firing.md) for more +details on how to use it. + +## AppiumDriver + +- All `AppiumDriver` descendants and the base class itself are not generic +anymore and work with `WebElement` interface only. +- The base Appium driver does not extend `ContextAware`, `Rotatable` and other +mobile-specific interfaces. Instead, it only has the very basic set of methods. +Mobile specific extensions have been respectively moved to `IOSDriver` and +`AndroidDriver`. +- Removed the obsolete `HasSessionDetails` extensions as it was using legacy +JWP calls to retrieve session details. +- `DefaultGenericMobileDriver` class has been removed. Now `AppiumDriver` is +inherited directly from Selenium's `RemoteWebDriver`. + +## MobileElement + +- `DefaultGenericMobileElement` class has been removed completely together +with its descendants (`MobileElement`, `IOSElement`, `AndroidElement` etc.). +Use `WebElement` instead. +- Due to the above change the page factory is now only creating elements +that are instantiated from `RemoteWebElement` and implement `WebElement` interface. +- If you used some special methods that `MobileElement` or its descendants provided +then change these: + - `replaceValue` has been moved to the corresponding `AndroidDriver` + instance and is called now `replaceElementValue` + - use `sendKeys` method of `WebElement` interface instead of `setValue`. + +## Touch Actions + +- The `TouchAction` and `MultiTouchAction` classes have been deprecated. +The support of these actions will be removed from future Appium versions. +Please use [W3C Actions](https://w3c.github.io/webdriver/#actions) instead +or the corresponding extension methods for the driver (if available). +Check + - https://www.youtube.com/watch?v=oAJ7jwMNFVU + - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + - https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/android/android-mobile-gestures.md + - https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios/ios-xctest-mobile-gestures.md + - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api +for more details on how to properly apply W3C Actions to your automation context. + +## resetApp/launchApp/closeApp + +- AppiumDriver methods `resetApp`, `launchApp` and `closeApp` have been deprecated as +they are going to be removed from future Appium versions. Check +https://github.com/appium/appium/issues/15807 for more details. From 0d782deb51e07056062956a5695f7239db69f48f Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 Nov 2021 17:55:31 +0100 Subject: [PATCH 037/501] chore: Add Valery Yatsynovich to the list of project developers (#1578) --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index b7e92bea8..eee426391 100644 --- a/build.gradle +++ b/build.gradle @@ -139,6 +139,11 @@ publishing { url = 'https://github.com/mykola-mokhnach' id = 'mykola-mokhnach' } + developer { + name = 'Valery Yatsynovich' + url = 'https://github.com/valfirst' + id = 'valfirst' + } } licenses { license { From ec10b15cc184bda212ce4fffa5104416f0f7d3e9 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Tue, 2 Nov 2021 18:36:00 +0530 Subject: [PATCH 038/501] Release 8.0.0-beta and update release notes --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ build.gradle | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f7d6b0c69..85d87fbd6 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,51 @@ dependencies { ``` ## Changelog +*8.0.0-beta* +- **[ENHANCEMENTS]** + - Start adding UiAutomator2 options. [#1543](https://github.com/appium/java-client/pull/1543) + - Add more UiAutomator2 options. [#1545](https://github.com/appium/java-client/pull/1545) + - Finish creating options for UiAutomator2 driver. [#1548](https://github.com/appium/java-client/pull/1548) + - Add WDA-related XCUITestOptions. [#1552](https://github.com/appium/java-client/pull/1552) + - Add web view options for XCUITest driver. [#1557](https://github.com/appium/java-client/pull/1557) + - Add the rest of XCUITest driver options. [#1561](https://github.com/appium/java-client/pull/1561) + - Add Espresso options. [#1563](https://github.com/appium/java-client/pull/1563) + - Add Windows driver options. [#1564](https://github.com/appium/java-client/pull/1564) + - Add Mac2 driver options. [#1565](https://github.com/appium/java-client/pull/1565) + - Add Gecko driver options. [#1573](https://github.com/appium/java-client/pull/1573) + - Add Safari driver options. [#1576](https://github.com/appium/java-client/pull/1576) + - Start adding XCUITest driver options. [#1551](https://github.com/appium/java-client/pull/1551) + - Implement driver-specific W3C option classes. [#1540](https://github.com/appium/java-client/pull/1540) + - Update Service to properly work with options. [#1550](https://github.com/appium/java-client/pull/1550) +- **[BREAKING CHANGE]** + - Migrate to Selenium 4. [#1531](https://github.com/appium/java-client/pull/1531) + - Make sure we only write W3C payload into create session command. [#1537](https://github.com/appium/java-client/pull/1537) + - Use the new session payload creator inherited from Selenium. [#1535](https://github.com/appium/java-client/pull/1535) + - unify locator factories naming and toString implementations. [#1538](https://github.com/appium/java-client/pull/1538) + - drop support of deprecated Selendroid driver. [#1553](https://github.com/appium/java-client/pull/1553) + - switch to javac compiler. [#1556](https://github.com/appium/java-client/pull/1556) + - revise used Selenium dependencies. [#1560](https://github.com/appium/java-client/pull/1560) + - change prefix to AppiumBy in locator toString implementation. [#1559](https://github.com/appium/java-client/pull/1559) + - enable dependencies caching. [#1567](https://github.com/appium/java-client/pull/1567) + - Include more tests into the pipeline. [#1566](https://github.com/appium/java-client/pull/1566) + - Tune setting of default platform names. [#1570](https://github.com/appium/java-client/pull/1570) + - Deprecate custom event listener implementation and default to the one provided by Selenium4. [#1541](https://github.com/appium/java-client/pull/1541) + - Deprecate touch actions. [#1569](https://github.com/appium/java-client/pull/1569) + - Deprecate legacy app management helpers. [#1571](https://github.com/appium/java-client/pull/1571) + - deprecate Windows UIAutomation selector. [#1562](https://github.com/appium/java-client/pull/1562) + - Remove unused entities. [#1572](https://github.com/appium/java-client/pull/1572) + - Remove setElementValue helper. [#1577](https://github.com/appium/java-client/pull/1577) + - Remove selenium package override. [#1555](https://github.com/appium/java-client/pull/1555) + - remove redundant exclusion of Gradle task signMavenJavaPublication. [#1568](https://github.com/appium/java-client/pull/1568) +- **[BUG FIX]** + - AndroidGeoLocation: update the constructor signature to mimic order of parameters in `org.openqa.selenium.html5.Location`. [#1526](https://github.com/appium/java-client/pull/1526) + - Prevent duplicate builds for PRs from base repo branches. [#1496](https://github.com/appium/java-client/pull/1496) + - Enable Dependabot for GitHub actions. [#1500](https://github.com/appium/java-client/pull/1500) + - bind mac2element in element map for mac platform. [#1474](https://github.com/appium/java-client/pull/1474) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 6.4.1. + - `com.google.code.gson:gson` was updated to 2.8.9. + *7.6.0* - **[ENHANCEMENTS]** - Add custom commands dynamically [Appium 2.0]. [#1506](https://github.com/appium/java-client/pull/1506) diff --git a/build.gradle b/build.gradle index eee426391..d1422c132 100644 --- a/build.gradle +++ b/build.gradle @@ -109,7 +109,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '7.6.0' + version = '8.0.0-beta' from components.java pom { name = 'java-client' From beb696c16f16da503a780a4686ed7eef9b197d1f Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Wed, 3 Nov 2021 14:56:18 +0530 Subject: [PATCH 039/501] update change-log in readme --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 85d87fbd6..d83f541ba 100644 --- a/README.md +++ b/README.md @@ -102,11 +102,6 @@ dependencies { - Remove setElementValue helper. [#1577](https://github.com/appium/java-client/pull/1577) - Remove selenium package override. [#1555](https://github.com/appium/java-client/pull/1555) - remove redundant exclusion of Gradle task signMavenJavaPublication. [#1568](https://github.com/appium/java-client/pull/1568) -- **[BUG FIX]** - - AndroidGeoLocation: update the constructor signature to mimic order of parameters in `org.openqa.selenium.html5.Location`. [#1526](https://github.com/appium/java-client/pull/1526) - - Prevent duplicate builds for PRs from base repo branches. [#1496](https://github.com/appium/java-client/pull/1496) - - Enable Dependabot for GitHub actions. [#1500](https://github.com/appium/java-client/pull/1500) - - bind mac2element in element map for mac platform. [#1474](https://github.com/appium/java-client/pull/1474) - **[DEPENDENCY UPDATES]** - `org.owasp.dependencycheck` was updated to 6.4.1. - `com.google.code.gson:gson` was updated to 2.8.9. From 21d92f0b41cf3efbe69a22db9d8937190c20c54f Mon Sep 17 00:00:00 2001 From: ayuryev <46725671+ayuryev@users.noreply.github.com> Date: Fri, 5 Nov 2021 17:14:26 +0200 Subject: [PATCH 040/501] fix: filter out new in java16+ method(s) from proxy class for by-builder (#1582) --- .../bys/builder/AppiumByBuilder.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java index 3a18cf940..bf7419892 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java @@ -30,8 +30,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; /** * It is the basic handler of Appium-specific page object annotations @@ -45,13 +47,11 @@ public abstract class AppiumByBuilder extends AbstractAnnotations { private static final List METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ = new ArrayList() { private static final long serialVersionUID = 1L; { - List objectClassMethodNames = - getMethodNames(Object.class.getDeclaredMethods()); - addAll(objectClassMethodNames); - List annotationClassMethodNames = - getMethodNames(Annotation.class.getDeclaredMethods()); - annotationClassMethodNames.removeAll(objectClassMethodNames); - addAll(annotationClassMethodNames); + Stream.of(Object.class, Annotation.class, Proxy.class) + .map(Class::getDeclaredMethods) + .map(AppiumByBuilder::getMethodNames) + .flatMap(List::stream) + .forEach(this::add); } }; protected final AnnotatedElementContainer annotatedElementContainer; @@ -73,13 +73,13 @@ private static List getMethodNames(Method[] methods) { } private static Method[] prepareAnnotationMethods(Class annotation) { - List targeAnnotationMethodNamesList = + List targetAnnotationMethodNamesList = getMethodNames(annotation.getDeclaredMethods()); - targeAnnotationMethodNamesList.removeAll(METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ); - Method[] result = new Method[targeAnnotationMethodNamesList.size()]; - for (String methodName : targeAnnotationMethodNamesList) { + targetAnnotationMethodNamesList.removeAll(METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ); + Method[] result = new Method[targetAnnotationMethodNamesList.size()]; + for (String methodName : targetAnnotationMethodNamesList) { try { - result[targeAnnotationMethodNamesList.indexOf(methodName)] = + result[targetAnnotationMethodNamesList.indexOf(methodName)] = annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException(e); From 3550ba78cd0014f897f4e53882fec083039afbbd Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 5 Nov 2021 19:09:20 +0100 Subject: [PATCH 041/501] refactor: Add more nice functional stuff into pagefactory helpers (#1584) --- .../pagefactory/DefaultElementByBuilder.java | 4 +- .../pagefactory/bys/ContentType.java | 3 +- .../bys/builder/AppiumByBuilder.java | 114 ++++++++---------- .../pagefactory/bys/builder/ByChained.java | 5 +- .../bys/builder/HowToUseSelectors.java | 4 +- .../pagefactory/bys/builder/Strategies.java | 10 +- 6 files changed, 64 insertions(+), 76 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index d31b56fe4..135c2f423 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -50,7 +50,7 @@ public class DefaultElementByBuilder extends AppiumByBuilder { private static final String PRIORITY = "priority"; private static final String VALUE = "value"; - private static final Class[] ANNOTATION_ARGUMENTS = new Class[]{}; + private static final Class[] ANNOTATION_ARGUMENTS = new Class[]{}; private static final Object[] ANNOTATION_PARAMETERS = new Object[]{}; public DefaultElementByBuilder(String platform, String automation) { @@ -155,7 +155,7 @@ private By[] getBys(Class singleLocator, Class[] DEFAULT_ANNOTATION_METHOD_ARGUMENTS = new Class[] {}; + protected static final Class[] DEFAULT_ANNOTATION_METHOD_ARGUMENTS = new Class[]{}; - private static final List METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ = - new ArrayList() { - private static final long serialVersionUID = 1L; { - Stream.of(Object.class, Annotation.class, Proxy.class) + private static final List METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ = new ArrayList() { + private static final long serialVersionUID = 1L; + + { + Stream.of(Object.class, Annotation.class, Proxy.class) .map(Class::getDeclaredMethods) .map(AppiumByBuilder::getMethodNames) .flatMap(List::stream) .forEach(this::add); - } - }; + } + }; protected final AnnotatedElementContainer annotatedElementContainer; protected final String platform; protected final String automation; @@ -65,79 +68,68 @@ protected AppiumByBuilder(String platform, String automation) { } private static List getMethodNames(Method[] methods) { - List names = new ArrayList<>(); - for (Method m : methods) { - names.add(m.getName()); - } - return names; + return Stream.of(methods).map(Method::getName).collect(Collectors.toList()); } private static Method[] prepareAnnotationMethods(Class annotation) { - List targetAnnotationMethodNamesList = - getMethodNames(annotation.getDeclaredMethods()); + List targetAnnotationMethodNamesList = getMethodNames(annotation.getDeclaredMethods()); targetAnnotationMethodNamesList.removeAll(METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ); - Method[] result = new Method[targetAnnotationMethodNamesList.size()]; - for (String methodName : targetAnnotationMethodNamesList) { - try { - result[targetAnnotationMethodNamesList.indexOf(methodName)] = - annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); - } catch (NoSuchMethodException | SecurityException e) { - throw new RuntimeException(e); - } - } - return result; + return targetAnnotationMethodNamesList.stream() + .map((methodName) -> { + try { + return annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException(e); + } + }).toArray(Method[]::new); } private static String getFilledValue(Annotation mobileBy) { - Method[] values = prepareAnnotationMethods(mobileBy.getClass()); - for (Method value : values) { - if (!String.class.equals(value.getReturnType())) { - continue; - } - - try { - String strategyParameter = value.invoke(mobileBy).toString(); - if (!strategyParameter.isEmpty()) { - return value.getName(); - } - } catch (IllegalAccessException - | IllegalArgumentException - | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - throw new IllegalArgumentException( - "@" + mobileBy.getClass().getSimpleName() + ": one of " + Strategies.strategiesNames() - .toString() + " should be filled"); + return Stream.of(prepareAnnotationMethods(mobileBy.getClass())) + .filter((method) -> String.class == method.getReturnType()) + .filter((method) -> { + try { + Object strategyParameter = method.invoke(mobileBy); + return strategyParameter != null && !String.valueOf(strategyParameter).isEmpty(); + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + throw new RuntimeException(e); + } + }) + .findFirst() + .map(Method::getName) + .orElseThrow(() -> new IllegalArgumentException( + String.format("@%s: one of %s should be filled", + mobileBy.getClass().getSimpleName(), Strategies.strategiesNames()) + )); } private static By getMobileBy(Annotation annotation, String valueName) { - Strategies[] strategies = Strategies.values(); - for (Strategies strategy : strategies) { - if (strategy.returnValueName().equals(valueName)) { - return strategy.getBy(annotation); - } - } - throw new IllegalArgumentException( - "@" + annotation.getClass().getSimpleName() + ": There is an unknown strategy " - + valueName); + return Stream.of(Strategies.values()) + .filter((strategy) -> strategy.returnValueName().equals(valueName)) + .findFirst() + .map((strategy) -> strategy.getBy(annotation)) + .orElseThrow(() -> new IllegalArgumentException( + String.format("@%s: There is an unknown strategy %s", + annotation.getClass().getSimpleName(), valueName) + )); } - private static T getComplexMobileBy(Annotation[] annotations, - Class requiredByClass) { - By[] byArray = new By[annotations.length]; - for (int i = 0; i < annotations.length; i++) { - byArray[i] = getMobileBy(annotations[i], getFilledValue(annotations[i])); - } + private static T getComplexMobileBy(Annotation[] annotations, Class requiredByClass) { + By[] byArray = Stream.of(annotations) + .map((annotation) -> getMobileBy(annotation, getFilledValue(annotation))) + .toArray(By[]::new); try { Constructor c = requiredByClass.getConstructor(By[].class); - Object[] values = new Object[] {byArray}; + Object[] values = new Object[]{byArray}; return c.newInstance(values); - } catch (Exception e) { + } catch (InvocationTargetException | NoSuchMethodException | InstantiationException + | IllegalAccessException e) { throw new RuntimeException(e); } } + @Nullable protected static By createBy(Annotation[] annotations, HowToUseSelectors howToUseLocators) { if (annotations == null || annotations.length == 0) { return null; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java index 0ea7dde77..f8d2240cb 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java @@ -35,6 +35,9 @@ public class ByChained extends org.openqa.selenium.support.pagefactory.ByChained private static AppiumFunction getSearchingFunction(By by) { return input -> { try { + if (input == null) { + return null; + } return input.findElement(by); } catch (NoSuchElementException e) { return null; @@ -71,7 +74,7 @@ public WebElement findElement(SearchContext context) { checkNotNull(searchingFunction); return waiting.until(searchingFunction); } catch (TimeoutException e) { - throw new NoSuchElementException("Cannot locate an element using " + toString()); + throw new NoSuchElementException("Cannot locate an element using " + this); } } } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java index 8fce3c467..a4d4f4fdb 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java @@ -17,7 +17,5 @@ package io.appium.java_client.pagefactory.bys.builder; public enum HowToUseSelectors { - USE_ONE, - BUILD_CHAINED, - USE_ANY; + USE_ONE, BUILD_CHAINED, USE_ANY } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 7b1d13ab1..d175f37e3 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -19,8 +19,9 @@ import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.openqa.selenium.By; @@ -127,12 +128,7 @@ enum Strategies { } static List strategiesNames() { - Strategies[] strategies = values(); - List result = new ArrayList<>(); - for (Strategies strategy : strategies) { - result.add(strategy.valueName); - } - return result; + return Stream.of(values()).map((s) -> s.valueName).collect(Collectors.toList()); } private static String getValue(Annotation annotation, Strategies strategy) { From 07483273030fe97045caa89c01279f9bf3842dbb Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sat, 6 Nov 2021 18:28:36 +0300 Subject: [PATCH 042/501] build: check build on JDK 8, 11, 17 (#1583) --- .github/workflows/gradle.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d02903e8f..494ab23bd 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,13 +13,18 @@ jobs: runs-on: macOS-latest + strategy: + matrix: + java: [ 8, 11, 17 ] + + name: JDK ${{ matrix.java }} steps: - uses: actions/checkout@v1 - - name: Set up JDK 8 + - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v2.3.1 with: distribution: 'zulu' - java-version: 8 + java-version: ${{ matrix.java }} cache: 'gradle' - name: Build with Gradle run: ./gradlew clean build -x test -x checkstyleTest From 4810b7ecf2994effe16755d28d0a70110dfd4fda Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 17 Nov 2021 00:07:57 +0300 Subject: [PATCH 043/501] chore: upgrade to Gradle 7.3 (#1594) --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 257 ++++++++++++++--------- 2 files changed, 154 insertions(+), 105 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index af7be50b1..fbce071a3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 744e882ed..1b6c78733 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" From 48ca7aeb04cb491def791491db558c095a2bb391 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 11:10:46 +0300 Subject: [PATCH 044/501] build(deps): bump org.owasp.dependencycheck from 6.4.1.1 to 6.5.0.1 (#1590) Bumps org.owasp.dependencycheck from 6.4.1.1 to 6.5.0.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d1422c132..343953083 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.4.1.1' + id 'org.owasp.dependencycheck' version '6.5.0.1' id 'com.github.johnrengelman.shadow' version '7.1.0' } From 42b2fa8531fe62ffe2e9f2dfb2c9847e45713f2e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 17 Nov 2021 11:19:56 +0100 Subject: [PATCH 045/501] docs: Add a link to options builder examples to the migration guide (#1595) --- docs/v7-to-v8-migration-guide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/v7-to-v8-migration-guide.md b/docs/v7-to-v8-migration-guide.md index 09d119efc..cdac6ee53 100644 --- a/docs/v7-to-v8-migration-guide.md +++ b/docs/v7-to-v8-migration-guide.md @@ -21,6 +21,8 @@ to create an UiAutomator2 driver instance. If there is no driver-specific options class for your driver then either use `BaseOptions` builder as the base class to define your capabilities or request driver developers to add one. _Do not_ use `DesiredCapabilities` class for this purpose in W3C context. +Check [unit tests](https://github.com/appium/java-client/blob/master/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java) +for more examples on how to build driver options. ## Elements lookup From 82fb923a4a4dce0b35e3436e054bfe80d679dc3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 13:54:10 +0300 Subject: [PATCH 046/501] build(deps): bump spring-context from 5.3.12 to 5.3.13 (#1589) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.12 to 5.3.13. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.12...v5.3.13) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 343953083..181cddb86 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.12' + implementation 'org.springframework:spring-context:5.3.13' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.32' From 665c7f5a4bcaaff5442a1c1fd41f460063c1a836 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 26 Nov 2021 16:53:47 +0100 Subject: [PATCH 047/501] refactor!: Switch e2e tests to use Appium2 (#1603) BREAKING CHANGE: Updated command line args to comply with Appium 2.0 BREAKING CHANGE: The default local service URL does not contain the /wd/hub prefix anymore --- .azure-templates/bootstrap_steps.yml | 2 +- azure-pipelines.yml | 6 +++- docs/v7-to-v8-migration-guide.md | 12 +++++++ .../local/AppiumDriverLocalService.java | 35 ++++++++++++++++--- .../service/local/AppiumServiceBuilder.java | 13 +++---- .../local/flags/GeneralServerFlag.java | 34 +++++------------- .../java_client/android/BaseAndroidTest.java | 13 +++---- .../io/appium/java_client/ios/AppIOSTest.java | 13 +++---- .../appium/java_client/ios/BaseIOSTest.java | 22 ++++++------ .../java_client/ios/BaseIOSWebViewTest.java | 17 ++------- .../java_client/ios/BaseSafariTest.java | 10 ++---- .../service/local/ServerBuilderTest.java | 11 +++--- 12 files changed, 93 insertions(+), 95 deletions(-) diff --git a/.azure-templates/bootstrap_steps.yml b/.azure-templates/bootstrap_steps.yml index 9f4e3032b..baf4b6979 100644 --- a/.azure-templates/bootstrap_steps.yml +++ b/.azure-templates/bootstrap_steps.yml @@ -7,4 +7,4 @@ steps: npm config set prefix $NVM_DIR/versions/node/`node --version` node --version - npm install -g appium@beta + npm install -g appium@next diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 67d36f46e..51703c04f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,13 +14,15 @@ variables: XCODE_VERSION: 11.5 IOS_PLATFORM_VERSION: 13.5 IOS_DEVICE_NAME: iPhone X - NODE_VERSION: 12.x + NODE_VERSION: 14.x JDK_VERSION: 1.8 jobs: - job: Android_E2E_Tests steps: - template: .azure-templates/bootstrap_steps.yml + - script: $NVM_DIR/versions/node/`node --version`/bin/appium driver install uiautomator2 + displayName: Install UIA2 driver - script: | echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;$(ANDROID_EMU_TARGET);$(ANDROID_EMU_TAG);$(ANDROID_EMU_ABI)' echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n "$(ANDROID_EMU_NAME)" -k 'system-images;$(ANDROID_EMU_TARGET);$(ANDROID_EMU_TAG);$(ANDROID_EMU_ABI)' --force @@ -50,6 +52,8 @@ jobs: sudo xcode-select -s /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer xcrun simctl list displayName: Simulator configuration + - script: $NVM_DIR/versions/node/`node --version`/bin/appium driver install xcuitest + displayName: Install XCUITest driver - task: Gradle@2 inputs: gradleWrapperFile: 'gradlew' diff --git a/docs/v7-to-v8-migration-guide.md b/docs/v7-to-v8-migration-guide.md index cdac6ee53..72cdc08c6 100644 --- a/docs/v7-to-v8-migration-guide.md +++ b/docs/v7-to-v8-migration-guide.md @@ -96,3 +96,15 @@ for more details on how to properly apply W3C Actions to your automation context - AppiumDriver methods `resetApp`, `launchApp` and `closeApp` have been deprecated as they are going to be removed from future Appium versions. Check https://github.com/appium/appium/issues/15807 for more details. + +## AppiumDriverLocalService + +- The default URL the server is listening on has been changed, and it +does not contain the `/wd/hub` suffix anymore (e.g. `http://0.0.0.0:4723/wd/hub` +became `http://0.0.0.0:4723/`). This has been done in order +to align the actual behavior with Appium v2. If you still would like to use +v8 of the Java client with Appium v1.2x, where the server URL contains the `/wd/hub` suffix +by default, then consider providing `--base-path` setting explicitly while +building `AppiumServiceBuilder` instance (e.g. `.withArgument(GeneralServerFlag.BASEPATH, "/wd/hub")`). +Older versions of Appium server (v1.19 and older) won't work with `AppiumDriverLocalService`, +because they don't allow provisioning of base path in form of a command line argument. diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 37851fd4b..ac86cf91b 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting; +import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.net.UrlChecker; @@ -37,6 +38,7 @@ import java.io.OutputStream; import java.lang.reflect.Field; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.time.Duration; import java.util.List; @@ -52,7 +54,7 @@ public final class AppiumDriverLocalService extends DriverService { - private static final String URL_MASK = "http://%s:%d/wd/hub"; + private static final String URL_MASK = "http://%s:%d/"; private static final Logger LOG = LoggerFactory.getLogger(AppiumDriverLocalService.class); private static final Pattern LOG_MESSAGE_PATTERN = Pattern.compile("^(.*)\\R"); private static final Pattern LOGGER_CONTEXT_PATTERN = Pattern.compile("^(\\[debug\\] )?\\[(.+?)\\]"); @@ -66,11 +68,14 @@ public final class AppiumDriverLocalService extends DriverService { private final ReentrantLock lock = new ReentrantLock(true); //uses "fair" thread ordering policy private final ListOutputStream stream = new ListOutputStream().add(System.out); private final URL url; + private String basePath; private CommandLine process = null; - AppiumDriverLocalService(String ipAddress, File nodeJSExec, int nodeJSPort, Duration startupTimeout, - List nodeJSArgs, Map nodeJSEnvironment) throws IOException { + AppiumDriverLocalService(String ipAddress, File nodeJSExec, + int nodeJSPort, Duration startupTimeout, + List nodeJSArgs, Map nodeJSEnvironment + ) throws IOException { super(nodeJSExec, nodeJSPort, startupTimeout, nodeJSArgs, nodeJSEnvironment); this.nodeJSExec = nodeJSExec; this.nodeJSArgs = nodeJSArgs; @@ -87,6 +92,26 @@ public static AppiumDriverLocalService buildService(AppiumServiceBuilder builder return builder.build(); } + public AppiumDriverLocalService withBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public String getBasePath() { + return this.basePath; + } + + @SneakyThrows + private static URL addSuffix(URL url, String suffix) { + return url.toURI().resolve("." + (suffix.startsWith("/") ? suffix : "/" + suffix)).toURL(); + } + + @SneakyThrows + @SuppressWarnings("SameParameterValue") + private static URL replaceHost(URL source, String oldHost, String newHost) { + return new URL(source.toString().replace(oldHost, newHost)); + } + /** * Base URL. * @@ -94,7 +119,7 @@ public static AppiumDriverLocalService buildService(AppiumServiceBuilder builder */ @Override public URL getUrl() { - return url; + return basePath == null ? url : addSuffix(url, basePath); } @Override @@ -125,7 +150,7 @@ public boolean isRunning() { private void ping(Duration timeout) throws UrlChecker.TimeoutException, MalformedURLException { // The operating system might block direct access to the universal broadcast IP address - URL status = new URL(url.toString().replace(BROADCAST_IP_ADDRESS, "127.0.0.1") + "/status"); + URL status = addSuffix(replaceHost(getUrl(), BROADCAST_IP_ADDRESS, "127.0.0.1"), "/status"); new UrlChecker().waitUntilAvailable(timeout.toMillis(), TimeUnit.MILLISECONDS, status); } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 93124226a..cf1e5ee89 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -25,8 +25,10 @@ import io.appium.java_client.remote.AndroidMobileCapabilityType; import io.appium.java_client.remote.MobileBrowserType; import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.appium.java_client.service.local.flags.ServerArgument; +import lombok.SneakyThrows; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; @@ -446,16 +448,15 @@ public AppiumServiceBuilder withLogFile(File logFile) { return super.withLogFile(logFile); } + @SneakyThrows @Override protected AppiumDriverLocalService createDriverService(File nodeJSExecutable, int nodeJSPort, Duration startupTimeout, List nodeArguments, Map nodeEnvironment) { - try { - return new AppiumDriverLocalService(ipAddress, nodeJSExecutable, nodeJSPort, startupTimeout, nodeArguments, - nodeEnvironment); - } catch (IOException e) { - throw new RuntimeException(e); - } + String basePath = serverArguments.getOrDefault( + GeneralServerFlag.BASEPATH.getArgument(), serverArguments.get("-pa")); + return new AppiumDriverLocalService(ipAddress, nodeJSExecutable, nodeJSPort, startupTimeout, nodeArguments, + nodeEnvironment).withBasePath(basePath); } } diff --git a/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java b/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java index 817deae05..19b69c38c 100644 --- a/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java +++ b/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java @@ -16,7 +16,6 @@ package io.appium.java_client.service.local.flags; - /** * Here is the list of common Appium server arguments. */ @@ -43,7 +42,10 @@ public enum GeneralServerFlag implements ServerArgument { * Pre-launch the application before allowing the first session * (Requires –app and, for Android, –app-pkg and –app-activity). * Default: false + * + * @deprecated This argument has been removed from Appium 2.0 */ + @Deprecated PRE_LAUNCH("--pre-launch"), /** * The message log level to be shown. @@ -75,14 +77,6 @@ public enum GeneralServerFlag implements ServerArgument { * --nodeconfig /abs/path/to/nodeconfig.json */ CONFIGURATION_FILE("--nodeconfig"), - /** - * IP Address of robot. Sample: --robot-address 0.0.0.0 - */ - ROBOT_ADDRESS("--robot-address"), - /** - * Port for robot. Sample: --robot-port 4242 - */ - ROBOT_PORT("--robot-port"), /** * Show info about the Appium server configuration and exit. Default: false */ @@ -140,33 +134,21 @@ public enum GeneralServerFlag implements ServerArgument { * Plugins are available with Appium as of Appium 2.0. * To activate all plugins, you can use the single string "all" as the value (e.g --plugins=all) * Default: [] - * Sample: --plugins=device-farm,images + * Sample: --use-plugins=device-farm,images */ - PLUGINS("--plugins"), + USE_PLUGINS("--use-plugins"), /** * A comma-separated list of installed driver names that should be active for this server. * All drivers will be active by default. * Default: [] - * Sample: --drivers=uiautomator2,xcuitest + * Sample: --use-drivers=uiautomator2,xcuitest */ - DRIVERS("--drivers"), + USE_DRIVERS("--use-drivers"), /** * Base path to use as the prefix for all webdriver routes running on this server. * Sample: --base-path=/wd/hub */ - BASEPATH("--base-path"), - /** - * Set the default desired client arguments for a plugin. - * Default: [] - * Sample: [ '{"images":{"foo1": "bar1", "foo2": "bar2"}}' | /path/to/pluginArgs.json ] - */ - PLUGINARGS("--plugin-args"), - /** - * Set the default desired client arguments for a driver. - * Default: [] - * Sample: [ '{"xcuitest": {"foo1": "bar1", "foo2": "bar2"}}' | /path/to/driverArgs.json ] - */ - DRIVERARGS("--driver-args"); + BASEPATH("--base-path"); private final String arg; diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 997b83a23..b6a4e5421 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -18,8 +18,8 @@ import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; +import io.appium.java_client.service.local.AppiumServiceBuilder; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -27,6 +27,8 @@ public class BaseAndroidTest { public static final String APP_ID = "io.appium.android.apis"; + protected static final int PORT = 4723; + private static AppiumDriverLocalService service; protected static AndroidDriver driver; @@ -34,12 +36,11 @@ public class BaseAndroidTest { * initialization. */ @BeforeClass public static void beforeClass() { - service = AppiumDriverLocalService.buildDefaultService(); + service = new AppiumServiceBuilder() + .withIPAddress("127.0.0.1") + .usingPort(PORT) + .build(); service.start(); - if (service == null || !service.isRunning()) { - throw new AppiumServerHasNotBeenStartedLocallyException( - "An appium server node is not started!"); - } UiAutomator2Options options = new UiAutomator2Options() .setDeviceName("Android Emulator") diff --git a/src/test/java/io/appium/java_client/ios/AppIOSTest.java b/src/test/java/io/appium/java_client/ios/AppIOSTest.java index 5aad73dfe..e84ae96fa 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/AppIOSTest.java @@ -1,11 +1,9 @@ package io.appium.java_client.ios; import io.appium.java_client.ios.options.XCUITestOptions; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.BeforeClass; import org.openqa.selenium.SessionNotCreatedException; -import java.net.URL; import java.time.Duration; import static io.appium.java_client.TestResources.testAppZip; @@ -16,22 +14,19 @@ public class AppIOSTest extends BaseIOSTest { @BeforeClass public static void beforeClass() throws Exception { - final String ip = startAppiumServer(); - - if (service == null || !service.isRunning()) { - throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!"); - } + startAppiumServer(); XCUITestOptions options = new XCUITestOptions() + .setPlatformVersion(PLATFORM_VERSION) .setDeviceName(DEVICE_NAME) .setCommandTimeouts(Duration.ofSeconds(240)) .setApp(testAppZip().toAbsolutePath().toString()) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); try { - driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); + driver = new IOSDriver(service.getUrl(), options); } catch (SessionNotCreatedException e) { options.useNewWDA(); - driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); + driver = new IOSDriver(service.getUrl(), options); } } } \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index c887ab6f8..2f4d1f5f1 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -20,33 +20,33 @@ import io.appium.java_client.service.local.AppiumServiceBuilder; import org.junit.AfterClass; -import java.net.SocketException; -import java.net.UnknownHostException; import java.time.Duration; -import static io.appium.java_client.TestUtils.getLocalIp4Address; - public class BaseIOSTest { protected static AppiumDriverLocalService service; protected static IOSDriver driver; protected static final int PORT = 4723; public static final String DEVICE_NAME = System.getenv("IOS_DEVICE_NAME") != null - ? System.getenv("IOS_DEVICE_NAME") : "iPhone 12"; + ? System.getenv("IOS_DEVICE_NAME") + : "iPhone 12"; public static final String PLATFORM_VERSION = System.getenv("IOS_PLATFORM_VERSION") != null - ? System.getenv("IOS_PLATFORM_VERSION") : "14.5"; + ? System.getenv("IOS_PLATFORM_VERSION") + : "14.5"; public static final Duration WDA_LAUNCH_TIMEOUT = Duration.ofSeconds(240); /** * Starts a local server. * - * @return ip of a local host - * @throws UnknownHostException when it is impossible to get ip address of a local host + * @return service instance */ - public static String startAppiumServer() throws UnknownHostException, SocketException { - service = new AppiumServiceBuilder().usingPort(PORT).build(); + public static AppiumDriverLocalService startAppiumServer() { + service = new AppiumServiceBuilder() + .withIPAddress("127.0.0.1") + .usingPort(PORT) + .build(); service.start(); - return getLocalIp4Address(); + return service; } /** diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 74b1c8f62..7aed47831 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -17,13 +17,10 @@ package io.appium.java_client.ios; import io.appium.java_client.ios.options.XCUITestOptions; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.BeforeClass; import org.openqa.selenium.SessionNotCreatedException; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.time.Duration; import java.util.function.Supplier; @@ -35,24 +32,14 @@ public class BaseIOSWebViewTest extends BaseIOSTest { @BeforeClass public static void beforeClass() throws IOException { - final String ip = startAppiumServer(); - - if (service == null || !service.isRunning()) { - throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!"); - } + startAppiumServer(); XCUITestOptions options = new XCUITestOptions() .setDeviceName(DEVICE_NAME) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) .setCommandTimeouts(Duration.ofSeconds(240)) .setApp(vodQaAppZip().toAbsolutePath().toString()); - Supplier createDriver = () -> { - try { - return new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - }; + Supplier createDriver = () -> new IOSDriver(service.getUrl(), options); try { driver = createDriver.get(); } catch (SessionNotCreatedException e) { diff --git a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java index 0dd44f2a6..4204cff41 100644 --- a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java @@ -18,26 +18,20 @@ import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.BeforeClass; import java.io.IOException; -import java.net.URL; public class BaseSafariTest extends BaseIOSTest { @BeforeClass public static void beforeClass() throws IOException { - final String ip = startAppiumServer(); - - if (service == null || !service.isRunning()) { - throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!"); - } + startAppiumServer(); XCUITestOptions options = new XCUITestOptions() .withBrowserName(MobileBrowserType.SAFARI) .setDeviceName(DEVICE_NAME) .setPlatformVersion(PLATFORM_VERSION) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); - driver = new IOSDriver(new URL("http://" + ip + ":" + PORT + "/wd/hub"), options); + driver = new IOSDriver(service.getUrl(), options); } } diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index ea8a7c706..7db741cdd 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -5,7 +5,6 @@ import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; import static io.appium.java_client.service.local.AppiumServiceBuilder.APPIUM_PATH; import static io.appium.java_client.service.local.flags.GeneralServerFlag.CALLBACK_ADDRESS; -import static io.appium.java_client.service.local.flags.GeneralServerFlag.PRE_LAUNCH; import static io.appium.java_client.service.local.flags.GeneralServerFlag.SESSION_OVERRIDE; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static java.lang.System.getProperty; @@ -141,7 +140,6 @@ public void checkAbilityToStartServiceUsingFlags() { service = new AppiumServiceBuilder() .withArgument(CALLBACK_ADDRESS, testIP) .withArgument(SESSION_OVERRIDE) - .withArgument(PRE_LAUNCH) .build(); service.start(); assertTrue(service.isRunning()); @@ -183,7 +181,6 @@ public void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { service = new AppiumServiceBuilder() .withArgument(CALLBACK_ADDRESS, testIP) .withArgument(SESSION_OVERRIDE) - .withArgument(PRE_LAUNCH) .withCapabilities(options).build(); service.start(); assertTrue(service.isRunning()); @@ -247,7 +244,7 @@ public void checkAbilityToStartServiceWithLogFile() throws Exception { @Test public void checkAbilityToStartServiceWithPortUsingFlag() { String port = "8996"; - String expectedUrl = String.format("http://0.0.0.0:%s/wd/hub", port); + String expectedUrl = String.format("http://0.0.0.0:%s/", port); service = new AppiumServiceBuilder() .withArgument(() -> "--port", port) @@ -260,7 +257,7 @@ public void checkAbilityToStartServiceWithPortUsingFlag() { @Test public void checkAbilityToStartServiceWithPortUsingShortFlag() { String port = "8996"; - String expectedUrl = String.format("http://0.0.0.0:%s/wd/hub", port); + String expectedUrl = String.format("http://0.0.0.0:%s/", port); service = new AppiumServiceBuilder() .withArgument(() -> "-p", port) @@ -272,7 +269,7 @@ public void checkAbilityToStartServiceWithPortUsingShortFlag() { @Test public void checkAbilityToStartServiceWithIpUsingFlag() { - String expectedUrl = String.format("http://%s:4723/wd/hub", testIP); + String expectedUrl = String.format("http://%s:4723/", testIP); service = new AppiumServiceBuilder() .withArgument(() -> "--address", testIP) @@ -284,7 +281,7 @@ public void checkAbilityToStartServiceWithIpUsingFlag() { @Test public void checkAbilityToStartServiceWithIpUsingShortFlag() { - String expectedUrl = String.format("http://%s:4723/wd/hub", testIP); + String expectedUrl = String.format("http://%s:4723/", testIP); service = new AppiumServiceBuilder() .withArgument(() -> "-a", testIP) From f64e34f7aca4a5a9fce7cc8f85f544da51524a63 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 3 Dec 2021 17:59:00 +0300 Subject: [PATCH 048/501] build: relax constraints of Selenium dependencies versions (#1606) https://docs.gradle.org/current/userguide/dependency_downgrade_and_exclude.html: "conflicting strict dependencies will trigger a build failure that you have to resolve". An attempt to use `java-client:8.0.0-beta` in conjunction with Selenium 4.1.0 leads to build failures, like: ``` > Could not resolve org.seleniumhq.selenium:selenium-remote-driver:{strictly 4.0.0}. Required by: project :xxxxxxx > io.appium:java-client:8.0.0-beta ``` In a favor of flexibility the constraints of selenium dependencies versions are relaxed. --- build.gradle | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 181cddb86..a48484dbd 100644 --- a/build.gradle +++ b/build.gradle @@ -33,17 +33,20 @@ dependencies { api ('org.seleniumhq.selenium:selenium-api') { version { - strictly "${seleniumVersion}" + strictly '[4.0, 5.0)' + prefer "${seleniumVersion}" } } api ('org.seleniumhq.selenium:selenium-remote-driver') { version { - strictly "${seleniumVersion}" + strictly '[4.0, 5.0)' + prefer "${seleniumVersion}" } } implementation ('org.seleniumhq.selenium:selenium-support') { version { - strictly "${seleniumVersion}" + strictly '[4.0, 5.0)' + prefer "${seleniumVersion}" } } implementation 'com.google.code.gson:gson:2.8.9' @@ -63,7 +66,8 @@ dependencies { } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { version { - strictly "${seleniumVersion}" + strictly '[4.0, 5.0)' + prefer "${seleniumVersion}" } } } From 158615250499b5a3c251a38928c7d4771d3f281e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Dec 2021 14:35:29 +0300 Subject: [PATCH 049/501] build(deps): bump actions/setup-java from 2.3.1 to 2.4.0 (#1607) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2.3.1 to 2.4.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v2.3.1...v2.4.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 494ab23bd..0adb4d267 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v2.3.1 + uses: actions/setup-java@v2.4.0 with: distribution: 'zulu' java-version: ${{ matrix.java }} From a43064d49e8084f8f4d3231dd077dad4c72c875f Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sun, 19 Dec 2021 00:28:30 +0300 Subject: [PATCH 050/501] fix: bump Selenium from 4.0.0 to 4.1.1 (#1613) Selenium 4.1.1 contains bug fix: HttpClient follows redirects by default. This fix is crucial for some cloud testing providers. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d2d4a6a43..0e37bcb22 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile ossrhUsername=your-jira-id ossrhPassword=your-jira-password -selenium.version=4.0.0 +selenium.version=4.1.1 From 50fd3e3f0f76fbf0fa25bbe413468c5000966cec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 23:13:56 +0300 Subject: [PATCH 051/501] build(deps): bump spring-context from 5.3.13 to 5.3.14 (#1614) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.13 to 5.3.14. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.13...v5.3.14) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a48484dbd..37bbdd79f 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.13' + implementation 'org.springframework:spring-context:5.3.14' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.32' From 6706efb2f51ba20dac71aa1cc15d353e4546620a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 23:40:14 +0300 Subject: [PATCH 052/501] build(deps): bump org.owasp.dependencycheck from 6.5.0.1 to 6.5.1 (#1616) Bumps org.owasp.dependencycheck from 6.5.0.1 to 6.5.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 37bbdd79f..8820660f7 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.5.0.1' + id 'org.owasp.dependencycheck' version '6.5.1' id 'com.github.johnrengelman.shadow' version '7.1.0' } From 659f4f8f6768ee5285d4b98fe9400fe1fd8bff4c Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Wed, 22 Dec 2021 19:41:41 +0530 Subject: [PATCH 053/501] Release 8.0.0-beta2 and update release notes --- README.md | 16 ++++++++++++++++ build.gradle | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d83f541ba..e25159ad1 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,22 @@ dependencies { ``` ## Changelog +*8.0.0-beta2* +- **[DOCUMENTATION]** + - Add a link to options builder examples to the migration guide. [#1595](https://github.com/appium/java-client/pull/1595) +- **[BUG FIX]** + - Filter out proxyClassLookup method from Proxy class (for Java 16+) in AppiumByBuilder. [#1575](https://github.com/appium/java-client/pull/1575) +- **[REFRACTOR]** + - Add more nice functional stuff into page factory helpers. [#1584](https://github.com/appium/java-client/pull/1584) + - Switch e2e tests to use Appium2. [#1603](https://github.com/appium/java-client/pull/1603) + - relax constraints of Selenium dependencies versions. [#1606](https://github.com/appium/java-client/pull/1606) +- **[DEPENDENCY UPDATES]** + - Upgrade to Selenium 4.1.1. [#1613](https://github.com/appium/java-client/pull/1613) + - `org.owasp.dependencycheck` was updated to 6.5.1. + - `org.springframework:spring-context` was updated to 5.3.14. + - `actions/setup-java` was updated to 2.4.0. + - `gradle` was updated to 7.3. + *8.0.0-beta* - **[ENHANCEMENTS]** - Start adding UiAutomator2 options. [#1543](https://github.com/appium/java-client/pull/1543) diff --git a/build.gradle b/build.gradle index 8820660f7..56ab0d8a9 100644 --- a/build.gradle +++ b/build.gradle @@ -113,7 +113,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '8.0.0-beta' + version = '8.0.0-beta2' from components.java pom { name = 'java-client' From 1c28134cff79566eaae594d14fb9fc1a1729fd6b Mon Sep 17 00:00:00 2001 From: Jason <819635822@qq.com> Date: Tue, 28 Dec 2021 00:57:02 +0800 Subject: [PATCH 054/501] fix: chinese garbled characters #1617 (#1618) --- .../service/local/AppiumDriverLocalService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index ac86cf91b..cc1c77ad5 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory; import org.slf4j.event.Level; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -410,16 +411,15 @@ static Slf4jLogMessageContext parseSlf4jContextFromLogMessage(String logMessage) public void addLogMessageConsumer(Consumer consumer) { checkNotNull(consumer, "consumer parameter is NULL!"); addOutPutStream(new OutputStream() { - StringBuilder lineBuilder = new StringBuilder(); + private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @Override public void write(int chr) { try { - lineBuilder.append((char) chr); - Matcher matcher = LOG_MESSAGE_PATTERN.matcher(lineBuilder.toString()); - if (matcher.matches()) { - consumer.accept(matcher.group(1)); - lineBuilder = new StringBuilder(); + outputStream.write(chr); + if (chr == '\n') { + consumer.accept(outputStream.toString()); + outputStream.reset(); } } catch (Exception e) { // log error and continue From e538394a04acb997e0a837a0527ca63053de9000 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Dec 2021 11:03:15 +0300 Subject: [PATCH 055/501] build(deps): bump actions/setup-java from 2.4.0 to 2.5.0 (#1620) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v2.4.0...v2.5.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 0adb4d267..5ebd84014 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v2.4.0 + uses: actions/setup-java@v2.5.0 with: distribution: 'zulu' java-version: ${{ matrix.java }} From 22c91e28815ef55d8d19a787d37ea17706cbe55c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 30 Dec 2021 20:51:47 +0100 Subject: [PATCH 056/501] fix: Avoid fallback to css for id and name locator annotations (#1622) --- .../java/io/appium/java_client/AppiumBy.java | 46 +++++++++++++------ .../pagefactory/bys/builder/Strategies.java | 8 ++-- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 98730e1ad..10a8c5b76 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -26,7 +26,6 @@ import java.io.Serializable; import java.util.List; -@SuppressWarnings("serial") public abstract class AppiumBy extends By implements Remotable { @Getter private final Parameters remoteParameters; @@ -38,7 +37,6 @@ protected AppiumBy(String selector, String locatorString, String locatorName) { this.locatorName = locatorName; } - @SuppressWarnings("unchecked") @Override public List findElements(SearchContext context) { return context.findElements(this); } @@ -48,7 +46,7 @@ protected AppiumBy(String selector, String locatorString, String locatorName) { } @Override public String toString() { - return String.format("AppiumBy.%s: %s", locatorName, remoteParameters.value()); + return String.format("%s.%s: %s", AppiumBy.class.getSimpleName(), locatorName, remoteParameters.value()); } /** @@ -115,6 +113,26 @@ public static By className(final String selector) { return new ByClassName(selector); } + /** + * For IOS the element name. + * For Android it is the resource identifier. + * @param selector element id + * @return an instance of {@link ById} + */ + public static By id(final String selector) { + return new ById(selector); + } + + /** + * For IOS the element name. + * For Android it is the resource identifier. + * @param selector element id + * @return an instance of {@link ByName} + */ + public static By name(final String selector) { + return new ByName(selector); + } + /** * This type of locator requires the use of the 'customFindModules' capability and a * separately-installed element finding plugin. @@ -165,70 +183,72 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) { } public static class ByAccessibilityId extends AppiumBy implements Serializable { - public ByAccessibilityId(String accessibilityId) { super("accessibility id", accessibilityId, "accessibilityId"); } } public static class ByAndroidDataMatcher extends AppiumBy implements Serializable { - protected ByAndroidDataMatcher(String locatorString) { super("-android datamatcher", locatorString, "androidDataMatcher"); } } public static class ByAndroidUIAutomator extends AppiumBy implements Serializable { - public ByAndroidUIAutomator(String uiautomatorText) { super("-android uiautomator", uiautomatorText, "androidUIAutomator"); } } public static class ByAndroidViewMatcher extends AppiumBy implements Serializable { - protected ByAndroidViewMatcher(String locatorString) { super("-android viewmatcher", locatorString, "androidViewMatcher"); } } public static class ByAndroidViewTag extends AppiumBy implements Serializable { - public ByAndroidViewTag(String tag) { super("-android viewtag", tag, "androidViewTag"); } } - public static class ByClassName extends AppiumBy implements Serializable { + public static class ById extends AppiumBy implements Serializable { + protected ById(String selector) { + super("id", selector, "id"); + } + } + + public static class ByName extends AppiumBy implements Serializable { + protected ByName(String selector) { + super("name", selector, "name"); + } + } + public static class ByClassName extends AppiumBy implements Serializable { protected ByClassName(String selector) { super("class name", selector, "className"); } } public static class ByCustom extends AppiumBy implements Serializable { - protected ByCustom(String selector) { super("-custom", selector, "custom"); } } public static class ByImage extends AppiumBy implements Serializable { - protected ByImage(String b64Template) { super("-image", b64Template, "image"); } } public static class ByIosClassChain extends AppiumBy implements Serializable { - protected ByIosClassChain(String locatorString) { super("-ios class chain", locatorString, "iOSClassChain"); } } public static class ByIosNsPredicate extends AppiumBy implements Serializable { - protected ByIosNsPredicate(String locatorString) { super("-ios predicate string", locatorString, "iOSNsPredicate"); } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index d175f37e3..db06bdbc1 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -53,19 +53,17 @@ enum Strategies { }, BYID("id") { @Override By getBy(Annotation annotation) { - return By.id(getValue(annotation, this)); + return AppiumBy.id(getValue(annotation, this)); } }, BYTAG("tagName") { @Override By getBy(Annotation annotation) { - return By - .tagName(getValue(annotation, this)); + return By.tagName(getValue(annotation, this)); } }, BYNAME("name") { @Override By getBy(Annotation annotation) { - return By - .name(getValue(annotation, this)); + return AppiumBy.name(getValue(annotation, this)); } }, BYXPATH("xpath") { From 3a02dd72a04cae3d0ff86f93eefd6aad3db6e50f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 14:35:15 +0300 Subject: [PATCH 057/501] build(deps): bump com.github.johnrengelman.shadow from 7.1.0 to 7.1.2 (#1624) Bumps com.github.johnrengelman.shadow from 7.1.0 to 7.1.2. --- updated-dependencies: - dependency-name: com.github.johnrengelman.shadow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 56ab0d8a9..9760260a5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id 'checkstyle' id 'signing' id 'org.owasp.dependencycheck' version '6.5.1' - id 'com.github.johnrengelman.shadow' version '7.1.0' + id 'com.github.johnrengelman.shadow' version '7.1.2' } repositories { From 9fa0a13e2f1684bd996963b1f6bd1a962c879d21 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 9 Jan 2022 17:09:27 +0100 Subject: [PATCH 058/501] fix: Do not convert argument names to lowercase (#1627) --- .../appium/java_client/service/local/AppiumServiceBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index cf1e5ee89..0196579c2 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -203,7 +203,7 @@ public AppiumServiceBuilder withArgument(ServerArgument argument) { * @return the self-reference. */ public AppiumServiceBuilder withArgument(ServerArgument argument, String value) { - String argName = argument.getArgument().trim().toLowerCase(); + String argName = argument.getArgument(); switch (argName) { case "--port": case "-p": From 57fa73aa99352de8d31104b288956c007cb74a30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jan 2022 10:28:11 +0300 Subject: [PATCH 059/501] build(deps): bump org.owasp.dependencycheck from 6.5.1 to 6.5.2.1 (#1629) Bumps org.owasp.dependencycheck from 6.5.1 to 6.5.2.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9760260a5..cf0c83272 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.5.1' + id 'org.owasp.dependencycheck' version '6.5.2.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 9bd455be5c07e20a3da5cbd0ff195a4eee5ee948 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jan 2022 14:22:38 +0300 Subject: [PATCH 060/501] build(deps): bump slf4j-api from 1.7.32 to 1.7.33 (#1633) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 1.7.32 to 1.7.33. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.32...v_1.7.33) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cf0c83272..f93fbb1cd 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.14' implementation 'org.aspectj:aspectjweaver:1.9.7' - implementation 'org.slf4j:slf4j-api:1.7.32' + implementation 'org.slf4j:slf4j-api:1.7.33' testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' From 68d05ee79dd32c986f34856f83875465c58d2a3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jan 2022 14:35:17 +0300 Subject: [PATCH 061/501] build(deps): bump org.owasp.dependencycheck from 6.5.2.1 to 6.5.3 (#1634) Bumps org.owasp.dependencycheck from 6.5.2.1 to 6.5.3. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f93fbb1cd..e48a3116a 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.5.2.1' + id 'org.owasp.dependencycheck' version '6.5.3' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 95417f2c3952c82a48318570c0af3df39c7a3570 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jan 2022 06:55:36 +0530 Subject: [PATCH 062/501] build(deps): bump spring-context from 5.3.14 to 5.3.15 (#1632) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.14 to 5.3.15. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.14...v5.3.15) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e48a3116a..a54a98fc8 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.14' + implementation 'org.springframework:spring-context:5.3.15' implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.slf4j:slf4j-api:1.7.33' From 49880957dfea83ad01a5d5075e1845c1032b540a Mon Sep 17 00:00:00 2001 From: Connor King Date: Tue, 25 Jan 2022 16:20:53 -0500 Subject: [PATCH 063/501] docs: Set the minimum java version (#1631) --- docs/Installing-the-project.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/Installing-the-project.md b/docs/Installing-the-project.md index a354af7f1..8417f9f79 100644 --- a/docs/Installing-the-project.md +++ b/docs/Installing-the-project.md @@ -17,6 +17,14 @@ Add the following to pom.xml: ``` +If you haven't already, change the Java version: +``` + + 1.8 + 1.8 + +``` + If it is necessary to change the version of Selenium then you can configure pom.xml like following: ``` From b4460f08ea4486730763faf7945f4517f7ef6ee0 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 9 Feb 2022 12:23:34 +0100 Subject: [PATCH 064/501] fix: Make interfaces public to fix decorator creation (#1644) --- .../java/io/appium/java_client/android/HasAndroidSettings.java | 2 +- src/main/java/io/appium/java_client/ios/HasIOSSettings.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/HasAndroidSettings.java b/src/main/java/io/appium/java_client/android/HasAndroidSettings.java index 0c0e44f34..73900e050 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidSettings.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidSettings.java @@ -21,7 +21,7 @@ import java.time.Duration; -interface HasAndroidSettings extends HasSettings { +public interface HasAndroidSettings extends HasSettings { /** * Set the `ignoreUnimportantViews` setting. *Android-only method*. * Sets whether Android devices should use `setCompressedLayoutHeirarchy()` diff --git a/src/main/java/io/appium/java_client/ios/HasIOSSettings.java b/src/main/java/io/appium/java_client/ios/HasIOSSettings.java index 83a994a43..0f27380b3 100644 --- a/src/main/java/io/appium/java_client/ios/HasIOSSettings.java +++ b/src/main/java/io/appium/java_client/ios/HasIOSSettings.java @@ -19,7 +19,7 @@ import io.appium.java_client.HasSettings; import io.appium.java_client.Setting; -interface HasIOSSettings extends HasSettings { +public interface HasIOSSettings extends HasSettings { /** * Set the `nativeWebTap` setting. *iOS-only method*. * Sets whether Safari/webviews should convert element taps into x/y taps. From 13377bfe30198420def32a1fce9738de31c5124a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 15:43:37 +0300 Subject: [PATCH 065/501] build(deps): bump gson from 2.8.9 to 2.9.0 (#1646) Bumps [gson](https://github.com/google/gson) from 2.8.9 to 2.9.0. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.9...gson-parent-2.9.0) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a54a98fc8..4ef1f34fc 100644 --- a/build.gradle +++ b/build.gradle @@ -49,7 +49,7 @@ dependencies { prefer "${seleniumVersion}" } } - implementation 'com.google.code.gson:gson:2.8.9' + implementation 'com.google.code.gson:gson:2.9.0' implementation 'commons-codec:commons-codec:1.15' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' From 2a0773c55e88a28e478044a75328fbc98db5699d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 16:39:51 +0300 Subject: [PATCH 066/501] build(deps): bump slf4j-api from 1.7.33 to 1.7.36 (#1647) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 1.7.33 to 1.7.36. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.33...v_1.7.36) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4ef1f34fc..558d76a9d 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.15' implementation 'org.aspectj:aspectjweaver:1.9.7' - implementation 'org.slf4j:slf4j-api:1.7.33' + implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' From 694e7fb40d70fa681fb0862c361f80582adf9b2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Feb 2022 09:48:30 +0300 Subject: [PATCH 067/501] build(deps): bump aspectjweaver from 1.9.7 to 1.9.8 (#1648) Bumps [aspectjweaver](https://github.com/eclipse/org.aspectj) from 1.9.7 to 1.9.8. - [Release notes](https://github.com/eclipse/org.aspectj/releases) - [Commits](https://github.com/eclipse/org.aspectj/commits) --- updated-dependencies: - dependency-name: org.aspectj:aspectjweaver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 558d76a9d..6a82cd2a0 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.15' - implementation 'org.aspectj:aspectjweaver:1.9.7' + implementation 'org.aspectj:aspectjweaver:1.9.8' implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'junit:junit:4.13.2' From 6ed1a487228e031e18dc3f82e29e0c26b7de10a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 15:29:25 +0300 Subject: [PATCH 068/501] build(deps): bump spring-context from 5.3.15 to 5.3.16 (#1650) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.15 to 5.3.16. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.15...v5.3.16) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6a82cd2a0..55b102622 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.15' + implementation 'org.springframework:spring-context:5.3.16' implementation 'org.aspectj:aspectjweaver:1.9.8' implementation 'org.slf4j:slf4j-api:1.7.36' From 2fe16a4566bcd4eba66067d8d5eb148f4f0d1e1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 16:35:26 +0300 Subject: [PATCH 069/501] build(deps): bump webdrivermanager from 5.0.3 to 5.1.0 (#1651) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.0.3 to 5.1.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.0.3...webdrivermanager-5.1.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 55b102622..2ae07eefd 100644 --- a/build.gradle +++ b/build.gradle @@ -61,7 +61,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.0.3') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.1.0') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From af15e29b18e7489c827bf249801fb38e43f1aad6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Feb 2022 14:39:11 +0300 Subject: [PATCH 070/501] build(deps): bump actions/setup-java from 2.5.0 to 3 (#1653) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2.5.0 to 3. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v2.5.0...v3) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5ebd84014..f428692fe 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v2.5.0 + uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: ${{ matrix.java }} From 3b88a69dfbc5066effbec7989ac438d856f7ab42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Mar 2022 15:51:31 +0300 Subject: [PATCH 071/501] build(deps): bump org.owasp.dependencycheck from 6.5.3 to 7.0.0 (#1654) Bumps org.owasp.dependencycheck from 6.5.3 to 7.0.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2ae07eefd..cef163fcf 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '6.5.3' + id 'org.owasp.dependencycheck' version '7.0.0' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 9bc5ccbcd0b04ed569f8a42cd463ea9a5a052891 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Mar 2022 16:39:24 +0300 Subject: [PATCH 072/501] build(deps): bump actions/checkout from 2 to 3 (#1655) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/gradle.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index ba5a2db79..ba0201318 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -13,5 +13,5 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index f428692fe..e5981b475 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -19,7 +19,7 @@ jobs: name: JDK ${{ matrix.java }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 with: From a8f111bb9c00488dd24690ee06c79a48784a4ba6 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 7 Mar 2022 19:44:31 +0530 Subject: [PATCH 073/501] Release 8.0.0 and update release notes --- README.md | 18 ++++++++++++++++++ build.gradle | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e25159ad1..a6f4038de 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,24 @@ dependencies { ``` ## Changelog +*8.0.0* +- **[DOCUMENTATION]** + - Set minimum Java version to 1.8.0. [#1631](https://github.com/appium/java-client/pull/1631) +- **[BUG FIX]** + - Make interfaces public to fix decorator creation. [#1644](https://github.com/appium/java-client/pull/1644) + - Do not convert argument names to lowercase. [#1627](https://github.com/appium/java-client/pull/1627) + - Avoid fallback to css for id and name locator annotations. [#1622](https://github.com/appium/java-client/pull/1622) + - Fix handling of chinese characters in `AppiumDriverLocalService`. [#1618](https://github.com/appium/java-client/pull/1618) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 7.0.0. + - `org.springframework:spring-context` was updated to 5.3.16. + - `actions/setup-java` was updated to 3. + - `actions/checkout` was updated to 3. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.1.0. + - `org.aspectj:aspectjweaver` was updated to 1.9.8. + - `org.slf4j:slf4j-api` was updated to 1.7.36. + - `com.github.johnrengelman.shadow` was updated to 7.1.2. + *8.0.0-beta2* - **[DOCUMENTATION]** - Add a link to options builder examples to the migration guide. [#1595](https://github.com/appium/java-client/pull/1595) diff --git a/build.gradle b/build.gradle index cef163fcf..b8ea9f256 100644 --- a/build.gradle +++ b/build.gradle @@ -113,7 +113,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '8.0.0-beta2' + version = '8.0.0' from components.java pom { name = 'java-client' From d3ede46a5600e066fec7a5a11c701f829696cdd3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 7 Mar 2022 16:26:23 +0100 Subject: [PATCH 074/501] docs: Add a note about the client code migration (#1656) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a6f4038de..4bed5b7e4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client) [![Javadocs](https://www.javadoc.io/badge/io.appium/java-client.svg)](https://www.javadoc.io/doc/io.appium/java-client) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f365c5e9458b42bf8a5b1d928d7e4f48)](https://www.codacy.com/app/appium/java-client) [![Build Status](https://travis-ci.org/appium/java-client.svg?branch=master)](https://travis-ci.org/appium/java-client) This is the Java language binding for writing Appium Tests, conforms to [Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) @@ -17,6 +16,12 @@ This is the Java language binding for writing Appium Tests, conforms to [Mobile [WIKI](https://github.com/appium/java-client/wiki) +## v8 Migration + +Since version 8 Appium Java Client had several major changes, which might require to +update your client code. Make sure to follow the [v7 to v8 Migration Guide](https://github.com/appium/java-client/blob/master/docs/v7-to-v8-migration-guide.md) +in order to streamline the migration process. + ## How to install latest java client Beta/Snapshots Java client project is available to use even before it is officially published to maven central. Refer [jitpack.io](https://jitpack.io/#appium/java-client) From f62b9d16d69375dadb1bdd2715fb8a2007d8b3f9 Mon Sep 17 00:00:00 2001 From: robinGupta11392 <36239951+robinGupta11392@users.noreply.github.com> Date: Sat, 19 Mar 2022 23:29:30 +0800 Subject: [PATCH 075/501] fix: #1660 - correction for ping method to get proper status URL in case of a basepath provided (#1661) --- .../service/local/AppiumServiceBuilder.java | 12 +++++ .../service/local/ServerBuilderTest.java | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 0196579c2..e0ce11520 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -16,6 +16,8 @@ package io.appium.java_client.service.local; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; import com.google.common.collect.ImmutableList; @@ -217,6 +219,9 @@ public AppiumServiceBuilder withArgument(ServerArgument argument, String value) case "-g": withLogFile(new File(value)); break; + case "--base-path": + serverArguments.put(argName, sanitizeBasePath(value)); + break; default: serverArguments.put(argName, value); break; @@ -224,6 +229,13 @@ public AppiumServiceBuilder withArgument(ServerArgument argument, String value) return this; } + private static String sanitizeBasePath(String basePath) { + basePath = checkNotNull(basePath).trim(); + checkArgument(!basePath.isEmpty(), + "Given base path is not valid - blank or empty values are not allowed for base path"); + return basePath.endsWith("/") ? basePath : basePath + "/"; + } + /** * Adds capabilities. * diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index 7db741cdd..3c3fed15e 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -4,6 +4,9 @@ import static io.appium.java_client.TestUtils.getLocalIp4Address; import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; import static io.appium.java_client.service.local.AppiumServiceBuilder.APPIUM_PATH; +import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP_ADDRESS; +import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; +import static io.appium.java_client.service.local.flags.GeneralServerFlag.BASEPATH; import static io.appium.java_client.service.local.flags.GeneralServerFlag.CALLBACK_ADDRESS; import static io.appium.java_client.service.local.flags.GeneralServerFlag.SESSION_OVERRIDE; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; @@ -18,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import com.google.common.collect.ImmutableMap; @@ -312,4 +316,45 @@ public void checkAbilityToStartServiceWithLogFileUsingShortFlag() { service.start(); assertTrue(testLogFile.exists()); } + + @Test + public void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() { + String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); + String basePath = "wd/hub"; + service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); + service.start(); + assertTrue(service.isRunning()); + assertEquals(baseUrl + basePath + "/", service.getUrl().toString()); + } + + @Test + public void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { + String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); + String basePath = "/wd/"; + service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); + service.start(); + assertTrue(service.isRunning()); + assertEquals(baseUrl + basePath.substring(1), service.getUrl().toString()); + } + + @Test + public void checkAbilityToValidateBasePathForEmptyBasePath() { + assertThrows(IllegalArgumentException.class, () -> { + new AppiumServiceBuilder().withArgument(BASEPATH, "").build(); + }); + } + + @Test + public void checkAbilityToValidateBasePathForBlankBasePath() { + assertThrows(IllegalArgumentException.class, () -> { + new AppiumServiceBuilder().withArgument(BASEPATH, " ").build(); + }); + } + + @Test + public void checkAbilityToValidateBasePathForNullBasePath() { + assertThrows(NullPointerException.class, () -> { + new AppiumServiceBuilder().withArgument(BASEPATH, null).build(); + }); + } } From 2ad786a24d742c7f0830eb4b72994cee5ba91106 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:18:59 +0300 Subject: [PATCH 076/501] build(deps): bump spring-context from 5.3.16 to 5.3.17 (#1663) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.16 to 5.3.17. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.16...v5.3.17) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b8ea9f256..670b8fec9 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.16' + implementation 'org.springframework:spring-context:5.3.17' implementation 'org.aspectj:aspectjweaver:1.9.8' implementation 'org.slf4j:slf4j-api:1.7.36' From 52f57e33681abc1af1062ac9c08319445d1435b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:32:17 +0300 Subject: [PATCH 077/501] build(deps): bump aspectjweaver from 1.9.8 to 1.9.9 (#1668) Bumps [aspectjweaver](https://github.com/eclipse/org.aspectj) from 1.9.8 to 1.9.9. - [Release notes](https://github.com/eclipse/org.aspectj/releases) - [Commits](https://github.com/eclipse/org.aspectj/commits) --- updated-dependencies: - dependency-name: org.aspectj:aspectjweaver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 670b8fec9..bdf1045fc 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.17' - implementation 'org.aspectj:aspectjweaver:1.9.8' + implementation 'org.aspectj:aspectjweaver:1.9.9' implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'junit:junit:4.13.2' From 976f944a3970e41d0c7f114de79f3e210158270f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:35:08 +0300 Subject: [PATCH 078/501] build(deps): bump org.owasp.dependencycheck from 7.0.0 to 7.0.1 (#1669) Bumps org.owasp.dependencycheck from 7.0.0 to 7.0.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bdf1045fc..41c2ec8a7 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.0.0' + id 'org.owasp.dependencycheck' version '7.0.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From a45209b6239ddb34da37ef036dde92051312fa09 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 28 Mar 2022 15:43:54 +0200 Subject: [PATCH 079/501] docs: Tune the arg value in the migration docs --- docs/v7-to-v8-migration-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/v7-to-v8-migration-guide.md b/docs/v7-to-v8-migration-guide.md index 72cdc08c6..a0ab9d256 100644 --- a/docs/v7-to-v8-migration-guide.md +++ b/docs/v7-to-v8-migration-guide.md @@ -105,6 +105,6 @@ became `http://0.0.0.0:4723/`). This has been done in order to align the actual behavior with Appium v2. If you still would like to use v8 of the Java client with Appium v1.2x, where the server URL contains the `/wd/hub` suffix by default, then consider providing `--base-path` setting explicitly while -building `AppiumServiceBuilder` instance (e.g. `.withArgument(GeneralServerFlag.BASEPATH, "/wd/hub")`). +building `AppiumServiceBuilder` instance (e.g. `.withArgument(GeneralServerFlag.BASEPATH, "/wd/hub/")`). Older versions of Appium server (v1.19 and older) won't work with `AppiumDriverLocalService`, because they don't allow provisioning of base path in form of a command line argument. From e09d121c49ff61b32ad6a042ff27e44ed72e40dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:48:45 +0300 Subject: [PATCH 080/501] build(deps): bump spring-context from 5.3.17 to 5.3.18 (#1672) Bumps [spring-context](https://github.com/spring-projects/spring-framework) from 5.3.17 to 5.3.18. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.17...v5.3.18) --- updated-dependencies: - dependency-name: org.springframework:spring-context dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 41c2ec8a7..af0cd21c8 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.17' + implementation 'org.springframework:spring-context:5.3.18' implementation 'org.aspectj:aspectjweaver:1.9.9' implementation 'org.slf4j:slf4j-api:1.7.36' From 4c88df663d2f4c702d668baf763eea772f1a84c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Apr 2022 12:58:38 +0300 Subject: [PATCH 081/501] build(deps): bump org.owasp.dependencycheck from 7.0.1 to 7.0.3 (#1673) Bumps org.owasp.dependencycheck from 7.0.1 to 7.0.3. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index af0cd21c8..33d15f4e8 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.0.1' + id 'org.owasp.dependencycheck' version '7.0.3' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 633023e77d728855a49dcffeedc295714a335028 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 14:09:02 +0300 Subject: [PATCH 082/501] build(deps): bump aspectjweaver from 1.9.9 to 1.9.9.1 (#1674) Bumps [aspectjweaver](https://github.com/eclipse/org.aspectj) from 1.9.9 to 1.9.9.1. - [Release notes](https://github.com/eclipse/org.aspectj/releases) - [Commits](https://github.com/eclipse/org.aspectj/commits) --- updated-dependencies: - dependency-name: org.aspectj:aspectjweaver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 33d15f4e8..7a11c584a 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' implementation 'org.springframework:spring-context:5.3.18' - implementation 'org.aspectj:aspectjweaver:1.9.9' + implementation 'org.aspectj:aspectjweaver:1.9.9.1' implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'junit:junit:4.13.2' From 11bb0ce2ee7becb1a22285d76f28f1ceba214131 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:13:27 +0300 Subject: [PATCH 083/501] build(deps): bump org.owasp.dependencycheck from 7.0.3 to 7.0.4.1 (#1675) Bumps org.owasp.dependencycheck from 7.0.3 to 7.0.4.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7a11c584a..0159d18c1 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.0.3' + id 'org.owasp.dependencycheck' version '7.0.4.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 2102e3d81c869790a33c4cd2251d2e3ffd9d3835 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 4 Apr 2022 16:31:38 +0200 Subject: [PATCH 084/501] refactor!: Remove obsolete event firing decorators (#1676) --- build.gradle | 2 - .../java_client/events/DefaultAspect.java | 563 ------------------ .../events/DefaultBeanConfiguration.java | 68 --- .../java_client/events/DefaultListener.java | 262 -------- .../events/EventFiringObjectFactory.java | 77 --- .../events/EventFiringWebDriverFactory.java | 71 --- .../events/ListenerInvocationHandler.java | 66 -- .../java_client/events/api/Listener.java | 25 - .../api/general/AlertEventListener.java | 78 --- .../general/AppiumWebDriverEventListener.java | 29 - .../api/general/ElementEventListener.java | 101 ---- .../api/general/JavaScriptEventListener.java | 45 -- .../api/general/ListensToException.java | 33 - .../api/general/NavigationEventListener.java | 93 --- .../api/general/SearchingEventListener.java | 57 -- .../api/general/WindowEventListener.java | 103 ---- .../api/mobile/ContextEventListener.java | 43 -- .../api/mobile/RotationEventListener.java | 44 -- 18 files changed, 1760 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/events/DefaultAspect.java delete mode 100644 src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java delete mode 100644 src/main/java/io/appium/java_client/events/DefaultListener.java delete mode 100644 src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java delete mode 100644 src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java delete mode 100644 src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java delete mode 100644 src/main/java/io/appium/java_client/events/api/Listener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/ElementEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/ListensToException.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java delete mode 100644 src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java diff --git a/build.gradle b/build.gradle index 0159d18c1..abf723873 100644 --- a/build.gradle +++ b/build.gradle @@ -55,8 +55,6 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.springframework:spring-context:5.3.18' - implementation 'org.aspectj:aspectjweaver:1.9.9.1' implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'junit:junit:4.13.2' diff --git a/src/main/java/io/appium/java_client/events/DefaultAspect.java b/src/main/java/io/appium/java_client/events/DefaultAspect.java deleted file mode 100644 index bb38d80e6..000000000 --- a/src/main/java/io/appium/java_client/events/DefaultAspect.java +++ /dev/null @@ -1,563 +0,0 @@ -/* - * 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.events; - -import static io.appium.java_client.events.DefaultBeanConfiguration.COMPONENT_BEAN; - -import com.google.common.collect.ImmutableList; - -import io.appium.java_client.events.api.Listener; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.After; -import org.aspectj.lang.annotation.AfterReturning; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.openqa.selenium.Alert; -import org.openqa.selenium.ContextAware; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.springframework.context.support.AbstractApplicationContext; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -@SuppressWarnings("unused") -@Aspect -class DefaultAspect { - - private static final List> listenable = ImmutableList.of(WebDriver.class, - WebElement.class, WebDriver.Navigation.class, WebDriver.TargetLocator.class, - ContextAware.class, Alert.class, WebDriver.Options.class, WebDriver.Window.class); - - private static final String EXECUTION_NAVIGATION_TO = "execution(* org.openqa.selenium.WebDriver." - + "Navigation.get(..)) || " - + "execution(* org.openqa.selenium.WebDriver.Navigation.to(..)) || " - + "execution(* org.openqa.selenium.WebDriver.get(..))"; - private static final String EXECUTION_NAVIGATION_BACK = "execution(* org.openqa.selenium.WebDriver." - + "Navigation.back(..))"; - private static final String EXECUTION_NAVIGATION_FORWARD = "execution(* org.openqa.selenium.WebDriver." - + "Navigation.forward(..))"; - private static final String EXECUTION_NAVIGATION_REFRESH = "execution(* org.openqa.selenium.WebDriver." - + "Navigation.refresh(..))"; - private static final String EXECUTION_SEARCH = "execution(* org.openqa.selenium.SearchContext." - + "findElement(..)) || " - + "execution(* org.openqa.selenium.SearchContext.findElements(..))"; - private static final String EXECUTION_CLICK = "execution(* org.openqa.selenium.WebElement.click(..))"; - private static final String EXECUTION_CHANGE_VALUE = "execution(* org.openqa.selenium.WebElement." - + "sendKeys(..)) || " - + "execution(* org.openqa.selenium.WebElement.clear(..)) || " - + "execution(* io.appium.java_client.android.AndroidElement.replaceValue(..)) || " - + "execution(* io.appium.java_client.MobileElement.setValue(..))"; - private static final String EXECUTION_SCRIPT = "execution(* org.openqa.selenium.JavascriptExecutor." - + "executeScript(..)) || " - + "execution(* org.openqa.selenium.JavascriptExecutor.executeAsyncScript(..))"; - private static final String EXECUTION_ALERT_ACCEPT = "execution(* org.openqa.selenium.Alert." - + "accept(..))"; - private static final String EXECUTION_ALERT_DISMISS = "execution(* org.openqa.selenium.Alert." - + "dismiss(..))"; - private static final String EXECUTION_ALERT_SEND_KEYS = "execution(* org.openqa.selenium.Alert." - + "sendKeys(..))"; - private static final String EXECUTION_WINDOW_SET_SIZE = "execution(* org.openqa.selenium." - + "WebDriver.Window.setSize(..))"; - private static final String EXECUTION_WINDOW_SET_POSITION = "execution(* org.openqa.selenium.WebDriver." - + "Window.setPosition(..))"; - private static final String EXECUTION_WINDOW_MAXIMIZE = "execution(* org.openqa.selenium.WebDriver." - + "Window.maximize(..))"; - private static final String EXECUTION_ROTATE = "execution(* org.openqa.selenium.Rotatable" - + ".rotate(..))"; - private static final String EXECUTION_CONTEXT = "execution(* org.openqa.selenium.ContextAware." - + "context(..))"; - private static final String EXECUTION_SWITCH_TO_WINDOW = "execution(* org.openqa.selenium.WebDriver.TargetLocator" - + ".window(..))"; - private static final String EXECUTION_TAKE_SCREENSHOT_AS = "execution(* org.openqa.selenium.TakesScreenshot" - + ".getScreenshotAs(..))"; - private static final String AROUND = "execution(* org.openqa.selenium.WebDriver.*(..)) || " - + "execution(* org.openqa.selenium.WebElement.*(..)) || " - + "execution(* org.openqa.selenium.WebDriver.Navigation.*(..)) || " - + "execution(* org.openqa.selenium.WebDriver.Options.*(..)) || " - + "execution(* org.openqa.selenium.WebDriver.TargetLocator.*(..)) || " - + "execution(* org.openqa.selenium.WebDriver.TargetLocator.*(..)) || " - + "execution(* org.openqa.selenium.JavascriptExecutor.*(..)) || " - + "execution(* org.openqa.selenium.ContextAware.*(..)) || " - + "execution(* org.openqa.selenium.WebDriver.Window.*(..)) || " - + "execution(* io.appium.java_client.android.AndroidElement.*(..)) || " - + "execution(* io.appium.java_client.ios.IOSElement.*(..)) || " - + "execution(* io.appium.java_client.android.AndroidDriver.*(..)) || " - + "execution(* io.appium.java_client.ios.IOSDriver.*(..)) || " - + "execution(* io.appium.java_client.AppiumDriver.*(..)) || " - + "execution(* io.appium.java_client.MobileElement.*(..)) || " - + "execution(* org.openqa.selenium.remote.RemoteWebDriver.*(..)) || " - + "execution(* org.openqa.selenium.remote.RemoteWebElement.*(..)) || " - + "execution(* org.openqa.selenium.Alert.*(..)) || " - + "execution(* org.openqa.selenium.TakesScreenshot.*(..))"; - - private final AbstractApplicationContext context; - private final WebDriver driver; - private final DefaultListener listener = new DefaultListener(); - - private static Throwable getRootCause(Throwable thrown) { - Class throwableClass = thrown.getClass(); - - if (!InvocationTargetException.class.equals(throwableClass) && !RuntimeException.class.equals(throwableClass)) { - return thrown; - } - if (thrown.getCause() != null) { - return getRootCause(thrown.getCause()); - } - return thrown; - } - - private static Class getClassForProxy(Class classOfObject) { - Class returnStatement = null; - for (Class c : listenable) { - if (!c.isAssignableFrom(classOfObject)) { - continue; - } - returnStatement = c; - } - return returnStatement; - } - - DefaultAspect(AbstractApplicationContext context, WebDriver driver) { - this.context = context; - this.driver = driver; - } - - private Object transformToListenable(Object toBeTransformed) { - if (toBeTransformed == null) { - return null; - } - - Object result = toBeTransformed; - if (getClassForProxy(toBeTransformed.getClass()) != null) { - result = context.getBean(COMPONENT_BEAN, toBeTransformed); - } - return result; - } - - private List returnProxyList(List originalList) { - try { - List proxyList = new ArrayList<>(); - for (Object o : originalList) { - if (getClassForProxy(o.getClass()) == null) { - proxyList.add(o); - } else { - proxyList.add(context.getBean(COMPONENT_BEAN, o)); - } - } - return proxyList; - } catch (Exception e) { - throw e; - } - - } - - public void add(Collection listeners) { - listener.add(listeners); - } - - @Before(EXECUTION_NAVIGATION_TO) - public void beforeNavigateTo(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeNavigateTo(String.valueOf(joinPoint.getArgs()[0]), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_NAVIGATION_TO) - public void afterNavigateTo(JoinPoint joinPoint) throws Throwable { - try { - listener.afterNavigateTo(String.valueOf(joinPoint.getArgs()[0]), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_NAVIGATION_BACK) - public void beforeNavigateBack(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeNavigateBack(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_NAVIGATION_BACK) - public void afterNavigateBack(JoinPoint joinPoint) throws Throwable { - try { - listener.afterNavigateBack(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_NAVIGATION_FORWARD) - public void beforeNavigateForward(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeNavigateForward(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_NAVIGATION_FORWARD) - public void afterNavigateForward(JoinPoint joinPoint) throws Throwable { - try { - listener.afterNavigateForward(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_NAVIGATION_REFRESH) - public void beforeNavigateRefresh(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeNavigateRefresh(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_NAVIGATION_REFRESH) - public void afterNavigateRefresh(JoinPoint joinPoint) throws Throwable { - try { - listener.afterNavigateRefresh(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @SuppressWarnings("unchecked") - private T castArgument(JoinPoint joinPoint, int argIndex) { - return (T) joinPoint.getArgs()[argIndex]; - } - - @SuppressWarnings("unchecked") - private T castTarget(JoinPoint joinPoint) { - return (T) joinPoint.getTarget(); - } - - @Before(EXECUTION_SEARCH) - public void beforeFindBy(JoinPoint joinPoint) throws Throwable { - try { - Object target = joinPoint.getTarget(); - if (!WebElement.class.isAssignableFrom(target.getClass())) { - listener.beforeFindBy(castArgument(joinPoint, 0), null, driver); - } else { - listener.beforeFindBy(castArgument(joinPoint, 0), - castTarget(joinPoint), driver); - } - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_SEARCH) - public void afterFindBy(JoinPoint joinPoint) throws Throwable { - try { - Object target = joinPoint.getTarget(); - if (!WebElement.class.isAssignableFrom(target.getClass())) { - listener.afterFindBy(castArgument(joinPoint, 0), null, driver); - } else { - listener.afterFindBy(castArgument(joinPoint, 0), - castTarget(joinPoint), driver); - } - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_CLICK) - public void beforeClickOn(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeClickOn(castTarget(joinPoint), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_CLICK) - public void afterClickOn(JoinPoint joinPoint) throws Throwable { - try { - listener.afterClickOn(castTarget(joinPoint), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_CHANGE_VALUE) - public void beforeChangeValueOf(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeChangeValueOf(castTarget(joinPoint), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_CHANGE_VALUE) - public void afterChangeValueOf(JoinPoint joinPoint) throws Throwable { - try { - listener.afterChangeValueOf(castTarget(joinPoint), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_SCRIPT) - public void beforeScript(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeScript(String.valueOf(joinPoint.getArgs()[0]), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_SCRIPT) - public void afterScript(JoinPoint joinPoint) throws Throwable { - try { - listener.afterScript(String.valueOf(joinPoint.getArgs()[0]), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_ALERT_ACCEPT) - public void beforeAlertAccept(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeAlertAccept(driver, castTarget(joinPoint)); - listener.beforeAlertAccept(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_ALERT_ACCEPT) - public void afterAlertAccept(JoinPoint joinPoint) throws Throwable { - try { - listener.afterAlertAccept(driver, castTarget(joinPoint)); - listener.afterAlertAccept(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_ALERT_DISMISS) - public void beforeAlertDismiss(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeAlertDismiss(driver, castTarget(joinPoint)); - listener.beforeAlertDismiss(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_ALERT_DISMISS) - public void afterAlertDismiss(JoinPoint joinPoint) throws Throwable { - try { - listener.afterAlertDismiss(driver, castTarget(joinPoint)); - listener.afterAlertDismiss(driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_ALERT_SEND_KEYS) - public void beforeAlertSendKeys(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeAlertSendKeys(driver, castTarget(joinPoint), - String.valueOf(joinPoint.getArgs()[0])); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_ALERT_SEND_KEYS) - public void afterAlertSendKeys(JoinPoint joinPoint) throws Throwable { - try { - listener.afterAlertSendKeys(driver, castTarget(joinPoint), - String.valueOf(joinPoint.getArgs()[0])); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_WINDOW_SET_SIZE) - public void beforeWindowIsResized(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeWindowChangeSize(driver, - castTarget(joinPoint), castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_WINDOW_SET_SIZE) - public void afterWindowIsResized(JoinPoint joinPoint) throws Throwable { - try { - listener.afterWindowChangeSize(driver, castTarget(joinPoint), - castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_WINDOW_SET_POSITION) - public void beforeWindowIsMoved(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeWindowIsMoved(driver, castTarget(joinPoint), - castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_WINDOW_SET_POSITION) - public void afterWindowIsMoved(JoinPoint joinPoint) throws Throwable { - try { - listener.afterWindowIsMoved(driver, castTarget(joinPoint), - castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_WINDOW_MAXIMIZE) - public void beforeMaximization(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeWindowIsMaximized(driver, castTarget(joinPoint)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_WINDOW_MAXIMIZE) - public void afterMaximization(JoinPoint joinPoint) throws Throwable { - try { - listener.afterWindowIsMaximized(driver, castTarget(joinPoint)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_SWITCH_TO_WINDOW) - public void beforeSwitchToWindow(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeSwitchToWindow(castArgument(joinPoint, 0), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @After(EXECUTION_SWITCH_TO_WINDOW) - public void afterSwitchToWindow(JoinPoint joinPoint) throws Throwable { - try { - listener.afterSwitchToWindow(castArgument(joinPoint, 0), driver); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_TAKE_SCREENSHOT_AS) - public void beforeTakeScreenShot(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeGetScreenshotAs(castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @AfterReturning(value = EXECUTION_TAKE_SCREENSHOT_AS, returning = "result") - public void afterTakeScreenShot(JoinPoint joinPoint, Object result) throws Throwable { - try { - listener.afterGetScreenshotAs(castArgument(joinPoint, 0), result); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_ROTATE) - public void beforeRotation(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeRotation(driver, castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - - } - - @After(EXECUTION_ROTATE) - public void afterRotation(JoinPoint joinPoint) throws Throwable { - try { - listener.afterRotation(driver, castArgument(joinPoint, 0)); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Before(EXECUTION_CONTEXT) - public void beforeSwitchingToContext(JoinPoint joinPoint) throws Throwable { - try { - listener.beforeSwitchingToContext(driver, String.valueOf(joinPoint.getArgs()[0])); - } catch (Throwable t) { - throw getRootCause(t); - } - - } - - @After(EXECUTION_CONTEXT) - public void afterSwitchingToContextn(JoinPoint joinPoint) throws Throwable { - try { - listener.afterSwitchingToContext(driver, String.valueOf(joinPoint.getArgs()[0])); - } catch (Throwable t) { - throw getRootCause(t); - } - } - - @Around(AROUND) - public Object doAround(ProceedingJoinPoint point) throws Throwable { - Throwable t = null; - Object result = null; - try { - result = point.proceed(); - } catch (Throwable e) { - t = e; - } - if (t != null) { - Throwable rootCause = getRootCause(t); - listener.onException(rootCause, driver); - throw rootCause; - } - - if (result == null) { // maybe it was "void" - return null; - } - if (List.class.isAssignableFrom(result.getClass())) { - return returnProxyList((List) (result)); - } - - return transformToListenable(result); - } -} diff --git a/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java b/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java deleted file mode 100644 index ac2dd1581..000000000 --- a/src/main/java/io/appium/java_client/events/DefaultBeanConfiguration.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.events; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.context.annotation.Scope; -import org.springframework.context.support.AbstractApplicationContext; - -import java.util.ArrayList; -import java.util.List; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -@Configuration -@EnableAspectJAutoProxy(proxyTargetClass = true) -class DefaultBeanConfiguration { - public static final String LISTENABLE_OBJECT = "object"; - public static final String COMPONENT_BEAN = "component"; - - protected final List listeners = new ArrayList<>(); - protected WebDriver driver; - protected AbstractApplicationContext context; - - @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - @Bean(name = LISTENABLE_OBJECT) - public T init(T t, WebDriver driver, List listeners, - AbstractApplicationContext context) { - this.driver = driver; - this.listeners.addAll(listeners); - this.context = context; - return t; - } - - @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - @Bean(name = COMPONENT_BEAN) - public T getComponent(T t) { - return t; - } - - @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - @Bean(name = "defaultAspect") - public DefaultAspect getAspect() { - DefaultAspect aspect = new DefaultAspect(context, driver); - aspect.add(listeners); - return aspect; - } -} diff --git a/src/main/java/io/appium/java_client/events/DefaultListener.java b/src/main/java/io/appium/java_client/events/DefaultListener.java deleted file mode 100644 index 87c2cf15d..000000000 --- a/src/main/java/io/appium/java_client/events/DefaultListener.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * 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.events; - -import io.appium.java_client.events.api.Listener; -import io.appium.java_client.events.api.general.AlertEventListener; -import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; -import io.appium.java_client.events.api.general.ElementEventListener; -import io.appium.java_client.events.api.general.JavaScriptEventListener; -import io.appium.java_client.events.api.general.ListensToException; -import io.appium.java_client.events.api.general.NavigationEventListener; -import io.appium.java_client.events.api.general.SearchingEventListener; -import io.appium.java_client.events.api.general.WindowEventListener; -import io.appium.java_client.events.api.mobile.ContextEventListener; -import io.appium.java_client.events.api.mobile.RotationEventListener; -import org.openqa.selenium.Alert; -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.OutputType; -import org.openqa.selenium.Point; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.events.WebDriverEventListener; - -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -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}, - new ListenerInvocationHandler(listeners)); - - @Override public void beforeNavigateTo(String url, WebDriver driver) { - ((NavigationEventListener) dispatcher).beforeNavigateTo(url, driver); - } - - @Override public void afterNavigateTo(String url, WebDriver driver) { - ((NavigationEventListener) dispatcher).afterNavigateTo(url, driver); - } - - @Override public void beforeNavigateBack(WebDriver driver) { - ((NavigationEventListener) dispatcher).beforeNavigateBack(driver); - } - - @Override public void afterNavigateBack(WebDriver driver) { - ((NavigationEventListener) dispatcher).afterNavigateBack(driver); - } - - @Override public void beforeNavigateForward(WebDriver driver) { - ((NavigationEventListener) dispatcher).beforeNavigateForward(driver); - } - - @Override public void afterNavigateForward(WebDriver driver) { - ((NavigationEventListener) dispatcher).afterNavigateForward(driver); - } - - @Override public void beforeNavigateRefresh(WebDriver driver) { - ((NavigationEventListener) dispatcher).beforeNavigateRefresh(driver); - } - - @Override public void afterNavigateRefresh(WebDriver driver) { - ((NavigationEventListener) dispatcher).afterNavigateRefresh(driver); - } - - @Override public void beforeFindBy(By by, WebElement element, WebDriver driver) { - ((SearchingEventListener) dispatcher).beforeFindBy(by, element, driver); - } - - @Override public void afterFindBy(By by, WebElement element, WebDriver driver) { - ((SearchingEventListener) dispatcher).afterFindBy(by, element, driver); - } - - @Override public void beforeClickOn(WebElement element, WebDriver driver) { - ((ElementEventListener) dispatcher).beforeClickOn(element, driver); - } - - @Override public void afterClickOn(WebElement element, WebDriver driver) { - ((ElementEventListener) dispatcher).afterClickOn(element, driver); - } - - @Override public void beforeChangeValueOf(WebElement element, WebDriver driver) { - ((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); - } - - @Override public void afterScript(String script, WebDriver driver) { - ((JavaScriptEventListener) dispatcher).afterScript(script, driver); - } - - @Override public void onException(Throwable throwable, WebDriver driver) { - ((ListensToException) dispatcher).onException(throwable, driver); - } - - @Override - public void beforeGetScreenshotAs(OutputType target) { - ((WebDriverEventListener) dispatcher).beforeGetScreenshotAs(target); - } - - @Override - public void afterGetScreenshotAs(OutputType target, X screenshot) { - ((WebDriverEventListener) dispatcher).afterGetScreenshotAs(target, screenshot); - } - - @Override - public void beforeGetText(WebElement element, WebDriver driver) { - ((ElementEventListener) dispatcher).beforeGetText(element, driver); - } - - @Override - public void afterGetText(WebElement element, WebDriver driver, String text) { - ((ElementEventListener) dispatcher).afterGetText(element, driver, text); - } - - public void add(Collection listeners) { - this.listeners.addAll(listeners); - } - - @Override public void beforeAlertAccept(WebDriver driver, Alert alert) { - ((AlertEventListener) dispatcher).beforeAlertAccept(driver, alert); - } - - @Override - public void beforeAlertAccept(WebDriver driver) { - ((WebDriverEventListener) dispatcher).beforeAlertAccept(driver); - } - - @Override public void afterAlertAccept(WebDriver driver, Alert alert) { - ((AlertEventListener) dispatcher).afterAlertAccept(driver, alert); - } - - @Override - public void afterAlertAccept(WebDriver driver) { - ((WebDriverEventListener) dispatcher).afterAlertAccept(driver); - } - - @Override public void afterAlertDismiss(WebDriver driver, Alert alert) { - ((AlertEventListener) dispatcher).afterAlertDismiss(driver, alert); - } - - @Override - public void afterAlertDismiss(WebDriver driver) { - ((WebDriverEventListener) dispatcher).afterAlertDismiss(driver); - } - - @Override public void beforeAlertDismiss(WebDriver driver, Alert alert) { - ((AlertEventListener) dispatcher).beforeAlertDismiss(driver, alert); - } - - @Override - public void beforeAlertDismiss(WebDriver driver) { - ((WebDriverEventListener) dispatcher).beforeAlertDismiss(driver); - } - - @Override public void beforeAlertSendKeys(WebDriver driver, Alert alert, String keys) { - ((AlertEventListener) dispatcher).beforeAlertSendKeys(driver, alert, keys); - } - - @Override public void afterAlertSendKeys(WebDriver driver, Alert alert, String keys) { - ((AlertEventListener) dispatcher).afterAlertSendKeys(driver, alert, keys); - } - - @Override public void beforeWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize) { - ((WindowEventListener) dispatcher).beforeWindowChangeSize(driver, window, targetSize); - } - - @Override public void afterWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize) { - ((WindowEventListener) dispatcher).afterWindowChangeSize(driver, window, targetSize); - } - - @Override - public void beforeWindowIsMoved(WebDriver driver, WebDriver.Window window, Point targetPoint) { - ((WindowEventListener) dispatcher).beforeWindowIsMoved(driver, window, targetPoint); - } - - @Override - public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point targetPoint) { - ((WindowEventListener) dispatcher).afterWindowIsMoved(driver, window, targetPoint); - } - - @Override public void beforeWindowIsMaximized(WebDriver driver, WebDriver.Window window) { - ((WindowEventListener) dispatcher).beforeWindowIsMaximized(driver, window); - } - - @Override public void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window) { - ((WindowEventListener) dispatcher).afterWindowIsMaximized(driver, window); - } - - @Override - public void beforeSwitchToWindow(String windowName, WebDriver driver) { - ((WebDriverEventListener) dispatcher).beforeSwitchToWindow(windowName, driver); - } - - @Override - public void afterSwitchToWindow(String windowName, WebDriver driver) { - ((WebDriverEventListener) dispatcher).afterSwitchToWindow(windowName, driver); - } - - @Override public void beforeSwitchingToContext(WebDriver driver, String context) { - ((ContextEventListener) dispatcher).beforeSwitchingToContext(driver, context); - } - - @Override public void afterSwitchingToContext(WebDriver driver, String context) { - ((ContextEventListener) dispatcher).afterSwitchingToContext(driver, context); - } - - @Override public void beforeRotation(WebDriver driver, ScreenOrientation orientation) { - ((RotationEventListener) dispatcher).beforeRotation(driver, orientation); - } - - @Override public void afterRotation(WebDriver driver, ScreenOrientation orientation) { - ((RotationEventListener) dispatcher).afterRotation(driver, orientation); - } -} diff --git a/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java b/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java deleted file mode 100644 index 867251ccd..000000000 --- a/src/main/java/io/appium/java_client/events/EventFiringObjectFactory.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.appium.java_client.events; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.support.AbstractApplicationContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.ServiceLoader; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public class EventFiringObjectFactory { - - /** - * This method makes an event firing object. - * - * @param t an original {@link Object} that is - * supposed to be listenable - * @param driver an instance of {@link org.openqa.selenium.WebDriver} - * @param listeners is a collection of {@link io.appium.java_client.events.api.Listener} that - * is supposed to be used for the event firing - * @param T - * @return an {@link Object} that fires events - */ - @SuppressWarnings("unchecked") - public static T getEventFiringObject(T t, WebDriver driver, Collection listeners) { - final List listenerList = new ArrayList<>(); - - for (Listener listener : ServiceLoader.load( - Listener.class)) { - listenerList.add(listener); - } - - listeners.stream().filter(listener -> !listenerList.contains(listener)).forEach(listenerList::add); - - AbstractApplicationContext context = new AnnotationConfigApplicationContext( - DefaultBeanConfiguration.class); - return (T) context.getBean( - DefaultBeanConfiguration.LISTENABLE_OBJECT, t, driver, listenerList, context); - } - - /** - * This method makes an event firing object. - * - * @param t an original {@link Object} that is - * supposed to be listenable - * @param driver an instance of {@link org.openqa.selenium.WebDriver} - * @param T - * @return an {@link Object} that fires events - */ - public static T getEventFiringObject(T t, WebDriver driver) { - return getEventFiringObject(t, driver, Collections.emptyList()); - } - - /** - * This method makes an event firing object. - * - * @param t an original {@link Object} that is - * supposed to be listenable - * @param driver an instance of {@link org.openqa.selenium.WebDriver} - * @param listeners is an array of {@link io.appium.java_client.events.api.Listener} that - * is supposed to be used for the event firing - * - * @param T - * @return an instance of {@link org.openqa.selenium.WebDriver} that fires events - */ - public static T getEventFiringObject(T t, WebDriver driver, Listener ... listeners) { - return getEventFiringObject(t, driver, Arrays.asList(listeners)); - } -} diff --git a/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java b/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java deleted file mode 100644 index f0d255772..000000000 --- a/src/main/java/io/appium/java_client/events/EventFiringWebDriverFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.events; - -import static io.appium.java_client.events.EventFiringObjectFactory.getEventFiringObject; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; - -import java.util.Collection; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public class EventFiringWebDriverFactory { - - /** - * This method makes an event firing instance of {@link org.openqa.selenium.WebDriver}. - * - * @param driver an original instance of {@link org.openqa.selenium.WebDriver} that is - * supposed to be listenable - * @param T - * @return an instance of {@link org.openqa.selenium.WebDriver} that fires events - */ - public static T getEventFiringWebDriver(T driver) { - return getEventFiringObject(driver, driver); - } - - /** - * This method makes an event firing instance of {@link org.openqa.selenium.WebDriver}. - * - * @param driver an original instance of {@link org.openqa.selenium.WebDriver} that is - * supposed to be listenable - * @param listeners is a set of {@link io.appium.java_client.events.api.Listener} that - * is supposed to be used for the event firing - * @param T - * @return an instance of {@link org.openqa.selenium.WebDriver} that fires events - */ - public static T getEventFiringWebDriver(T driver, Listener ... listeners) { - return getEventFiringObject(driver, driver, listeners); - } - - /** - * This method makes an event firing instance of {@link org.openqa.selenium.WebDriver}. - * - * @param driver an original instance of {@link org.openqa.selenium.WebDriver} that is - * supposed to be listenable - * @param listeners is a collection of {@link io.appium.java_client.events.api.Listener} that - * is supposed to be used for the event firing - * @param T - * @return an instance of {@link org.openqa.selenium.WebDriver} that fires events - */ - public static T getEventFiringWebDriver(T driver, Collection listeners) { - return getEventFiringObject(driver, driver, listeners); - } -} diff --git a/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java b/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java deleted file mode 100644 index 7fe31125d..000000000 --- a/src/main/java/io/appium/java_client/events/ListenerInvocationHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.events; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.support.events.WebDriverEventListener; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.List; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -class ListenerInvocationHandler implements InvocationHandler { - - private final List listeners; - - ListenerInvocationHandler(List listeners) { - this.listeners = listeners; - } - - private Method findElementInWebDriverEventListener(Method m) { - try { - return WebDriverEventListener.class.getMethod(m.getName(), m.getParameterTypes()); - } catch (NoSuchMethodException e) { - return null; - } - } - - @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - for (Listener l: listeners) { - boolean isInvoked = false; - if (method.getDeclaringClass().isAssignableFrom(l.getClass())) { - method.invoke(l, args); - isInvoked = true; - } - - if (isInvoked) { - continue; - } - - Method webDriverEventListenerMethod = findElementInWebDriverEventListener(method); - if (webDriverEventListenerMethod != null - && WebDriverEventListener.class.isAssignableFrom(l.getClass())) { - webDriverEventListenerMethod.invoke(l, args); - } - } - return null; - } -} diff --git a/src/main/java/io/appium/java_client/events/api/Listener.java b/src/main/java/io/appium/java_client/events/api/Listener.java deleted file mode 100644 index aeb7e7986..000000000 --- a/src/main/java/io/appium/java_client/events/api/Listener.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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.events.api; - -/** - * This interface just marks event listeners. - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface Listener { -} diff --git a/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java b/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java deleted file mode 100644 index a9895b758..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/AlertEventListener.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.Alert; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface AlertEventListener extends Listener { - - /** - * This action will be performed each time before {@link Alert#accept()}. - * - * @param driver WebDriver - * @param alert {@link Alert} which is being accepted - */ - void beforeAlertAccept(WebDriver driver, Alert alert); - - /** - * This action will be performed each time after {@link Alert#accept()}. - * - * @param driver WebDriver - * @param alert {@link Alert} which has been accepted - */ - void afterAlertAccept(WebDriver driver, Alert alert); - - /** - * This action will be performed each time before {@link Alert#dismiss()}. - * - * @param driver WebDriver - * @param alert {@link Alert} which which is being dismissed - */ - void afterAlertDismiss(WebDriver driver, Alert alert); - - /** - * This action will be performed each time after {@link Alert#dismiss()}. - * - * @param driver WebDriver - * @param alert {@link Alert} which has been dismissed - */ - void beforeAlertDismiss(WebDriver driver, Alert alert); - - /** - * This action will be performed each time before {@link Alert#sendKeys(String)}. - * - * @param driver WebDriver - * @param alert {@link Alert} which is receiving keys - * @param keys Keys which are being sent - */ - void beforeAlertSendKeys(WebDriver driver, Alert alert, String keys); - - /** - * This action will be performed each time after {@link Alert#sendKeys(String)}. - * - * @param driver WebDriver - * @param alert {@link Alert} which has received keys - * @param keys Keys which have been sent - */ - void afterAlertSendKeys(WebDriver driver, Alert alert, String keys); -} diff --git a/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java b/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java deleted file mode 100644 index d232c207e..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/AppiumWebDriverEventListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.support.events.WebDriverEventListener; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface AppiumWebDriverEventListener extends Listener, WebDriverEventListener, ListensToException, - SearchingEventListener, NavigationEventListener, - JavaScriptEventListener, ElementEventListener { -} 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 deleted file mode 100644 index 6b5d72935..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/ElementEventListener.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface ElementEventListener extends Listener { - /** - * Called before {@link WebElement#click WebElement.click()}. - * - * @param driver WebDriver - * @param element the WebElement being used for the action - */ - void beforeClickOn(WebElement element, WebDriver driver); - - /** - * Called after {@link WebElement#click WebElement.click()}. - * Not called, if an exception is thrown. - * - * @param driver WebDriver - * @param element the WebElement being used for the action - */ - void afterClickOn(WebElement element, WebDriver driver); - - /** - * Called before {@link WebElement#clear WebElement.clear()}, - * {@link WebElement#sendKeys WebElement.sendKeys(...)}. - * - * @param driver WebDriver - * @param element the WebElement being used for the action - */ - void beforeChangeValueOf(WebElement element, WebDriver driver); - - /** - * Called before {@link WebElement#clear WebElement.clear()}, - * {@link WebElement#sendKeys WebElement.sendKeys(...)}. - * - * @param driver WebDriver - * @param element the WebElement being used for the action - * @param keysToSend character sequence to send to the element - */ - void beforeChangeValueOf(WebElement element, WebDriver driver, CharSequence[] keysToSend); - - /** - * Called after {@link WebElement#clear WebElement.clear()}, - * {@link 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); - - /** - * Called after {@link WebElement#clear WebElement.clear()}, - * {@link WebElement#sendKeys WebElement.sendKeys(...)} . - * Not called, if an exception is thrown. - * - * @param driver WebDriver - * @param element the WebElement being used for the action - * @param keysToSend character sequence to send to the element - */ - void afterChangeValueOf(WebElement element, WebDriver driver, CharSequence[] keysToSend); - - /** - * Called before {@link WebElement#getText()} method is being called. - * - * @param element - {@link WebElement} against which call is being made - * @param driver - instance of {@link WebDriver} - */ - void beforeGetText(WebElement element, WebDriver driver); - - /** - * Called right after {@link WebElement#getText()} method is being called. - * - * @param element - {@link WebElement} against which call is being made - * @param driver - instance of {@link WebDriver} - * @param text - {@link String} object extracted from respective {@link WebElement} - */ - void afterGetText(WebElement element, WebDriver driver, String text); -} diff --git a/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java b/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java deleted file mode 100644 index 25556a961..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/JavaScriptEventListener.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface JavaScriptEventListener extends Listener { - /** - * Called before - * {@link org.openqa.selenium.JavascriptExecutor#executeScript(String, Object[]) }. - * - * @param driver WebDriver - * @param script the script to be executed - */ - void beforeScript(String script, WebDriver driver); - - /** - * Called after - * {@link org.openqa.selenium.remote.RemoteWebDriver#executeScript(String, Object[]) }. - * Not called if an exception is thrown - * - * @param driver WebDriver - * @param script the script that was executed - */ - void afterScript(String script, WebDriver driver); -} diff --git a/src/main/java/io/appium/java_client/events/api/general/ListensToException.java b/src/main/java/io/appium/java_client/events/api/general/ListensToException.java deleted file mode 100644 index a6f3b4b3d..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/ListensToException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface ListensToException extends Listener { - /** - * Called whenever an exception would be thrown. - * @param throwable the exception that will be thrown - * @param driver WebDriver - */ - void onException(Throwable throwable, WebDriver driver); -} diff --git a/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java b/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java deleted file mode 100644 index 9b2b33e39..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/NavigationEventListener.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface NavigationEventListener extends Listener { - - /** - * Called before {@link org.openqa.selenium.WebDriver#get get(String url)} - * respectively {@link org.openqa.selenium.WebDriver.Navigation#to - * navigate().to(String url)}. - * - * @param url URL - * @param driver WebDriver - */ - void beforeNavigateTo(String url, WebDriver driver); - - /** - * Called after {@link org.openqa.selenium.WebDriver#get get(String url)} - * respectively {@link org.openqa.selenium.WebDriver.Navigation#to - * navigate().to(String url)}. Not called, if an exception is thrown. - * - * @param url URL - * @param driver WebDriver - */ - void afterNavigateTo(String url, WebDriver driver); - - /** - * Called before {@link org.openqa.selenium.WebDriver.Navigation#back - * navigate().back()}. - * - * @param driver WebDriver - */ - void beforeNavigateBack(WebDriver driver); - - /** - * Called after {@link org.openqa.selenium.WebDriver.Navigation - * navigate().back()}. Not called, if an exception is thrown. - * - * @param driver WebDriver - */ - void afterNavigateBack(WebDriver driver); - - /** - * Called before {@link org.openqa.selenium.WebDriver.Navigation#forward - * navigate().forward()}. - * - * @param driver WebDriver - */ - void beforeNavigateForward(WebDriver driver); - - /** - * Called after {@link org.openqa.selenium.WebDriver.Navigation#forward - * navigate().forward()}. Not called, if an exception is thrown. - * - * @param driver WebDriver - */ - void afterNavigateForward(WebDriver driver); - - /** - * Called before {@link org.openqa.selenium.WebDriver.Navigation#refresh navigate().refresh()}. - * - * @param driver WebDriver - */ - void beforeNavigateRefresh(WebDriver driver); - - /** - * Called after {@link org.openqa.selenium.WebDriver.Navigation#refresh navigate().refresh()}. - * - * @param driver WebDriver - */ - void afterNavigateRefresh(WebDriver driver); -} diff --git a/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java b/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java deleted file mode 100644 index 03be74a3e..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/SearchingEventListener.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface SearchingEventListener extends Listener { - - /** - * Called before {@link org.openqa.selenium.WebDriver#findElement WebDriver.findElement(...)}, - * or - * {@link org.openqa.selenium.WebDriver#findElements WebDriver.findElements(...)}, or - * {@link org.openqa.selenium.WebElement#findElement WebElement.findElement(...)}, or - * {@link org.openqa.selenium.WebElement#findElement WebElement.findElements(...)}. - * - * @param element will be null, if a find method of WebDriver - * is called. - * @param by locator being used - * @param driver WebDriver - */ - void beforeFindBy(By by, WebElement element, WebDriver driver); - - /** - * Called after {@link org.openqa.selenium.WebDriver#findElement WebDriver.findElement(...)}, - * or - * {@link org.openqa.selenium.WebDriver#findElements WebDriver.findElements(...)}, or - * {@link org.openqa.selenium.WebElement#findElement WebElement.findElement(...)}, or - * {@link org.openqa.selenium.WebElement#findElement WebElement.findElements(...)}. - * - * @param element will be null, if a find method of WebDriver - * is called. - * @param by locator being used - * @param driver WebDriver - */ - void afterFindBy(By by, WebElement element, WebDriver driver); -} diff --git a/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java b/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java deleted file mode 100644 index 5a50294ec..000000000 --- a/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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.events.api.general; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface WindowEventListener extends Listener { - /** - * This action will be performed each time before {@link WebDriver.Window#setSize(Dimension)}. - * - * @param driver WebDriver - * @param window is the window whose size is going to be changed - * @param targetSize is the new size - */ - void beforeWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize); - - /** - * This action will be performed each time after {@link WebDriver.Window#setSize(Dimension)}. - * - * @param driver WebDriver - * @param window is the window whose size has been changed - * @param targetSize is the new size - */ - void afterWindowChangeSize(WebDriver driver, WebDriver.Window window, - Dimension targetSize); - - /** - * This action will be performed each time before {@link WebDriver.Window#setPosition(Point)}. - * - * @param driver WebDriver - * @param window is the window whose position is going to be changed - * @param targetPoint is the new window coordinates - */ - void beforeWindowIsMoved(WebDriver driver, WebDriver.Window window, - Point targetPoint); - - /** - * This action will be performed each time after {@link WebDriver.Window#setPosition(Point)}. - * - * @param driver WebDriver - * @param window is the window whose position has been changed - * @param targetPoint is the new window coordinates - */ - void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, - Point targetPoint); - - - /** - * This action will be performed each time before {@link WebDriver.Window#maximize()}. - * - * @param driver WebDriver - * @param window is the window which is going to be maximized - */ - void beforeWindowIsMaximized(WebDriver driver, WebDriver.Window window); - - /** - * This action will be performed each time after {@link WebDriver.Window#maximize()}. - * - * @param driver WebDriver - * @param window is the window which has been maximized - */ - void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window); - - /** - * This action will be performed each time before - * {@link org.openqa.selenium.WebDriver.TargetLocator#window(java.lang.String)}. - * - * @param windowName the name of the window to switch - * @param driver WebDriver - */ - void beforeSwitchToWindow(String windowName, WebDriver driver); - - /** - * This action will be performed each time after - * {@link org.openqa.selenium.WebDriver.TargetLocator#window(java.lang.String)}. - * - * @param windowName the name of the window to switch - * @param driver WebDriver - */ - void afterSwitchToWindow(String windowName, WebDriver driver); -} diff --git a/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java b/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java deleted file mode 100644 index 3372e1b2e..000000000 --- a/src/main/java/io/appium/java_client/events/api/mobile/ContextEventListener.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.events.api.mobile; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface ContextEventListener extends Listener { - - /** - * Called before {@link org.openqa.selenium.ContextAware#context(String)}. - * - * @param driver Webdriver - * @param context The context that is needed to switch to. - */ - void beforeSwitchingToContext(WebDriver driver, String context); - - /** - * Called after {@link org.openqa.selenium.ContextAware#context(String)}. - * - * @param driver Webdriver - * @param context The context that is needed to switch to. - */ - void afterSwitchingToContext(WebDriver driver, String context); -} diff --git a/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java b/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java deleted file mode 100644 index b57b8542e..000000000 --- a/src/main/java/io/appium/java_client/events/api/mobile/RotationEventListener.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.events.api.mobile; - -import io.appium.java_client.events.api.Listener; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.WebDriver; - -/** - * Deprecated. Use EventFiringDecorator and WebDriverListener instead. - */ -@Deprecated -public interface RotationEventListener extends Listener { - - /** - * Called before {@link org.openqa.selenium.Rotatable#rotate(ScreenOrientation)}. - * - * @param driver WebDriver - * @param orientation the desired screen orientation - */ - void beforeRotation(WebDriver driver, ScreenOrientation orientation); - - /** - * Called after {@link org.openqa.selenium.Rotatable#rotate(ScreenOrientation)}. - * - * @param driver WebDriver - * @param orientation the desired screen orientation - */ - void afterRotation(WebDriver driver, ScreenOrientation orientation); -} From 0c13b5293324d0084d50f2060948ee4df3131cc4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 4 Apr 2022 20:01:40 +0200 Subject: [PATCH 085/501] refactor!: Remove deprecated option classes (#1679) --- .../java_client/android/AndroidOptions.java | 41 ---------- .../io/appium/java_client/ios/IOSOptions.java | 41 ---------- .../android/AndroidOptionsTest.java | 78 ------------------- .../java_client/ios/IOSOptionsTest.java | 78 ------------------- 4 files changed, 238 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/android/AndroidOptions.java delete mode 100644 src/main/java/io/appium/java_client/ios/IOSOptions.java delete mode 100644 src/test/java/io/appium/java_client/android/AndroidOptionsTest.java delete mode 100644 src/test/java/io/appium/java_client/ios/IOSOptionsTest.java diff --git a/src/main/java/io/appium/java_client/android/AndroidOptions.java b/src/main/java/io/appium/java_client/android/AndroidOptions.java deleted file mode 100644 index 3841ab62c..000000000 --- a/src/main/java/io/appium/java_client/android/AndroidOptions.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 io.appium.java_client.remote.MobileOptions; -import io.appium.java_client.remote.MobilePlatform; -import org.openqa.selenium.Capabilities; - -/** - * Use the specific options class for your driver, - * for example UiAutomator2Options. - */ -@Deprecated -public class AndroidOptions extends MobileOptions { - public AndroidOptions() { - setAndroidPlatformName(); - } - - public AndroidOptions(Capabilities source) { - super(source); - setAndroidPlatformName(); - } - - private void setAndroidPlatformName() { - setPlatformName(MobilePlatform.ANDROID); - } -} diff --git a/src/main/java/io/appium/java_client/ios/IOSOptions.java b/src/main/java/io/appium/java_client/ios/IOSOptions.java deleted file mode 100644 index 9cb847d1e..000000000 --- a/src/main/java/io/appium/java_client/ios/IOSOptions.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 io.appium.java_client.remote.MobileOptions; -import io.appium.java_client.remote.MobilePlatform; -import org.openqa.selenium.Capabilities; - -/** - * Use the specific options class for your driver, - * for example XCUITestOptions. - */ -@Deprecated -public class IOSOptions extends MobileOptions { - public IOSOptions() { - setIOSPlatformName(); - } - - public IOSOptions(Capabilities source) { - super(source); - setIOSPlatformName(); - } - - private void setIOSPlatformName() { - setPlatformName(MobilePlatform.IOS); - } -} diff --git a/src/test/java/io/appium/java_client/android/AndroidOptionsTest.java b/src/test/java/io/appium/java_client/android/AndroidOptionsTest.java deleted file mode 100644 index 26061993f..000000000 --- a/src/test/java/io/appium/java_client/android/AndroidOptionsTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobilePlatform; -import org.junit.Test; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.Platform; -import org.openqa.selenium.ScreenOrientation; - -import java.net.MalformedURLException; -import java.net.URL; -import java.time.Duration; - -import static org.junit.Assert.assertEquals; - -public class AndroidOptionsTest { - - @Test - public void setsPlatformNameByDefault() { - assertEquals(Platform.ANDROID, new AndroidOptions().getPlatformName()); - } - - @Test - public void acceptsExistingCapabilities() { - MutableCapabilities capabilities = new MutableCapabilities(); - capabilities.setCapability("deviceName", "Pixel"); - capabilities.setCapability("platformVersion", "10"); - capabilities.setCapability("newCommandTimeout", 60); - - AndroidOptions androidOptions = new AndroidOptions(capabilities); - - assertEquals("Pixel", androidOptions.getDeviceName()); - assertEquals("10", androidOptions.getPlatformVersion()); - assertEquals(Duration.ofSeconds(60), androidOptions.getNewCommandTimeout()); - } - - @Test - public void acceptsMobileCapabilities() throws MalformedURLException { - AndroidOptions androidOptions = new AndroidOptions(); - androidOptions.setApp(new URL("http://example.com/myapp.apk")) - .setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2) - .setPlatformVersion("10") - .setDeviceName("Pixel") - .setOtherApps("/path/to/app.apk") - .setLocale("fr_CA") - .setUdid("1ae203187fc012g") - .setOrientation(ScreenOrientation.LANDSCAPE) - .setNewCommandTimeout(Duration.ofSeconds(60)) - .setLanguage("fr"); - - assertEquals("http://example.com/myapp.apk", androidOptions.getApp()); - assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, androidOptions.getAutomationName()); - assertEquals("10", androidOptions.getPlatformVersion()); - assertEquals("Pixel", androidOptions.getDeviceName()); - assertEquals("/path/to/app.apk", androidOptions.getOtherApps()); - assertEquals("fr_CA", androidOptions.getLocale()); - assertEquals("1ae203187fc012g", androidOptions.getUdid()); - assertEquals(ScreenOrientation.LANDSCAPE, androidOptions.getOrientation()); - assertEquals(Duration.ofSeconds(60), androidOptions.getNewCommandTimeout()); - assertEquals("fr", androidOptions.getLanguage()); - } -} diff --git a/src/test/java/io/appium/java_client/ios/IOSOptionsTest.java b/src/test/java/io/appium/java_client/ios/IOSOptionsTest.java deleted file mode 100644 index 4bfa02ea6..000000000 --- a/src/test/java/io/appium/java_client/ios/IOSOptionsTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobilePlatform; -import org.junit.Test; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.Platform; -import org.openqa.selenium.ScreenOrientation; - -import java.net.MalformedURLException; -import java.net.URL; -import java.time.Duration; - -import static org.junit.Assert.assertEquals; - -public class IOSOptionsTest { - private IOSOptions iosOptions = new IOSOptions(); - - @Test - public void setsPlatformNameByDefault() { - assertEquals(Platform.IOS, iosOptions.getPlatformName()); - } - - @Test - public void acceptsExistingCapabilities() { - MutableCapabilities capabilities = new MutableCapabilities(); - capabilities.setCapability("deviceName", "Pixel"); - capabilities.setCapability("platformVersion", "10"); - capabilities.setCapability("newCommandTimeout", 60); - - iosOptions = new IOSOptions(capabilities); - - assertEquals("Pixel", iosOptions.getDeviceName()); - assertEquals("10", iosOptions.getPlatformVersion()); - assertEquals(Duration.ofSeconds(60), iosOptions.getNewCommandTimeout()); - } - - @Test - public void acceptsMobileCapabilities() throws MalformedURLException { - iosOptions.setApp(new URL("http://example.com/myapp.apk")) - .setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2) - .setPlatformVersion("10") - .setDeviceName("Pixel") - .setOtherApps("/path/to/app.apk") - .setLocale("fr_CA") - .setUdid("1ae203187fc012g") - .setOrientation(ScreenOrientation.LANDSCAPE) - .setNewCommandTimeout(Duration.ofSeconds(60)) - .setLanguage("fr"); - - assertEquals("http://example.com/myapp.apk", iosOptions.getApp()); - assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, iosOptions.getAutomationName()); - assertEquals("10", iosOptions.getPlatformVersion()); - assertEquals("Pixel", iosOptions.getDeviceName()); - assertEquals("/path/to/app.apk", iosOptions.getOtherApps()); - assertEquals("fr_CA", iosOptions.getLocale()); - assertEquals("1ae203187fc012g", iosOptions.getUdid()); - assertEquals(ScreenOrientation.LANDSCAPE, iosOptions.getOrientation()); - assertEquals(Duration.ofSeconds(60), iosOptions.getNewCommandTimeout()); - assertEquals("fr", iosOptions.getLanguage()); - } -} From 4e8920bfc9e70f3200df5b4903212c8528e6ec55 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 5 Apr 2022 08:34:21 +0300 Subject: [PATCH 086/501] chore: Delete all references to removed `MobileElement` class (#1677) --- .../io/appium/java_client/pagefactory/ElementInterceptor.java | 2 +- .../java_client/pagefactory/ElementListInterceptor.java | 2 +- .../java_client/pagefactory/utils/WebDriverUnpackUtility.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java index a95740aff..35a703e8a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java @@ -26,7 +26,7 @@ import java.lang.reflect.Method; /** - * Intercepts requests to {@link io.appium.java_client.MobileElement}. + * Intercepts requests to {@link WebElement}. */ class ElementInterceptor extends InterceptorOfASingleElement { diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java index 08c58627c..5dd385b29 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java @@ -26,7 +26,7 @@ import java.util.List; /** - * Intercepts requests to the list of {@link io.appium.java_client.MobileElement}. + * Intercepts requests to the list of {@link WebElement}. */ class ElementListInterceptor extends InterceptorOfAListOfElements { diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index e11aa2e4d..8aa5f7634 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -55,8 +55,8 @@ public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchCon ((WrapsDriver) searchContext).getWrappedDriver()); } - // Search context it is not only Webdriver. Webelement is search context too. - // RemoteWebElement and MobileElement implement WrapsDriver + // Search context it is not only WebDriver. WebElement is search context too. + // RemoteWebElement implements WrapsDriver if (searchContext instanceof WrapsElement) { return unpackWebDriverFromSearchContext( ((WrapsElement) searchContext).getWrappedElement()); From 59000773d0bc74ddd5201b0acfecd096818b9db9 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 13 Apr 2022 18:55:48 +0200 Subject: [PATCH 087/501] fix: Pass orientation name capability in uppercase (#1686) --- .../java_client/remote/options/SupportsOrientationOption.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java index e27acbdcf..3bc8b16e0 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java @@ -32,7 +32,7 @@ public interface SupportsOrientationOption> extends * @return self instance for chaining. */ default T setOrientation(ScreenOrientation orientation) { - return amend(ORIENTATION_OPTION, orientation.value()); + return amend(ORIENTATION_OPTION, orientation.name()); } /** From c930603982697053f3de2f0135075b8d40b6079c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 14 Apr 2022 08:41:04 +0200 Subject: [PATCH 088/501] chore: Add new EspressoBuildConfig options (#1687) --- .../options/server/EspressoBuildConfig.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java index 209cdcac2..2044f0bd1 100644 --- a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java +++ b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java @@ -134,6 +134,83 @@ public Optional getCompileSdkVersion() { return getToolsVersionsFieldValue("compileSdk"); } + /** + * Set the version of the included androidx.compose.ui components to compile the server for. + * By default, the version from app's build.gradle is used. + * + * @param composeVersion E.g. "1.0.5" + * @return self instance for chaining. + */ + public EspressoBuildConfig withComposeVersion(String composeVersion) { + return assignToolsVersionsField("composeVersion", composeVersion); + } + + /** + * Get the version of included androidx.compose.ui components. + * + * @return Version of androidx.compose.ui components. + */ + public Optional getComposeVersion() { + return getToolsVersionsFieldValue("composeVersion"); + } + + /** + * Set the minimum version of JVM the project sources are compatible with. + * + * @param sourceCompatibility E.g. "VERSION_12" + * @return self instance for chaining. + */ + public EspressoBuildConfig withSourceCompatibility(String sourceCompatibility) { + return assignToolsVersionsField("sourceCompatibility", sourceCompatibility); + } + + /** + * Get the minimum version of JVM the project sources are compatible with. + * + * @return Minimum version of JVM the project sources are compatible with. + */ + public Optional getSourceCompatibility() { + return getToolsVersionsFieldValue("sourceCompatibility"); + } + + /** + * Set the target version of the generated JVM bytecode as a string. + * + * @param jvmTarget E.g. "1_10" or `1_8` + * @return self instance for chaining. + */ + public EspressoBuildConfig withJvmTarget(String jvmTarget) { + return assignToolsVersionsField("jvmTarget", jvmTarget); + } + + /** + * Get the target version of the generated JVM bytecode as a string. + * + * @return Target version of the generated JVM bytecode as a string. + */ + public Optional getJvmTarget() { + return getToolsVersionsFieldValue("jvmTarget"); + } + + /** + * Set the target version of JVM the project sources are compatible with. + * + * @param targetCompatibility E.g. "VERSION_12" + * @return self instance for chaining. + */ + public EspressoBuildConfig withTargetCompatibility(String targetCompatibility) { + return assignToolsVersionsField("targetCompatibility", targetCompatibility); + } + + /** + * Get the target version of JVM the project sources are compatible with. + * + * @return Target version of JVM the project sources are compatible with. + */ + public Optional getTargetCompatibility() { + return getToolsVersionsFieldValue("targetCompatibility"); + } + /** * Set the minimum Android SDK version to compile the server for. * By default, the version from the app build.gradle is used. From 2d1726cb6c0aec142c438e76772c5f6ad5fb90cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 May 2022 09:54:01 +0200 Subject: [PATCH 089/501] build(deps): bump webdrivermanager from 5.1.0 to 5.1.1 (#1682) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.1.0 to 5.1.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.1.0...webdrivermanager-5.1.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index abf723873..644e58323 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.1.0') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.1.1') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From 293dd055a4bf272953bcf415c2bb728c199bbeef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 May 2022 09:54:14 +0200 Subject: [PATCH 090/501] build(deps): bump lombok from 1.18.22 to 1.18.24 (#1688) Bumps [lombok](https://github.com/projectlombok/lombok) from 1.18.22 to 1.18.24. - [Release notes](https://github.com/projectlombok/lombok/releases) - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.22...v1.18.24) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 644e58323..f48418efd 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.22' + compileOnly 'org.projectlombok:lombok:1.18.24' annotationProcessor 'org.projectlombok:lombok:1.18.22' api ('org.seleniumhq.selenium:selenium-api') { From 1a970e44e055190cad5880e4e79c8f2b19a3bfe4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 May 2022 09:54:34 +0200 Subject: [PATCH 091/501] build(deps): bump org.owasp.dependencycheck from 7.0.4.1 to 7.1.0.1 (#1691) Bumps org.owasp.dependencycheck from 7.0.4.1 to 7.1.0.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f48418efd..4e3b9b855 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.0.4.1' + id 'org.owasp.dependencycheck' version '7.1.0.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 40c22da9b5137d5831ba2c345f4dbb664a8b3fad Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 29 May 2022 16:07:11 +0200 Subject: [PATCH 092/501] chore: Bump minimum selenium api version to 4.2.0 (#1696) --- build.gradle | 10 +++++----- gradle.properties | 2 +- .../remote/AppiumNewSessionCommandPayload.java | 2 +- .../appium/java_client/remote/options/BaseOptions.java | 2 +- .../java_client/android/AndroidDataMatcherTest.java | 4 +++- .../java_client/android/OpenNotificationsTest.java | 3 ++- .../java/io/appium/java_client/ios/IOSAlertTest.java | 5 +++-- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 4e3b9b855..1a7943b76 100644 --- a/build.gradle +++ b/build.gradle @@ -29,23 +29,23 @@ ext { dependencies { compileOnly 'org.projectlombok:lombok:1.18.24' - annotationProcessor 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.24' api ('org.seleniumhq.selenium:selenium-api') { version { - strictly '[4.0, 5.0)' + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } api ('org.seleniumhq.selenium:selenium-remote-driver') { version { - strictly '[4.0, 5.0)' + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } implementation ('org.seleniumhq.selenium:selenium-support') { version { - strictly '[4.0, 5.0)' + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } @@ -64,7 +64,7 @@ dependencies { } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { version { - strictly '[4.0, 5.0)' + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } diff --git a/gradle.properties b/gradle.properties index 0e37bcb22..cc4c62990 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile ossrhUsername=your-jira-id ossrhPassword=your-jira-password -selenium.version=4.1.1 +selenium.version=4.2.0 diff --git a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java index 81a8f44e1..5ebbdfbc3 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java +++ b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java @@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableSet; import org.openqa.selenium.Capabilities; import org.openqa.selenium.internal.Require; -import org.openqa.selenium.remote.AcceptedW3CCapabilityKeys; +import org.openqa.selenium.AcceptedW3CCapabilityKeys; import org.openqa.selenium.remote.CommandPayload; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index b54057314..c157fc684 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -21,7 +21,7 @@ import org.openqa.selenium.Platform; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.internal.Require; -import org.openqa.selenium.remote.AcceptedW3CCapabilityKeys; +import org.openqa.selenium.AcceptedW3CCapabilityKeys; import org.openqa.selenium.remote.CapabilityType; import javax.annotation.Nullable; diff --git a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java index ef54035c6..afe0b7653 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java @@ -24,13 +24,15 @@ import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; + import static org.junit.Assert.assertNotNull; public class AndroidDataMatcherTest extends BaseEspressoTest { @Test public void testFindByDataMatcher() { - final WebDriverWait wait = new WebDriverWait(driver, 10); + final WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions .elementToBeClickable(AppiumBy.accessibilityId("Graphics"))); driver.findElement(AppiumBy.accessibilityId("Graphics")).click(); diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index db055c305..293479e53 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -8,6 +8,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; import java.util.List; public class OpenNotificationsTest extends BaseAndroidTest { @@ -15,7 +16,7 @@ public class OpenNotificationsTest extends BaseAndroidTest { public void openNotification() { driver.closeApp(); driver.openNotifications(); - WebDriverWait wait = new WebDriverWait(driver, 20); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20)); assertNotEquals(0, wait.until(input -> { List result = input .findElements(id("com.android.systemui:id/settings_button")); diff --git a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java index 07edb2be5..8fa3afd13 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java @@ -30,15 +30,16 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; import java.util.function.Supplier; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class IOSAlertTest extends AppIOSTest { - private static final long ALERT_TIMEOUT_SECONDS = 5; + private static final Duration ALERT_TIMEOUT = Duration.ofSeconds(5); private static final int CLICK_RETRIES = 2; - private final WebDriverWait waiter = new WebDriverWait(driver, ALERT_TIMEOUT_SECONDS); + private final WebDriverWait waiter = new WebDriverWait(driver, ALERT_TIMEOUT); private static final String iOSAutomationText = "show alert"; private void ensureAlertPresence() { From 92133301603d4aae71a95a1b318f96de5cba239f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 May 2022 16:28:06 +0300 Subject: [PATCH 093/501] build(deps): bump webdrivermanager from 5.1.1 to 5.2.0 (#1697) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.1.1 to 5.2.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.1.1...webdrivermanager-5.2.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1a7943b76..2f4dd2173 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.1.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.0') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From 938b49f95504106edd52739d99501970420c235c Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 30 May 2022 22:16:12 +0530 Subject: [PATCH 094/501] Release 8.1.0 and update release notes --- README.md | 18 ++++++++++++++++++ build.gradle | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4bed5b7e4..5a7b83f65 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,24 @@ dependencies { ``` ## Changelog +*8.1.0* +- **[ENHANCEMENTS]** + - Add new EspressoBuildConfig options. [#1687](https://github.com/appium/java-client/pull/1687) +- **[DOCUMENTATION]** + - delete all references to removed MobileElement class. [#1677](https://github.com/appium/java-client/pull/1677) +- **[BUG FIX]** + - Pass orientation name capability in uppercase. [#1686](https://github.com/appium/java-client/pull/1686) + - correction for ping method to get proper status URL. [#1661](https://github.com/appium/java-client/pull/1661) + - Remove deprecated option classes. [#1679](https://github.com/appium/java-client/pull/1679) + - Remove obsolete event firing decorators. [#1676](https://github.com/appium/java-client/pull/1676) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.2.0. + - `org.owasp.dependencycheck` was updated to 7.1.0.1. + - `org.springframework:spring-context` was updated to 5.3.18. + - `org.aspectj:aspectjweaver` was updated to 1.9.9. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.2.0. + - `org.projectlombok:lombok` was updated to 1.18.24. + *8.0.0* - **[DOCUMENTATION]** - Set minimum Java version to 1.8.0. [#1631](https://github.com/appium/java-client/pull/1631) diff --git a/build.gradle b/build.gradle index 2f4dd2173..d3eeeb4c0 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '8.0.0' + version = '8.1.0' from components.java pom { name = 'java-client' From 28ef8874cad423c412a74f7b96e8082257a6eba9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 31 May 2022 08:13:33 +0300 Subject: [PATCH 095/501] docs: Polish release notes for v8.1.0 (#1698) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a7b83f65..a381ac89a 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ dependencies { - **[DEPENDENCY UPDATES]** - `org.seleniumhq.selenium:selenium-java` was updated to 4.2.0. - `org.owasp.dependencycheck` was updated to 7.1.0.1. - - `org.springframework:spring-context` was updated to 5.3.18. + - `org.springframework:spring-context` was removed. [#1676](https://github.com/appium/java-client/pull/1676) - `org.aspectj:aspectjweaver` was updated to 1.9.9. - `io.github.bonigarcia:webdrivermanager` was updated to 5.2.0. - `org.projectlombok:lombok` was updated to 1.18.24. From 9b4e32ec9b04531a603aaa7a53916abd2b13b343 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 31 May 2022 10:28:17 +0200 Subject: [PATCH 096/501] chore: Ignore the test which has a connected server issue (#1699) --- .../appium/java_client/ios/IOSNativeWebTapSettingTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java b/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java index b48410348..67f388d34 100644 --- a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java @@ -4,6 +4,7 @@ import java.time.Duration; +import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; @@ -12,7 +13,9 @@ public class IOSNativeWebTapSettingTest extends BaseSafariTest { - @Test public void nativeWebTapSettingTest() { + @Test + @Ignore("https://github.com/appium/appium/issues/17014") + public void nativeWebTapSettingTest() { assertTrue(driver.isBrowser()); driver.get("https://saucelabs.com/test/guinea-pig"); From c68d503ff9c97dea6bedd0809ca5bbc88def6ee8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 1 Jun 2022 11:56:12 +0200 Subject: [PATCH 097/501] fix: Perform safe typecast while getting the platform name (#1702) --- gradle.properties | 2 +- src/main/java/io/appium/java_client/AppiumDriver.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index cc4c62990..62048789f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile ossrhUsername=your-jira-id ossrhPassword=your-jira-password -selenium.version=4.2.0 +selenium.version=4.2.1 diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 6d57cadd2..1616053ac 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -133,8 +133,7 @@ public AppiumDriver(Capabilities capabilities) { */ protected static Capabilities ensurePlatformName( Capabilities originalCapabilities, String defaultName) { - String currentName = (String) originalCapabilities.getCapability(PLATFORM_NAME); - return isBlank(currentName) + return originalCapabilities.getPlatformName() == null ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) : originalCapabilities; } From b4aeb6eadebfa8f47290aa14ba1762284f1b1b90 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 2 Jun 2022 09:42:39 +0200 Subject: [PATCH 098/501] fix: Add prefix to platformVersion capability name (#1704) --- .../AppiumNewSessionCommandPayload.java | 13 ++--- .../remote/options/BaseOptions.java | 24 +++++---- .../remote/options/W3CCapabilityKeys.java | 49 +++++++++++++++++++ 3 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java diff --git a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java index 5ebbdfbc3..a57170d6c 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java +++ b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java @@ -18,19 +18,16 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import io.appium.java_client.remote.options.BaseOptions; import org.openqa.selenium.Capabilities; import org.openqa.selenium.internal.Require; -import org.openqa.selenium.AcceptedW3CCapabilityKeys; import org.openqa.selenium.remote.CommandPayload; import java.util.Map; -import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; public class AppiumNewSessionCommandPayload extends CommandPayload { - private static final AcceptedW3CCapabilityKeys ACCEPTED_W3C_PATTERNS = new AcceptedW3CCapabilityKeys(); - /** * Appends "appium:" prefix to all non-prefixed non-standard capabilities. * @@ -40,10 +37,10 @@ public class AppiumNewSessionCommandPayload extends CommandPayload { private static Map makeW3CSafe(Capabilities possiblyInvalidCapabilities) { return Require.nonNull("Capabilities", possiblyInvalidCapabilities) .asMap().entrySet().stream() - .collect(ImmutableMap.toImmutableMap(entry -> ACCEPTED_W3C_PATTERNS.test(entry.getKey()) - ? entry.getKey() - : APPIUM_PREFIX + entry.getKey(), - Map.Entry::getValue)); + .collect(ImmutableMap.toImmutableMap( + entry -> BaseOptions.toW3cName(entry.getKey()), + Map.Entry::getValue + )); } /** diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index c157fc684..7ef52b7e4 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -21,7 +21,6 @@ import org.openqa.selenium.Platform; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.internal.Require; -import org.openqa.selenium.AcceptedW3CCapabilityKeys; import org.openqa.selenium.remote.CapabilityType; import javax.annotation.Nullable; @@ -51,7 +50,6 @@ public class BaseOptions> extends MutableCapabilities i SupportsNewCommandTimeoutOption, SupportsBrowserNameOption, SupportsPlatformVersionOption { - private static final AcceptedW3CCapabilityKeys W3C_KEY_PATTERNS = new AcceptedW3CCapabilityKeys(); /** * Creates new instance with no preset capabilities. @@ -109,8 +107,7 @@ public Platform getPlatformName() { @Override public Map asMap() { return unmodifiableMap(super.asMap().entrySet().stream() - .collect(Collectors.toMap(entry -> W3C_KEY_PATTERNS.test(entry.getKey()) - ? entry.getKey() : APPIUM_PREFIX + entry.getKey(), Map.Entry::getValue) + .collect(Collectors.toMap(entry -> toW3cName(entry.getKey()), Map.Entry::getValue) )); } @@ -145,16 +142,25 @@ public T clone() { @Override public void setCapability(String key, @Nullable Object value) { Require.nonNull("Capability name", key); - super.setCapability(W3C_KEY_PATTERNS.test(key) ? key : APPIUM_PREFIX + key, value); + super.setCapability(toW3cName(key), value); } @Override @Nullable public Object getCapability(String capabilityName) { Object value = super.getCapability(capabilityName); - if (value == null) { - value = super.getCapability(APPIUM_PREFIX + capabilityName); - } - return value; + return value == null + ? super.getCapability(APPIUM_PREFIX + capabilityName) + : value; + } + + /** + * Adds the 'appium:' prefix to the given capability name if necessary. + * + * @param capName the original capability name. + * @return The preformatted W3C-compatible capability name. + */ + public static String toW3cName(String capName) { + return W3CCapabilityKeys.INSTANCE.test(capName) ? capName : APPIUM_PREFIX + capName; } } \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java b/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java new file mode 100644 index 000000000..b29150311 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.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.remote.options; + +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +public class W3CCapabilityKeys implements Predicate { + public static final W3CCapabilityKeys INSTANCE = new W3CCapabilityKeys(); + private static final Predicate ACCEPTED_W3C_PATTERNS = Stream.of( + "^[\\w-]+:.*$", + "^acceptInsecureCerts$", + "^browserName$", + "^browserVersion$", + "^platformName$", + "^pageLoadStrategy$", + "^proxy$", + "^setWindowRect$", + "^strictFileInteractability$", + "^timeouts$", + "^unhandledPromptBehavior$", + "^webSocketUrl$") // from webdriver-bidi + .map(Pattern::compile) + .map(Pattern::asPredicate) + .reduce(identity -> false, Predicate::or); + + protected W3CCapabilityKeys() { + } + + @Override + public boolean test(String capabilityName) { + return ACCEPTED_W3C_PATTERNS.test(capabilityName); + } +} From f1856bd59008eb654655c64ff1537dee179afab3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 4 Jun 2022 19:36:19 +0200 Subject: [PATCH 099/501] test: Update e2e tests (#1706) --- .../widget/tests/AbstractStubWebDriver.java | 32 ++++++------------- .../tests/combined/CombinedAppTest.java | 7 ++-- .../tests/combined/CombinedWidgetTest.java | 7 ++-- .../local/StartingAppLocallyAndroidTest.java | 6 ++-- 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index b9b9d097e..bea245a99 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -1,7 +1,7 @@ package io.appium.java_client.pagefactory_tests.widget.tests; import static com.google.common.collect.ImmutableList.of; -import static io.appium.java_client.remote.AutomationName.APPIUM; +import static io.appium.java_client.remote.AutomationName.ANDROID_UIAUTOMATOR2; import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; import static io.appium.java_client.remote.MobilePlatform.ANDROID; import static io.appium.java_client.remote.MobilePlatform.IOS; @@ -13,13 +13,12 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Cookie; import org.openqa.selenium.HasCapabilities; +import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.logging.Logs; -import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.Response; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -115,10 +114,10 @@ public String getAutomationName() { @Override public Capabilities getCapabilities() { - Map caps = new HashMap<>(); - caps.put("platformName", getPlatformName()); - caps.put("automationName", getAutomationName()); - return new DesiredCapabilities(caps); + return new ImmutableCapabilities( + "appium:platformName", getPlatformName(), + "appium:automationName", getAutomationName() + ); } @Override @@ -200,20 +199,7 @@ public String getPlatformName() { @Override public String getAutomationName() { - return APPIUM; - } - } - - public static class StubIOSDriver extends AbstractStubWebDriver { - - @Override - public String getPlatformName() { - return IOS; - } - - @Override - public String getAutomationName() { - return APPIUM; + return ANDROID_UIAUTOMATOR2; } } @@ -239,7 +225,7 @@ public String getPlatformName() { @Override public String getAutomationName() { - return APPIUM; + return WINDOWS; } } @@ -265,7 +251,7 @@ public String getPlatformName() { @Override public String getAutomationName() { - return APPIUM; + return ANDROID; } @Override diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index a0d87a4f8..9953578be 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -2,9 +2,9 @@ import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; import io.appium.java_client.pagefactory.OverrideWidget; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractApp; @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.List; +@SuppressWarnings({"unused", "unchecked"}) @RunWith(Parameterized.class) public class CombinedAppTest extends WidgetTest { @@ -42,8 +43,6 @@ public static Collection data() { DefaultFindByWidget.class), dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubIOSDriver(), - DefaultStubWidget.class), dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultStubWidget.class), dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), @@ -62,7 +61,7 @@ public CombinedAppTest(AbstractApp app, WebDriver driver, Class data() { new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class), dataArray(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - dataArray(new AppWithPartiallyCombinedWidgets(), - new AbstractStubWebDriver.StubIOSDriver(), DefaultStubWidget.class), dataArray(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultStubWidget.class), dataArray(new AppWithPartiallyCombinedWidgets(), @@ -68,7 +67,7 @@ public CombinedWidgetTest(AbstractApp app, WebDriver driver, Class widgetClas @Override public void checkThatWidgetsAreCreatedCorrectly() { - assertThat("Excpected widget class was " + widgetClass.getName(), + assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSubWidget().getSelfReference().getClass(), equalTo(widgetClass)); diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index ee7eb82e2..34b0e2565 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -46,7 +46,7 @@ public void startingAndroidAppWithCapabilitiesOnlyTest() { Capabilities caps = driver.getCapabilities(); assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( - (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) + String.valueOf(caps.getCapability(MobileCapabilityType.PLATFORM_NAME))) ); assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); @@ -70,7 +70,7 @@ public void startingAndroidAppWithCapabilitiesAndServiceTest() { Capabilities caps = driver.getCapabilities(); assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( - (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) + String.valueOf(caps.getCapability(MobileCapabilityType.PLATFORM_NAME))) ); assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); } finally { @@ -105,7 +105,7 @@ public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { Capabilities caps = driver.getCapabilities(); assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( - (String) caps.getCapability(MobileCapabilityType.PLATFORM_NAME)) + String.valueOf(caps.getCapability(MobileCapabilityType.PLATFORM_NAME))) ); assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); } finally { From ea09b215f6ad20830dc4afb3d2dc7e3285e308ab Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Sun, 5 Jun 2022 21:13:09 +0530 Subject: [PATCH 100/501] Release 8.1.1 and update release notes --- README.md | 8 ++++++++ build.gradle | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a381ac89a..39c936ba5 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,14 @@ dependencies { ``` ## Changelog +*8.1.1* +- **[BUG FIX]** + - Perform safe typecast while getting the platform name. [#1702](https://github.com/appium/java-client/pull/1702) + - Add prefix to platformVersion capability name. [#1704](https://github.com/appium/java-client/pull/1704) +- **[REFRACTOR]** + - Update e2e tests to make it green. [#1706](https://github.com/appium/java-client/pull/1706) + - Ignore the test which has a connected server issue. [#1699](https://github.com/appium/java-client/pull/1699) + *8.1.0* - **[ENHANCEMENTS]** - Add new EspressoBuildConfig options. [#1687](https://github.com/appium/java-client/pull/1687) diff --git a/build.gradle b/build.gradle index d3eeeb4c0..539c4cb61 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '8.1.0' + version = '8.1.1' from components.java pom { name = 'java-client' From 101a2e207f522ee77ba6d5a4d5d091b5adf12fb3 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 8 Jun 2022 05:51:53 +0300 Subject: [PATCH 101/501] chore: Upgrade to Gradle 7.4.2 (#1708) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 539c4cb61..cc332c44d 100644 --- a/build.gradle +++ b/build.gradle @@ -181,7 +181,7 @@ signing { } wrapper { - gradleVersion = '7.1.1' + gradleVersion = '7.4.2' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 8958 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fbce071a3..92f06b50f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 14f8017817a38504e088d6bbd6ce8e0d7fc079db Mon Sep 17 00:00:00 2001 From: jiangyitao <451988022@163.com> Date: Mon, 13 Jun 2022 15:27:31 +0800 Subject: [PATCH 102/501] feat: AppiumDriverLocalService can handle outputStreams (#1709) --- .../service/local/AppiumDriverLocalService.java | 13 ++++++++++++- .../java_client/service/local/ListOutputStream.java | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index cc1c77ad5..d4cedc033 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -44,6 +44,7 @@ import java.time.Duration; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; @@ -70,7 +71,7 @@ public final class AppiumDriverLocalService extends DriverService { private final ListOutputStream stream = new ListOutputStream().add(System.out); private final URL url; private String basePath; - + private CommandLine process = null; AppiumDriverLocalService(String ipAddress, File nodeJSExec, @@ -294,6 +295,16 @@ public void addOutPutStreams(List outputStreams) { } } + /** + * Remove the outputStream which is receiving server output data. + * + * @return the outputStream has been removed if it is present + */ + public Optional removeOutPutStream(OutputStream outputStream) { + checkNotNull(outputStream, "outputStream parameter is NULL!"); + return stream.remove(outputStream); + } + /** * Remove all existing server output streams. * diff --git a/src/main/java/io/appium/java_client/service/local/ListOutputStream.java b/src/main/java/io/appium/java_client/service/local/ListOutputStream.java index 6586d5cc1..89820f70a 100644 --- a/src/main/java/io/appium/java_client/service/local/ListOutputStream.java +++ b/src/main/java/io/appium/java_client/service/local/ListOutputStream.java @@ -20,6 +20,7 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.List; +import java.util.Optional; class ListOutputStream extends OutputStream { @@ -30,6 +31,10 @@ ListOutputStream add(OutputStream stream) { return this; } + Optional remove(OutputStream stream) { + return streams.remove(stream) ? Optional.of(stream) : Optional.empty(); + } + @Override public void write(int i) throws IOException { for (OutputStream stream : streams) { stream.write(i); From 2a3d0d2205f62f92260d36f2acb7c5ca43aae285 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jun 2022 17:19:31 +0300 Subject: [PATCH 103/501] build(deps): bump org.owasp.dependencycheck from 7.1.0.1 to 7.1.1 (#1710) Bumps org.owasp.dependencycheck from 7.1.0.1 to 7.1.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cc332c44d..a48920905 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.1.0.1' + id 'org.owasp.dependencycheck' version '7.1.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 02ce866f8a4eeb7657dde93227cfa96f02582eb2 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 21 Jun 2022 09:20:34 +0200 Subject: [PATCH 104/501] fix: Update the environment argument type (#1712) --- .../mac/options/SupportsEnvironmentOption.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java b/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java index 17a2d05f9..803561030 100644 --- a/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java +++ b/src/main/java/io/appium/java_client/mac/options/SupportsEnvironmentOption.java @@ -20,7 +20,7 @@ import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; -import java.util.List; +import java.util.Map; import java.util.Optional; public interface SupportsEnvironmentOption> extends @@ -33,11 +33,11 @@ public interface SupportsEnvironmentOption> extends * the parent process. This capability is only going to be applied if the application * is not running on session startup. * - * @param arguments E.g. ["--help"]. + * @param env E.g. ["--help"]. * @return self instance for chaining. */ - default T setEnvironment(List arguments) { - return amend(ENVIRONMENT_OPTION, arguments); + default T setEnvironment(Map env) { + return amend(ENVIRONMENT_OPTION, env); } /** @@ -45,8 +45,8 @@ default T setEnvironment(List arguments) { * * @return Application environment mapping. */ - default Optional> getEnvironment() { + default Optional> getEnvironment() { //noinspection unchecked - return Optional.ofNullable((List) getCapability(ENVIRONMENT_OPTION)); + return Optional.ofNullable((Map) getCapability(ENVIRONMENT_OPTION)); } } From 5bdab90b6afcaafdf9e582bab2fb5fe4c3409a62 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 21 Jun 2022 23:22:10 +0200 Subject: [PATCH 105/501] test: Bump Node.js version (#1713) --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 51703c04f..9d6f6fc5d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,7 +14,7 @@ variables: XCODE_VERSION: 11.5 IOS_PLATFORM_VERSION: 13.5 IOS_DEVICE_NAME: iPhone X - NODE_VERSION: 14.x + NODE_VERSION: 16.x JDK_VERSION: 1.8 jobs: From a9985c64ffb27ed061531f8ac1a481f349acba6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 14:26:22 +0300 Subject: [PATCH 106/501] build(deps): bump webdrivermanager from 5.2.0 to 5.2.1 (#1714) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.2.0 to 5.2.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.2.0...webdrivermanager-5.2.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a48920905..e1a71aa40 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.0') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.1') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From 3127fda0bac51c7b92fafa4ad8ebce8c431fc5cb Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 25 Jul 2022 07:34:18 +0300 Subject: [PATCH 107/501] chore: Upgrade to Gradle 7.5 (#1720) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 ++++++ gradlew.bat | 14 ++++++++------ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index e1a71aa40..016aeaefe 100644 --- a/build.gradle +++ b/build.gradle @@ -181,7 +181,7 @@ signing { } wrapper { - gradleVersion = '7.4.2' + gradleVersion = '7.5' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10197 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 92f06b50f..2ec77e51a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c78733..a69d9cb6c 100755 --- a/gradlew +++ b/gradlew @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f93..53a6b238d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From da326d631de72847491e853a201dcd26f7f4525a Mon Sep 17 00:00:00 2001 From: Ramesh Babu Prudhvi Date: Thu, 28 Jul 2022 23:46:01 +0530 Subject: [PATCH 108/501] test: Run tests on the JUnit Jupiter Platform (#1721) --- build.gradle | 8 +-- .../AndroidAbilityToUseSupplierTest.java | 4 +- .../android/AndroidActivityTest.java | 8 +-- .../android/AndroidAppStringsTest.java | 4 +- .../android/AndroidConnectionTest.java | 12 ++--- .../android/AndroidContextTest.java | 18 ++++--- .../android/AndroidDataMatcherTest.java | 4 +- .../android/AndroidDriverTest.java | 16 +++--- .../android/AndroidElementTest.java | 12 ++--- .../android/AndroidFunctionTest.java | 25 +++++---- .../android/AndroidLogcatListenerTest.java | 10 ++-- .../android/AndroidScreenRecordTest.java | 6 +-- .../android/AndroidSearchingTest.java | 12 ++--- .../java_client/android/AndroidTouchTest.java | 10 ++-- .../android/AndroidViewMatcherTest.java | 4 +- .../java_client/android/BaseAndroidTest.java | 8 +-- .../java_client/android/BaseEspressoTest.java | 8 +-- .../java_client/android/BatteryTest.java | 2 +- .../java_client/android/ClipboardTest.java | 8 +-- .../android/ExecuteCDPCommandTest.java | 12 ++--- .../android/ExecuteDriverScriptTest.java | 6 +-- .../java_client/android/FingerPrintTest.java | 22 ++++---- .../android/ImagesComparisonTest.java | 8 +-- .../java_client/android/IntentTest.java | 14 ++--- .../java_client/android/KeyCodeTest.java | 10 ++-- .../java_client/android/LogEventTest.java | 6 +-- .../android/OpenNotificationsTest.java | 5 +- .../java_client/android/SettingTest.java | 4 +- .../java_client/android/UIAutomator2Test.java | 15 +++--- .../drivers/options/OptionsBuildingTest.java | 10 ++-- .../java_client/events/EventsFiringTest.java | 10 ++-- .../java_client/internal/ConfigTest.java | 17 +++--- .../io/appium/java_client/ios/AppIOSTest.java | 6 +-- .../appium/java_client/ios/BaseIOSTest.java | 4 +- .../java_client/ios/BaseIOSWebViewTest.java | 4 +- .../java_client/ios/BaseSafariTest.java | 4 +- .../appium/java_client/ios/ClipboardTest.java | 4 +- .../appium/java_client/ios/IOSAlertTest.java | 16 +++--- .../java_client/ios/IOSAppStringsTest.java | 4 +- .../java_client/ios/IOSContextTest.java | 16 +++--- .../appium/java_client/ios/IOSDriverTest.java | 28 +++++----- .../java_client/ios/IOSElementTest.java | 14 ++--- .../ios/IOSNativeWebTapSettingTest.java | 8 +-- .../java_client/ios/IOSScreenRecordTest.java | 2 +- .../java_client/ios/IOSSearchingTest.java | 4 +- .../ios/IOSSyslogListenerTest.java | 10 ++-- .../appium/java_client/ios/IOSTouchTest.java | 12 ++--- .../java_client/ios/IOSWebViewTest.java | 4 +- .../java_client/ios/ImagesComparisonTest.java | 8 +-- .../appium/java_client/ios/RotationTest.java | 8 +-- .../appium/java_client/ios/SettingTest.java | 4 +- .../AndroidPageObjectTest.java | 27 +++++----- .../DesktopBrowserCompatibilityTest.java | 10 ++-- .../MobileBrowserCompatibilityTest.java | 14 ++--- .../pagefactory_tests/TimeoutTest.java | 16 +++--- .../pagefactory_tests/XCUITModeTest.java | 20 +++---- .../widget/tests/ExtendedWidgetTest.java | 47 ----------------- .../widget/tests/WidgetTest.java | 42 ++++++++++++--- .../tests/android/AndroidWidgetTest.java | 9 +++- .../tests/combined/CombinedAppTest.java | 52 ++++++++----------- .../tests/combined/CombinedWidgetTest.java | 52 ++++++++----------- .../widget/tests/ios/XCUITWidgetTest.java | 9 +++- .../tests/windows/WindowsWidgetTest.java | 9 +++- .../java_client/remote/MobileOptionsTest.java | 6 ++- .../service/local/ServerBuilderTest.java | 20 +++---- .../local/StartingAppLocallyAndroidTest.java | 8 +-- .../local/StartingAppLocallyIosTest.java | 10 ++-- .../service/local/ThreadSafetyTest.java | 8 +-- .../java_client/touch/TouchOptionsTests.java | 16 +++--- 69 files changed, 429 insertions(+), 424 deletions(-) delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ExtendedWidgetTest.java diff --git a/build.gradle b/build.gradle index 016aeaefe..eee2cdf67 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.slf4j:slf4j-api:1.7.36' - testImplementation 'junit:junit:4.13.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.1') { exclude group: 'org.seleniumhq.selenium' @@ -192,7 +192,7 @@ processResources { } task xcuiTest( type: Test ) { - useJUnit() + useJUnitPlatform() testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { @@ -207,7 +207,7 @@ task xcuiTest( type: Test ) { } task uiAutomationTest( type: Test ) { - useJUnit() + useJUnitPlatform() testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { @@ -223,7 +223,7 @@ task uiAutomationTest( type: Test ) { } task miscTest( type: Test ) { - useJUnit() + useJUnitPlatform() testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index 0626c4f9d..38fa40b93 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -4,12 +4,12 @@ import static io.appium.java_client.touch.WaitOptions.waitOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import io.appium.java_client.AppiumBy; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; diff --git a/src/test/java/io/appium/java_client/android/AndroidActivityTest.java b/src/test/java/io/appium/java_client/android/AndroidActivityTest.java index 0acfd0b49..86377ac11 100644 --- a/src/test/java/io/appium/java_client/android/AndroidActivityTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidActivityTest.java @@ -16,16 +16,16 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import io.appium.java_client.android.nativekey.AndroidKey; import io.appium.java_client.android.nativekey.KeyEvent; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class AndroidActivityTest extends BaseAndroidTest { - @Before public void setUp() { + @BeforeEach public void setUp() { Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); driver.startActivity(activity); } diff --git a/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java b/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java index 87eafb978..9aaeb88b3 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java @@ -16,9 +16,9 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class AndroidAppStringsTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java b/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java index f1eb1043a..88e1c1d6e 100644 --- a/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java @@ -16,16 +16,16 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.android.connection.ConnectionState; import io.appium.java_client.android.connection.ConnectionStateBuilder; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.MethodName.class) public class AndroidConnectionTest extends BaseAndroidTest { @Test diff --git a/src/test/java/io/appium/java_client/android/AndroidContextTest.java b/src/test/java/io/appium/java_client/android/AndroidContextTest.java index 60e423fe8..57f5895d8 100644 --- a/src/test/java/io/appium/java_client/android/AndroidContextTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidContextTest.java @@ -16,15 +16,16 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import io.appium.java_client.NoSuchContextException; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class AndroidContextTest extends BaseAndroidTest { - @BeforeClass public static void beforeClass2() throws Exception { + @BeforeAll public static void beforeClass2() throws Exception { Activity activity = new Activity("io.appium.android.apis", ".view.WebView1"); driver.startActivity(activity); Thread.sleep(20000); @@ -46,9 +47,12 @@ public class AndroidContextTest extends BaseAndroidTest { assertEquals(driver.getContext(), "NATIVE_APP"); } - @Test(expected = NoSuchContextException.class) public void testContextError() { - driver.context("Planet of the Ape-ium"); - assertEquals("Planet of the Ape-ium", driver.getContext()); + @Test public void testContextError() { + assertThrows(NoSuchContextException.class, + () -> { + driver.context("Planet of the Ape-ium"); + assertEquals("Planet of the Ape-ium", driver.getContext()); + }); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java index afe0b7653..3db8ade05 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java @@ -19,14 +19,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.json.Json; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class AndroidDataMatcherTest extends BaseEspressoTest { diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index c94669138..145bd32dc 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -16,21 +16,21 @@ package io.appium.java_client.android; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.lessThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import io.appium.java_client.appmanagement.ApplicationState; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.hamcrest.Matchers; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.html5.Location; diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java index 911dd8150..8ce9fd2fc 100644 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidElementTest.java @@ -16,20 +16,20 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import io.appium.java_client.AppiumBy; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; public class AndroidElementTest extends BaseAndroidTest { - @Before public void setup() { + @BeforeEach public void setup() { Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); driver.startActivity(activity); } diff --git a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java index e86a58c05..735d0aeda 100644 --- a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java @@ -2,16 +2,17 @@ import static java.time.Duration.ofMillis; import static java.time.Duration.ofSeconds; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.functions.AppiumFunction; import io.appium.java_client.functions.ExpectedCondition; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; @@ -65,7 +66,7 @@ public class AndroidFunctionTest extends BaseAndroidTest { return null; }; - @BeforeClass + @BeforeAll public static void startWebViewActivity() { if (driver != null) { Activity activity = new Activity("io.appium.android.apis", ".view.WebView1"); @@ -73,7 +74,7 @@ public static void startWebViewActivity() { } } - @Before + @BeforeEach public void setUp() { driver.context("NATIVE_APP"); @@ -127,17 +128,19 @@ public void complexWaitingTestWithPreCondition() { assertThat("There should be 3 calls", calls.size(), is(3)); } - @Test(expected = TimeoutException.class) + @Test public void nullPointerExceptionSafetyTestWithPrecondition() { Wait wait = new FluentWait<>(Pattern.compile("Fake_context")) .withTimeout(ofSeconds(30)).pollingEvery(ofMillis(500)); - assertTrue(wait.until(searchingFunction.compose(contextFunction)).size() > 0); + assertThrows(TimeoutException.class, + () -> assertTrue(wait.until(searchingFunction.compose(contextFunction)).size() > 0)); } - @Test(expected = TimeoutException.class) + @Test public void nullPointerExceptionSafetyTestWithPostConditions() { Wait wait = new FluentWait<>(Pattern.compile("Fake_context")) .withTimeout(ofSeconds(30)).pollingEvery(ofMillis(500)); - assertTrue(wait.until(contextFunction.andThen(searchingFunction).andThen(filteringFunction)).size() > 0); + assertThrows(TimeoutException.class, + () -> assertTrue(wait.until(contextFunction.andThen(searchingFunction).andThen(filteringFunction)).size() > 0)); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java b/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java index 5cfdee5c2..f1045c8cf 100644 --- a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java @@ -1,9 +1,9 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.commons.lang3.time.DurationFormatUtils; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.time.Duration; import java.util.concurrent.Semaphore; @@ -25,9 +25,9 @@ public void verifyLogcatListenerCanBeAssigned() { messageSemaphore.acquire(); // This is needed for pushing some internal log messages driver.runAppInBackground(Duration.ofSeconds(1)); - assertTrue(String.format("Didn't receive any log message after %s timeout", - DurationFormatUtils.formatDuration(timeout.toMillis(), "H:mm:ss", true)), - messageSemaphore.tryAcquire(timeout.toMillis(), TimeUnit.MILLISECONDS)); + assertTrue(messageSemaphore.tryAcquire(timeout.toMillis(), TimeUnit.MILLISECONDS), + String.format("Didn't receive any log message after %s timeout", + DurationFormatUtils.formatDuration(timeout.toMillis(), "H:mm:ss", true))); } catch (InterruptedException e) { throw new IllegalStateException(e); } finally { diff --git a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java b/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java index be34c67b9..63510fc26 100644 --- a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java @@ -5,15 +5,15 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriverException; import java.time.Duration; public class AndroidScreenRecordTest extends BaseAndroidTest { - @Before + @BeforeEach public void setUp() { Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); driver.startActivity(activity); diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index e96ac64e7..262b50c61 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -16,19 +16,19 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import io.appium.java_client.AppiumBy; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; public class AndroidSearchingTest extends BaseAndroidTest { - @Before + @BeforeEach public void setup() { Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); driver.startActivity(activity); diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index e03485bbf..958da3140 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -7,15 +7,15 @@ import static io.appium.java_client.touch.offset.ElementOption.element; import static io.appium.java_client.touch.offset.PointOption.point; import static java.time.Duration.ofSeconds; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import io.appium.java_client.AppiumBy; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; @@ -24,7 +24,7 @@ public class AndroidTouchTest extends BaseAndroidTest { - @Before + @BeforeEach public void setUp() { driver.resetApp(); } diff --git a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java index 191055553..852723694 100644 --- a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java @@ -19,14 +19,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.json.Json; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class AndroidViewMatcherTest extends BaseEspressoTest { diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index b6a4e5421..3e75fe6f1 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -20,8 +20,8 @@ import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import static io.appium.java_client.TestResources.apiDemosApk; @@ -35,7 +35,7 @@ public class BaseAndroidTest { /** * initialization. */ - @BeforeClass public static void beforeClass() { + @BeforeAll public static void beforeClass() { service = new AppiumServiceBuilder() .withIPAddress("127.0.0.1") .usingPort(PORT) @@ -52,7 +52,7 @@ public class BaseAndroidTest { /** * finishing. */ - @AfterClass public static void afterClass() { + @AfterAll public static void afterClass() { if (driver != null) { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java index 6375ff58e..cfc690021 100644 --- a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java +++ b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java @@ -19,8 +19,8 @@ import io.appium.java_client.android.options.EspressoOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import static io.appium.java_client.TestResources.apiDemosApk; @@ -32,7 +32,7 @@ public class BaseEspressoTest { /** * initialization. */ - @BeforeClass public static void beforeClass() { + @BeforeAll public static void beforeClass() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); @@ -51,7 +51,7 @@ public class BaseEspressoTest { /** * finishing. */ - @AfterClass public static void afterClass() { + @AfterAll public static void afterClass() { if (driver != null) { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/android/BatteryTest.java b/src/test/java/io/appium/java_client/android/BatteryTest.java index a48ecc092..619fafac1 100644 --- a/src/test/java/io/appium/java_client/android/BatteryTest.java +++ b/src/test/java/io/appium/java_client/android/BatteryTest.java @@ -21,7 +21,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class BatteryTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/ClipboardTest.java b/src/test/java/io/appium/java_client/android/ClipboardTest.java index 0e58ae3b6..cf9ee8581 100644 --- a/src/test/java/io/appium/java_client/android/ClipboardTest.java +++ b/src/test/java/io/appium/java_client/android/ClipboardTest.java @@ -16,14 +16,14 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class ClipboardTest extends BaseAndroidTest { - @Before public void setUp() { + @BeforeEach public void setUp() { driver.resetApp(); } 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 634a9a516..fc1a138c6 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -20,9 +20,9 @@ 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.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; @@ -34,7 +34,7 @@ import java.util.Map; import static java.time.Duration.ofSeconds; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class ExecuteCDPCommandTest { @@ -49,7 +49,7 @@ public class ExecuteCDPCommandTest { /** * The setting up. */ - @Before + @BeforeEach public void setUp() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); @@ -66,7 +66,7 @@ public void setUp() { /** * finishing. */ - @After + @AfterEach public void tearDown() { if (driver != null) { driver.quit(); diff --git a/src/test/java/io/appium/java_client/android/ExecuteDriverScriptTest.java b/src/test/java/io/appium/java_client/android/ExecuteDriverScriptTest.java index 5b8da2938..d8bf5a65d 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteDriverScriptTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteDriverScriptTest.java @@ -19,16 +19,16 @@ import io.appium.java_client.driverscripts.ScriptOptions; import io.appium.java_client.driverscripts.ScriptType; import io.appium.java_client.driverscripts.ScriptValue; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class ExecuteDriverScriptTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java index 42d696b58..a32c482fe 100644 --- a/src/test/java/io/appium/java_client/android/FingerPrintTest.java +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -20,12 +20,12 @@ import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; @@ -48,7 +48,7 @@ private static void initDriver() { /** * initialization. */ - @BeforeClass public static void beforeClass() { + @BeforeAll public static void beforeClass() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); @@ -60,7 +60,7 @@ private static void initDriver() { /** * finishing. */ - @AfterClass public static void afterClass() { + @AfterAll public static void afterClass() { if (service != null) { service.stop(); } @@ -98,7 +98,7 @@ private void clickOnSecurity() { /** * enable system security which is required for finger print activation. */ - @Before + @BeforeEach public void before() { initDriver(); clickOnSecurity(); @@ -123,14 +123,14 @@ public void fingerPrintTest() { try { clickNext(); } catch (Exception e) { - Assert.fail("fingerprint command fail to execute"); + Assertions.fail("fingerprint command fail to execute"); } } /** * disabling pin lock mode. */ - @After + @AfterEach public void after() { driver.quit(); diff --git a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java b/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java index 388b32cf1..adc8795ea 100644 --- a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java +++ b/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java @@ -16,11 +16,11 @@ package io.appium.java_client.android; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import io.appium.java_client.imagecomparison.FeatureDetector; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; @@ -31,7 +31,7 @@ import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; import org.apache.commons.codec.binary.Base64; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.OutputType; public class ImagesComparisonTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/IntentTest.java b/src/test/java/io/appium/java_client/android/IntentTest.java index ea10811e6..a25e6a0bf 100644 --- a/src/test/java/io/appium/java_client/android/IntentTest.java +++ b/src/test/java/io/appium/java_client/android/IntentTest.java @@ -1,14 +1,14 @@ package io.appium.java_client.android; import static io.appium.java_client.TestResources.intentExampleApk; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import java.util.function.Predicate; @@ -20,7 +20,7 @@ public class IntentTest { /** * initialization. */ - @BeforeClass public static void beforeClass() { + @BeforeAll public static void beforeClass() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); @@ -37,7 +37,7 @@ public class IntentTest { /** * finishing. */ - @AfterClass public static void afterClass() { + @AfterAll public static void afterClass() { if (driver != null) { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/android/KeyCodeTest.java b/src/test/java/io/appium/java_client/android/KeyCodeTest.java index 9a6b8ed1e..7a3ae47e3 100644 --- a/src/test/java/io/appium/java_client/android/KeyCodeTest.java +++ b/src/test/java/io/appium/java_client/android/KeyCodeTest.java @@ -16,22 +16,22 @@ package io.appium.java_client.android; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.android.nativekey.AndroidKey; import io.appium.java_client.android.nativekey.KeyEvent; import io.appium.java_client.android.nativekey.KeyEventFlag; import io.appium.java_client.android.nativekey.KeyEventMetaModifier; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; public class KeyCodeTest extends BaseAndroidTest { private static final By PRESS_RESULT_VIEW = By.id("io.appium.android.apis:id/text"); - @Before + @BeforeEach public void setUp() { final Activity activity = new Activity(driver.getCurrentPackage(), ".text.KeyEventText"); driver.startActivity(activity); diff --git a/src/test/java/io/appium/java_client/android/LogEventTest.java b/src/test/java/io/appium/java_client/android/LogEventTest.java index ab4b0350a..a473fbe32 100644 --- a/src/test/java/io/appium/java_client/android/LogEventTest.java +++ b/src/test/java/io/appium/java_client/android/LogEventTest.java @@ -16,15 +16,15 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.serverevents.CommandEvent; import io.appium.java_client.serverevents.CustomEvent; import io.appium.java_client.serverevents.TimedEvent; import io.appium.java_client.serverevents.ServerEvents; import org.hamcrest.Matchers; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class LogEventTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index 293479e53..dde09bbc1 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -1,10 +1,9 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.openqa.selenium.By.id; -import org.junit.Test; - +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; diff --git a/src/test/java/io/appium/java_client/android/SettingTest.java b/src/test/java/io/appium/java_client/android/SettingTest.java index 52963e566..380efa1cb 100644 --- a/src/test/java/io/appium/java_client/android/SettingTest.java +++ b/src/test/java/io/appium/java_client/android/SettingTest.java @@ -1,14 +1,14 @@ package io.appium.java_client.android; import io.appium.java_client.Setting; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.time.Duration; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class SettingTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java index 85b91ab30..6c2bf0857 100644 --- a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java +++ b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java @@ -1,12 +1,12 @@ package io.appium.java_client.android; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import io.appium.java_client.AppiumBy; -import org.junit.After; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.DeviceRotation; import org.openqa.selenium.WebElement; @@ -17,7 +17,7 @@ public class UIAutomator2Test extends BaseAndroidTest { - @After + @AfterEach public void afterMethod() { driver.rotate(new DeviceRotation(0, 0, 0)); } @@ -55,7 +55,8 @@ public void testPortraitUpsideDown() { /** * ignoring. */ - @Ignore + @Disabled + @Test public void testToastMSGIsDisplayed() { final WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); Activity activity = new Activity("io.appium.android.apis", ".view.PopupMenu1"); diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java index 8b842ee32..ab10f1ec1 100644 --- a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -35,17 +35,17 @@ import io.appium.java_client.safari.options.WebrtcData; import io.appium.java_client.windows.options.PowerShellData; import io.appium.java_client.windows.options.WindowsOptions; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.Platform; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; @SuppressWarnings("ConstantConditions") public class OptionsBuildingTest { diff --git a/src/test/java/io/appium/java_client/events/EventsFiringTest.java b/src/test/java/io/appium/java_client/events/EventsFiringTest.java index f6d0d2890..cd00dce37 100644 --- a/src/test/java/io/appium/java_client/events/EventsFiringTest.java +++ b/src/test/java/io/appium/java_client/events/EventsFiringTest.java @@ -17,20 +17,20 @@ package io.appium.java_client.events; import io.appium.java_client.events.stubs.EmptyWebDriver; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.events.EventFiringDecorator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class EventsFiringTest { private final WebDriver emptyWebDriver = new EmptyWebDriver(); private CustomListener listener; private WebDriver decorated; - @Before + @BeforeEach public void beforeTest() { listener = new CustomListener(); decorated = new EventFiringDecorator(listener).decorate(emptyWebDriver); diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index d9185dc5f..4ae2feb6c 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -2,10 +2,11 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class ConfigTest { private static final String EXISTING_KEY = "selenium.version"; @@ -17,14 +18,16 @@ public void verifyGettingExistingValue() { assertTrue(Config.main().getOptionalValue(EXISTING_KEY, String.class).isPresent()); } - @Test(expected = IllegalArgumentException.class) + @Test public void verifyGettingNonExistingValue() { - assertThat(Config.main().getValue(MISSING_KEY, String.class).length(), greaterThan(0)); + assertThrows(IllegalArgumentException.class, + () -> assertThat(Config.main().getValue(MISSING_KEY, String.class).length(), greaterThan(0))); } - @Test(expected = ClassCastException.class) + @Test public void verifyGettingExistingValueWithWrongClass() { - assertThat(Config.main().getValue(EXISTING_KEY, Integer.class), greaterThan(0)); + assertThrows(ClassCastException.class, + () -> assertThat(Config.main().getValue(EXISTING_KEY, Integer.class), greaterThan(0))); } @Test diff --git a/src/test/java/io/appium/java_client/ios/AppIOSTest.java b/src/test/java/io/appium/java_client/ios/AppIOSTest.java index e84ae96fa..b049a15bb 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/AppIOSTest.java @@ -1,7 +1,7 @@ package io.appium.java_client.ios; import io.appium.java_client.ios.options.XCUITestOptions; -import org.junit.BeforeClass; +import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.SessionNotCreatedException; import java.time.Duration; @@ -12,7 +12,7 @@ public class AppIOSTest extends BaseIOSTest { public static final String BUNDLE_ID = "io.appium.TestApp"; - @BeforeClass + @BeforeAll public static void beforeClass() throws Exception { startAppiumServer(); @@ -29,4 +29,4 @@ public static void beforeClass() throws Exception { driver = new IOSDriver(service.getUrl(), options); } } -} \ No newline at end of file +} diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index 2f4d1f5f1..dfdf3c4da 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -18,7 +18,7 @@ import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; -import org.junit.AfterClass; +import org.junit.jupiter.api.AfterAll; import java.time.Duration; @@ -52,7 +52,7 @@ public static AppiumDriverLocalService startAppiumServer() { /** * finishing. */ - @AfterClass public static void afterClass() { + @AfterAll public static void afterClass() { if (driver != null) { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 7aed47831..c461ded8a 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -17,7 +17,7 @@ package io.appium.java_client.ios; import io.appium.java_client.ios.options.XCUITestOptions; -import org.junit.BeforeClass; +import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.SessionNotCreatedException; import java.io.IOException; @@ -30,7 +30,7 @@ public class BaseIOSWebViewTest extends BaseIOSTest { private static final Duration WEB_VIEW_DETECT_INTERVAL = Duration.ofSeconds(1); private static final Duration WEB_VIEW_DETECT_DURATION = Duration.ofSeconds(15); - @BeforeClass + @BeforeAll public static void beforeClass() throws IOException { startAppiumServer(); diff --git a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java index 4204cff41..654c4e58b 100644 --- a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseSafariTest.java @@ -18,13 +18,13 @@ import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.MobileBrowserType; -import org.junit.BeforeClass; +import org.junit.jupiter.api.BeforeAll; import java.io.IOException; public class BaseSafariTest extends BaseIOSTest { - @BeforeClass public static void beforeClass() throws IOException { + @BeforeAll public static void beforeClass() throws IOException { startAppiumServer(); XCUITestOptions options = new XCUITestOptions() diff --git a/src/test/java/io/appium/java_client/ios/ClipboardTest.java b/src/test/java/io/appium/java_client/ios/ClipboardTest.java index ac7618fd8..af6b8a51d 100644 --- a/src/test/java/io/appium/java_client/ios/ClipboardTest.java +++ b/src/test/java/io/appium/java_client/ios/ClipboardTest.java @@ -16,9 +16,9 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class ClipboardTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java index 8fa3afd13..3c731e007 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java @@ -16,16 +16,16 @@ package io.appium.java_client.ios; -import static junit.framework.TestCase.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; import io.appium.java_client.AppiumBy; import org.apache.commons.lang3.StringUtils; -import org.junit.After; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.support.ui.WebDriverWait; @@ -33,7 +33,7 @@ import java.time.Duration; import java.util.function.Supplier; -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.MethodName.class) public class IOSAlertTest extends AppIOSTest { private static final Duration ALERT_TIMEOUT = Duration.ofSeconds(5); @@ -63,7 +63,7 @@ private void ensureAlertPresence() { } } - @After + @AfterEach public void afterEach() { try { driver.switchTo().alert().accept(); diff --git a/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java b/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java index d1cb976d0..6080737f8 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java @@ -16,9 +16,9 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class IOSAppStringsTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/IOSContextTest.java b/src/test/java/io/appium/java_client/ios/IOSContextTest.java index 369ea3292..57915a1f7 100644 --- a/src/test/java/io/appium/java_client/ios/IOSContextTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSContextTest.java @@ -16,12 +16,13 @@ package io.appium.java_client.ios; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import io.appium.java_client.NoSuchContextException; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class IOSContextTest extends BaseIOSWebViewTest { @@ -40,8 +41,11 @@ public class IOSContextTest extends BaseIOSWebViewTest { driver.context("NATIVE_APP"); } - @Test(expected = NoSuchContextException.class) public void testContextError() { - driver.context("Planet of the Ape-ium"); - assertEquals("Planet of the Ape-ium", driver.getContext()); + @Test public void testContextError() { + assertThrows(NoSuchContextException.class, + () -> { + driver.context("Planet of the Ape-ium"); + assertEquals("Planet of the Ape-ium", driver.getContext()); + }); } } diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index f06e5b882..bcfd41d7d 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -19,18 +19,18 @@ import static io.appium.java_client.TestUtils.waitUntilTrue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.remote.HideKeyboardStrategy; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebElement; @@ -44,7 +44,7 @@ import java.time.Duration; public class IOSDriverTest extends AppIOSTest { - @Before + @BeforeEach public void setupEach() { if (driver.queryAppState(BUNDLE_ID).ordinal() < ApplicationState.RUNNING_IN_FOREGROUND.ordinal()) { driver.activateApp(BUNDLE_ID); @@ -94,7 +94,7 @@ public void getDeviceTimeTest() { driver.hideKeyboard(HideKeyboardStrategy.PRESS_KEY, "Done"); } - @Ignore + @Disabled @Test public void geolocationTest() { Location location = new Location(45, 45, 100); try { @@ -132,7 +132,7 @@ public void getDeviceTimeTest() { assertTrue(driver.isKeyboardShown()); } - @Ignore("The app crashes when restored from the background") + @Disabled("The app crashes when restored from the background") @Test public void putAppIntoBackgroundAndRestoreTest() { final long msStarted = System.currentTimeMillis(); @@ -140,7 +140,7 @@ public void putAppIntoBackgroundAndRestoreTest() { assertThat(System.currentTimeMillis() - msStarted, greaterThan(3000L)); } - @Ignore("The app crashes when restored from the background") + @Disabled("The app crashes when restored from the background") @Test public void applicationsManagementTest() { driver.runAppInBackground(Duration.ofSeconds(-1)); @@ -153,7 +153,7 @@ public void applicationsManagementTest() { Duration.ofSeconds(10), Duration.ofSeconds(1)); } - @Ignore("The app crashes when restored from the background") + @Disabled("The app crashes when restored from the background") @Test public void putAIntoBackgroundWithoutRestoreTest() { waitUntilTrue(() -> !driver.findElements(By.id("IntegerA")).isEmpty(), @@ -164,7 +164,7 @@ public void putAIntoBackgroundWithoutRestoreTest() { driver.activateApp(BUNDLE_ID); } - @Ignore + @Disabled @Test public void touchIdTest() { driver.toggleTouchIDEnrollment(true); driver.performTouchID(true); diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index ca57c4cb4..18db02e2b 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -3,12 +3,12 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.FixMethodOrder; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; @@ -16,7 +16,7 @@ import java.time.Duration; -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.MethodName.class) public class IOSElementTest extends AppIOSTest { @Test @@ -25,7 +25,7 @@ public void findByAccessibilityIdTest() { } // FIXME: Stabilize the test on CI - @Ignore + @Disabled @Test public void setValueTest() { WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20)); diff --git a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java b/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java index 67f388d34..e4d27f327 100644 --- a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java @@ -1,11 +1,11 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.Duration; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -14,7 +14,7 @@ public class IOSNativeWebTapSettingTest extends BaseSafariTest { @Test - @Ignore("https://github.com/appium/appium/issues/17014") + @Disabled("https://github.com/appium/appium/issues/17014") public void nativeWebTapSettingTest() { assertTrue(driver.isBrowser()); driver.get("https://saucelabs.com/test/guinea-pig"); diff --git a/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java b/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java index 5657b1ff2..cf88b7b4a 100644 --- a/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java @@ -5,7 +5,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.time.Duration; diff --git a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java b/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java index a90196bbe..30213f480 100644 --- a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java @@ -16,9 +16,9 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.appium.java_client.AppiumBy; diff --git a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java b/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java index ce627e8f9..d5e2b377f 100644 --- a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java @@ -1,9 +1,9 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.commons.lang3.time.DurationFormatUtils; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.time.Duration; import java.util.concurrent.Semaphore; @@ -25,9 +25,9 @@ public void verifySyslogListenerCanBeAssigned() { messageSemaphore.acquire(); // This is needed for pushing some internal log messages driver.runAppInBackground(Duration.ofSeconds(1)); - assertTrue(String.format("Didn't receive any log message after %s timeout", - DurationFormatUtils.formatDuration(timeout.toMillis(), "H:mm:ss", true)), - messageSemaphore.tryAcquire(timeout.toMillis(), TimeUnit.MILLISECONDS)); + assertTrue(messageSemaphore.tryAcquire(timeout.toMillis(), TimeUnit.MILLISECONDS), + String.format("Didn't receive any log message after %s timeout", + DurationFormatUtils.formatDuration(timeout.toMillis(), "H:mm:ss", true))); } catch (InterruptedException e) { throw new IllegalStateException(e); } finally { diff --git a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java index dab6dde45..46a4d0474 100644 --- a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java @@ -5,22 +5,22 @@ import static io.appium.java_client.touch.WaitOptions.waitOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofMillis; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; import io.appium.java_client.AppiumBy; import io.appium.java_client.MultiTouchAction; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.MethodName.class) public class IOSTouchTest extends AppIOSTest { @Test diff --git a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java index 4afb89cd1..d03f1acdc 100644 --- a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java @@ -1,11 +1,11 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.Duration; import io.appium.java_client.AppiumBy; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; diff --git a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java b/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java index b3bbcf0c2..ef52196b5 100644 --- a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java +++ b/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java @@ -16,11 +16,11 @@ package io.appium.java_client.ios; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import io.appium.java_client.imagecomparison.FeatureDetector; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; @@ -31,7 +31,7 @@ import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; import org.apache.commons.codec.binary.Base64; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.OutputType; public class ImagesComparisonTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/RotationTest.java b/src/test/java/io/appium/java_client/ios/RotationTest.java index 7e65b12b7..21d177fff 100644 --- a/src/test/java/io/appium/java_client/ios/RotationTest.java +++ b/src/test/java/io/appium/java_client/ios/RotationTest.java @@ -16,15 +16,15 @@ package io.appium.java_client.ios; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.After; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.DeviceRotation; public class RotationTest extends AppIOSTest { - @After public void afterMethod() { + @AfterEach public void afterMethod() { driver.rotate(new DeviceRotation(0, 0, 0)); } diff --git a/src/test/java/io/appium/java_client/ios/SettingTest.java b/src/test/java/io/appium/java_client/ios/SettingTest.java index 9d0fbcf80..9fc2bfa4b 100644 --- a/src/test/java/io/appium/java_client/ios/SettingTest.java +++ b/src/test/java/io/appium/java_client/ios/SettingTest.java @@ -18,9 +18,9 @@ import io.appium.java_client.Setting; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.EnumMap; import java.util.HashMap; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index 56c423ab4..c183c44e0 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -18,10 +18,11 @@ import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static java.time.Duration.ofSeconds; -import static junit.framework.TestCase.assertNotNull; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.android.BaseAndroidTest; @@ -31,8 +32,8 @@ import io.appium.java_client.pagefactory.AndroidFindBys; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; import org.openqa.selenium.WrapsDriver; @@ -221,7 +222,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { /** * The setting up. */ - @Before public void setUp() { + @BeforeEach public void setUp() { if (!populated) { //This time out is set because test can be run on slow Android SDK emulator PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); @@ -323,9 +324,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { assertNotEquals(null, textAndroidId.getAttribute("text")); } - @Test(expected = NoSuchElementException.class) public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy() { - assertNotNull( - elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.getAttribute("text")); + @Test public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy() { + assertThrows(NoSuchElementException.class, + () -> assertNotNull( + elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.getAttribute("text"))); } @Test public void checkThatTestWillNotBeFailedBecauseOfInvalidFindByList() { @@ -347,9 +349,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { assertEquals(((RemoteWebElement) cached).getId(), ((RemoteWebElement) cached).getId()); } - @Test(expected = NoSuchElementException.class) + @Test public void checkThatElementSearchingThrowsExpectedExceptionIfChainedLocatorIsInvalid() { - assertNotNull(elementFoundByInvalidChainedSelector.getAttribute("text")); + assertThrows(NoSuchElementException.class, + () -> assertNotNull(elementFoundByInvalidChainedSelector.getAttribute("text"))); } @Test public void checkThatListSearchingWorksIfChainedLocatorIsInvalid() { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index 81b3be1cf..c2cb1b6f4 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -20,16 +20,16 @@ import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static java.time.Duration.ofSeconds; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; import io.appium.java_client.pagefactory.iOSXCUITFindBy; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; @@ -53,7 +53,7 @@ public class DesktopBrowserCompatibilityTest { /** * The starting. */ - @BeforeClass public static void beforeClass() { + @BeforeAll public static void beforeClass() { chromedriver().setup(); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java index d9f4b6707..dad9d7a18 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java @@ -24,10 +24,10 @@ import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.remote.MobileBrowserType; import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; @@ -58,7 +58,7 @@ public class MobileBrowserCompatibilityTest { /** * The setting up. */ - @Before + @BeforeEach public void setUp() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); @@ -74,7 +74,7 @@ public void setUp() { /** * finishing. */ - @After + @AfterEach public void tearDown() { if (driver != null) { driver.quit(); @@ -91,7 +91,7 @@ public void test() { searchTextField.sendKeys("Hello"); btnG.click(); - Assert.assertNotEquals(0, foundLinks.size()); + Assertions.assertNotEquals(0, foundLinks.size()); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java index ea2300e09..cfba2ba36 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java @@ -24,16 +24,16 @@ import static java.time.Duration.ofSeconds; import static java.time.temporal.ChronoUnit.SECONDS; import static org.apache.commons.lang3.time.DurationFormatUtils.formatDuration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.lessThanOrEqualTo; -import static org.junit.Assert.assertThat; import static org.openqa.selenium.support.PageFactory.initElements; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.WithTimeout; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; @@ -77,7 +77,7 @@ private static String assertionMessage(Duration expectedDuration) { formatDuration(expectedDuration.toMillis(), "H:mm:ss:SSS", true)); } - @BeforeClass + @BeforeAll public static void beforeAll() { chromedriver().setup(); } @@ -85,7 +85,7 @@ public static void beforeAll() { /** * The setting up. */ - @Before public void setUp() { + @BeforeEach public void setUp() { driver = new ChromeDriver(); timeOutDuration = DEFAULT_WAITING_TIMEOUT; initElements(new AppiumFieldDecorator(driver, timeOutDuration), this); @@ -94,7 +94,7 @@ public static void beforeAll() { /** * finishing. */ - @After public void tearDown() { + @AfterEach public void tearDown() { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java index b56f67859..418f35e71 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java @@ -22,25 +22,25 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.ios.AppIOSTest; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; import io.appium.java_client.pagefactory.iOSXCUITFindBy; -import org.junit.Before; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.PageFactory; import java.util.List; -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.MethodName.class) public class XCUITModeTest extends AppIOSTest { private boolean populated = false; @@ -91,7 +91,7 @@ public class XCUITModeTest extends AppIOSTest { /** * The setting up. */ - @Before public void setUp() { + @BeforeEach public void setUp() { if (!populated) { PageFactory.initElements(new AppiumFieldDecorator(driver), this); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ExtendedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ExtendedWidgetTest.java deleted file mode 100644 index d8d3a7b60..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ExtendedWidgetTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.appium.java_client.pagefactory_tests.widget.tests; - -import static java.util.stream.Collectors.toList; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; - -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; - -import java.util.List; - -public abstract class ExtendedWidgetTest extends WidgetTest { - - protected ExtendedWidgetTest(ExtendedApp app, WebDriver driver) { - super(app, driver); - } - - @Test - public abstract void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation(); - - @Test - public abstract void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass(); - - @Test - public abstract void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations(); - - protected static void checkThatLocatorsAreCreatedCorrectly(DefaultStubWidget single, - List multiple, By rootLocator, - By subLocator) { - - assertThat(single.toString(), containsString(rootLocator.toString())); - assertThat(multiple.stream().map(DefaultStubWidget::toString).collect(toList()), - contains(containsString(rootLocator.toString()), - containsString(rootLocator.toString()))); - - assertThat(single.getSubWidget().toString(), containsString(subLocator.toString())); - assertThat(single.getSubWidgets().stream().map(Object::toString).collect(toList()), - contains(containsString(subLocator.toString()), - containsString(subLocator.toString()))); - - assertThat(multiple.stream().map(abstractWidget -> abstractWidget.getSubWidget().toString()).collect(toList()), - contains(containsString(subLocator.toString()), - containsString(subLocator.toString()))); - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java index 6ef019438..0420d44f6 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java @@ -1,20 +1,22 @@ package io.appium.java_client.pagefactory_tests.widget.tests; -import static java.util.Arrays.copyOf; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; import static org.openqa.selenium.support.PageFactory.initElements; import io.appium.java_client.pagefactory.AppiumFieldDecorator; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; +import java.util.List; + public abstract class WidgetTest { protected final AbstractApp app; - protected static Object[] dataArray(Object...objects) { - return copyOf(objects, objects.length); - } - protected WidgetTest(AbstractApp app, WebDriver driver) { this.app = app; initElements(new AppiumFieldDecorator(driver), app); @@ -22,4 +24,32 @@ protected WidgetTest(AbstractApp app, WebDriver driver) { @Test public abstract void checkThatWidgetsAreCreatedCorrectly(); + + @Test + public abstract void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation(); + + @Test + public abstract void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass(); + + @Test + public abstract void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations(); + + protected static void checkThatLocatorsAreCreatedCorrectly(DefaultStubWidget single, + List multiple, By rootLocator, + By subLocator) { + + assertThat(single.toString(), containsString(rootLocator.toString())); + assertThat(multiple.stream().map(DefaultStubWidget::toString).collect(toList()), + contains(containsString(rootLocator.toString()), + containsString(rootLocator.toString()))); + + assertThat(single.getSubWidget().toString(), containsString(subLocator.toString())); + assertThat(single.getSubWidgets().stream().map(Object::toString).collect(toList()), + contains(containsString(subLocator.toString()), + containsString(subLocator.toString()))); + + assertThat(multiple.stream().map(abstractWidget -> abstractWidget.getSubWidget().toString()).collect(toList()), + contains(containsString(subLocator.toString()), + containsString(subLocator.toString()))); + } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java index 93047222b..a3eee515a 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java @@ -8,20 +8,23 @@ import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedWidgetTest; +import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; +import org.junit.jupiter.api.Test; -public class AndroidWidgetTest extends ExtendedWidgetTest { +public class AndroidWidgetTest extends WidgetTest { public AndroidWidgetTest() { super(new AndroidApp(), new AbstractStubWebDriver.StubAndroidDriver()); } + @Test @Override public void checkThatWidgetsAreCreatedCorrectly() { checkThatLocatorsAreCreatedCorrectly(app.getWidget(), app.getWidgets(), androidUIAutomator(ANDROID_DEFAULT_WIDGET_LOCATOR), androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getAnnotatedWidget(), @@ -29,6 +32,7 @@ public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { androidUIAutomator(ANDROID_ROOT_WIDGET_LOCATOR), androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidget(), @@ -36,6 +40,7 @@ public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() androidUIAutomator(ANDROID_ROOT_WIDGET_LOCATOR), androidUIAutomator(ANDROID_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidgetWithOverriddenLocators(), diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index 9953578be..8c93632ec 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -1,66 +1,60 @@ package io.appium.java_client.pagefactory_tests.widget.tests.combined; -import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; +import static org.openqa.selenium.support.PageFactory.initElements; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.OverrideWidget; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractApp; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; -import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.openqa.selenium.WebDriver; -import java.util.Collection; import java.util.List; +import java.util.stream.Stream; @SuppressWarnings({"unused", "unchecked"}) -@RunWith(Parameterized.class) -public class CombinedAppTest extends WidgetTest { - - private final Class widgetClass; +public class CombinedAppTest { /** * Test data generation. * * @return test parameters */ - @Parameterized.Parameters - public static Collection data() { - return asList( - dataArray(new CombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - dataArray(new CombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), + public static Stream data() { + return Stream.of( + Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), + Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultIosXCUITWidget.class), - dataArray(new CombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), - dataArray(new CombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), - dataArray(new CombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), + Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), + Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), + Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class), - dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), + Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), + Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultStubWidget.class), - dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), + Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultStubWidget.class), - dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), + Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), - dataArray(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), + Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class) ); } - public CombinedAppTest(AbstractApp app, WebDriver driver, Class widgetClass) { - super(app, driver); - this.widgetClass = widgetClass; - } - - @Override - public void checkThatWidgetsAreCreatedCorrectly() { + @ParameterizedTest + @MethodSource("data") + public void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { + initElements(new AppiumFieldDecorator(driver), app); assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSelfReference().getClass(), equalTo(widgetClass)); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java index cbae48bcc..1d686c58e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java @@ -1,72 +1,66 @@ package io.appium.java_client.pagefactory_tests.widget.tests.combined; -import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; +import static org.openqa.selenium.support.PageFactory.initElements; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.OverrideWidget; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractApp; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; -import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import java.util.ArrayList; -import java.util.Collection; import java.util.List; +import java.util.stream.Stream; @SuppressWarnings({"unchecked", "unused"}) -@RunWith(Parameterized.class) -public class CombinedWidgetTest extends WidgetTest { - - private final Class widgetClass; +public class CombinedWidgetTest { /** * Test data generation. * * @return test parameters */ - @Parameterized.Parameters - public static Collection data() { - return asList( - dataArray(new AppWithCombinedWidgets(), + public static Stream data() { + return Stream.of( + Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - dataArray(new AppWithCombinedWidgets(), + Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultIosXCUITWidget.class), - dataArray(new AppWithCombinedWidgets(), + Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), - dataArray(new AppWithCombinedWidgets(), + Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), - dataArray(new AppWithCombinedWidgets(), + Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class), - dataArray(new AppWithPartiallyCombinedWidgets(), + Arguments.of(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - dataArray(new AppWithPartiallyCombinedWidgets(), + Arguments.of(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultStubWidget.class), - dataArray(new AppWithPartiallyCombinedWidgets(), + Arguments.of(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultStubWidget.class), - dataArray(new AppWithPartiallyCombinedWidgets(), + Arguments.of(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), - dataArray(new AppWithPartiallyCombinedWidgets(), + Arguments.of(new AppWithPartiallyCombinedWidgets(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class) ); } - public CombinedWidgetTest(AbstractApp app, WebDriver driver, Class widgetClass) { - super(app, driver); - this.widgetClass = widgetClass; - } - - @Override - public void checkThatWidgetsAreCreatedCorrectly() { + @ParameterizedTest + @MethodSource("data") + public void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { + initElements(new AppiumFieldDecorator(driver), app); assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSubWidget().getSelfReference().getClass(), equalTo(widgetClass)); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java index d2e4d483f..6a9bb0d53 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java @@ -8,20 +8,23 @@ import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedWidgetTest; +import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; +import org.junit.jupiter.api.Test; -public class XCUITWidgetTest extends ExtendedWidgetTest { +public class XCUITWidgetTest extends WidgetTest { public XCUITWidgetTest() { super(new IosApp(), new AbstractStubWebDriver.StubIOSXCUITDriver()); } + @Test @Override public void checkThatWidgetsAreCreatedCorrectly() { checkThatLocatorsAreCreatedCorrectly(app.getWidget(), app.getWidgets(), iOSNsPredicateString(IOS_XCUIT_WIDGET_LOCATOR), iOSNsPredicateString(XCUIT_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getAnnotatedWidget(), @@ -29,6 +32,7 @@ public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { iOSNsPredicateString(XCUIT_ROOT_WIDGET_LOCATOR), iOSNsPredicateString(XCUIT_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidget(), @@ -36,6 +40,7 @@ public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() iOSNsPredicateString(XCUIT_ROOT_WIDGET_LOCATOR), iOSNsPredicateString(XCUIT_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidgetWithOverriddenLocators(), diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java index fbd9da9a6..d5990b7e5 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java @@ -8,20 +8,23 @@ import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedWidgetTest; +import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; +import org.junit.jupiter.api.Test; -public class WindowsWidgetTest extends ExtendedWidgetTest { +public class WindowsWidgetTest extends WidgetTest { public WindowsWidgetTest() { super(new WindowsApp(), new AbstractStubWebDriver.StubWindowsDriver()); } + @Test @Override public void checkThatWidgetsAreCreatedCorrectly() { checkThatLocatorsAreCreatedCorrectly(app.getWidget(), app.getWidgets(), windowsAutomation(WINDOWS_DEFAULT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getAnnotatedWidget(), @@ -29,6 +32,7 @@ public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { windowsAutomation(WINDOWS_ROOT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidget(), @@ -36,6 +40,7 @@ public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() windowsAutomation(WINDOWS_ROOT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); } + @Test @Override public void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations() { checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidgetWithOverriddenLocators(), diff --git a/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java b/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java index ab2b776e1..13faeb583 100644 --- a/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java +++ b/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java @@ -16,7 +16,7 @@ package io.appium.java_client.remote; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.ScreenOrientation; @@ -24,7 +24,9 @@ import java.net.URL; import java.time.Duration; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; public class MobileOptionsTest { private MobileOptions mobileOptions = new MobileOptions<>(); diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index 3c3fed15e..fe5b9a3b6 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -16,20 +16,20 @@ import static java.util.Arrays.asList; import static java.util.Optional.ofNullable; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.options.UiAutomator2Options; import io.github.bonigarcia.wdm.WebDriverManager; -import org.junit.After; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import java.io.File; import java.io.FileOutputStream; @@ -67,14 +67,14 @@ public class ServerBuilderTest { /** * initialization. */ - @BeforeClass + @BeforeAll public static void beforeClass() throws Exception { testIP = getLocalIp4Address(); chromeManager = chromedriver(); chromeManager.setup(); } - @After + @AfterEach public void tearDown() throws Exception { ofNullable(service).ifPresent(AppiumDriverLocalService::stop); diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index 34b0e2565..3d248f462 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -23,16 +23,16 @@ import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.github.bonigarcia.wdm.WebDriverManager; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.Capabilities; import java.time.Duration; import static io.appium.java_client.TestResources.apiDemosApk; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class StartingAppLocallyAndroidTest { diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index b7bc4786c..ec629f8ba 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -17,10 +17,10 @@ package io.appium.java_client.service.local; import static io.appium.java_client.TestResources.uiCatalogAppZip; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSDriver; @@ -29,7 +29,7 @@ import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; diff --git a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java b/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java index fa1ba1d5c..50d59a5df 100644 --- a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java +++ b/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java @@ -1,12 +1,12 @@ package io.appium.java_client.service.local; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class ThreadSafetyTest { diff --git a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java index 1500e2f81..b08249962 100644 --- a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java +++ b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java @@ -8,15 +8,15 @@ import static io.appium.java_client.touch.offset.PointOption.point; import static java.time.Duration.ofMillis; import static java.time.Duration.ofSeconds; -import static junit.framework.TestCase.fail; import static org.hamcrest.CoreMatchers.everyItem; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.in; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; import io.appium.java_client.touch.offset.ElementOption; import io.appium.java_client.touch.offset.PointOption; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.openqa.selenium.Point; import org.openqa.selenium.remote.RemoteWebElement; @@ -28,16 +28,16 @@ public class TouchOptionsTests { private static final RemoteWebElement DUMMY_ELEMENT = new DummyElement(); - @Test(expected = IllegalArgumentException.class) + @Test public void invalidEmptyPointOptionsShouldFailOnBuild() { - new PointOption<>().build(); - fail("The exception throwing was expected"); + assertThrows(IllegalArgumentException.class, + () -> new PointOption<>().build()); } - @Test(expected = IllegalArgumentException.class) + @Test public void invalidEmptyElementOptionsShouldFailOnBuild() { - new ElementOption().build(); - fail("The exception throwing was expected"); + assertThrows(IllegalArgumentException.class, + () -> new ElementOption().build()); } @Test From dcc38b60e8c1fe9098f49eb7cdebb8d3c5d67071 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Aug 2022 08:00:26 +0300 Subject: [PATCH 109/501] build(deps): bump gson from 2.9.0 to 2.9.1 (#1730) Bumps [gson](https://github.com/google/gson) from 2.9.0 to 2.9.1. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.9.0...gson-parent-2.9.1) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index eee2cdf67..523db8b5d 100644 --- a/build.gradle +++ b/build.gradle @@ -49,7 +49,7 @@ dependencies { prefer "${seleniumVersion}" } } - implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.google.code.gson:gson:2.9.1' implementation 'commons-codec:commons-codec:1.15' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' From 0716883a2b43e06ccf573a8f3444f9f7cd7caf2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Aug 2022 09:00:40 +0300 Subject: [PATCH 110/501] build(deps): bump webdrivermanager from 5.2.1 to 5.2.2 (#1729) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.2.1 to 5.2.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.2.1...webdrivermanager-5.2.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 523db8b5d..c67af1618 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.2') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From 938a4db16b9f3f3c724b2f5429c6670465ef41c4 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 5 Aug 2022 13:10:23 -0700 Subject: [PATCH 111/501] feat: Allow to create a driver with ClientConfig (#1735) --- .../io/appium/java_client/AppiumDriver.java | 5 ++++ .../java_client/android/AndroidDriver.java | 24 ++++++++++++++++++ .../appium/java_client/gecko/GeckoDriver.java | 24 ++++++++++++++++++ .../io/appium/java_client/ios/IOSDriver.java | 24 ++++++++++++++++++ .../io/appium/java_client/mac/Mac2Driver.java | 25 +++++++++++++++++++ .../remote/AppiumCommandExecutor.java | 25 +++++++++++++------ .../java_client/safari/SafariDriver.java | 25 +++++++++++++++++++ .../java_client/windows/WindowsDriver.java | 25 +++++++++++++++++++ 8 files changed, 169 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 1616053ac..0f109af2c 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -41,6 +41,7 @@ import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.html5.RemoteLocationContext; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; @@ -83,6 +84,10 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { this.remoteAddress = executor.getAddressOfRemoteServer(); } + public AppiumDriver(ClientConfig clientConfig, Capabilities capabilities) { + this(new AppiumCommandExecutor(MobileCommand.commandRepository, clientConfig), capabilities); + } + public AppiumDriver(URL remoteAddress, Capabilities capabilities) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, remoteAddress), capabilities); 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 741a4b9f9..76810cac3 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -51,6 +51,7 @@ import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.html5.RemoteLocationContext; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -182,6 +183,29 @@ public AndroidDriver(HttpClient.Factory httpClientFactory, Capabilities capabili super(httpClientFactory, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * UiAutomator2Options options = new UiAutomator2Options();
+     * AndroidDriver driver = new AndroidDriver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public AndroidDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, ensurePlatformName(capabilities, ANDROID_PLATFORM)); + } + /** * Creates a new instance based on {@code capabilities}. * diff --git a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java index bd85fcfc9..43d2072c8 100644 --- a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java +++ b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java @@ -22,6 +22,7 @@ import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -73,6 +74,29 @@ public GeckoDriver(HttpClient.Factory httpClientFactory, Capabilities capabiliti super(httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * GeckoOptions options = new GeckoOptions();
+     * GeckoDriver driver = new GeckoDriver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public GeckoDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + public GeckoDriver(Capabilities capabilities) { super(ensureAutomationName(capabilities, AUTOMATION_NAME)); } 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 01a848b87..18ecf3065 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -48,6 +48,7 @@ import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.html5.RemoteLocationContext; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -171,6 +172,29 @@ public IOSDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities super(httpClientFactory, ensurePlatformName(capabilities, PLATFORM_NAME)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * XCUITestOptions options = new XCUITestOptions();
+     * IOSDriver driver = new IOSDriver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public IOSDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, ensurePlatformName(capabilities, PLATFORM_NAME)); + } + /** * Creates a new instance based on {@code capabilities}. * diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index a65497eaa..b76de5943 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -25,6 +25,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -84,6 +85,30 @@ public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities capabilitie capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * Mac2Options options = new Mac2Options();
+     * Mac2Driver driver = new Mac2Driver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public Mac2Driver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + public Mac2Driver(Capabilities capabilities) { super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 463e14c38..01c551fb4 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -62,24 +62,33 @@ public class AppiumCommandExecutor extends HttpCommandExecutor { private AppiumCommandExecutor(Map additionalCommands, DriverService service, URL addressOfRemoteServer, - HttpClient.Factory httpClientFactory) { + HttpClient.Factory httpClientFactory, + ClientConfig clientConfig) { super(additionalCommands, - ClientConfig.defaultConfig() - .baseUrl(Require.nonNull("Server URL", ofNullable(service) - .map(DriverService::getUrl) - .orElse(addressOfRemoteServer))) - .readTimeout(DEFAULT_READ_TIMEOUT), httpClientFactory); + ofNullable(clientConfig).orElse( + ClientConfig.defaultConfig() + .baseUrl(Require.nonNull("Server URL", ofNullable(service) + .map(DriverService::getUrl) + .orElse(addressOfRemoteServer))) + .readTimeout(DEFAULT_READ_TIMEOUT) + ), + ofNullable(httpClientFactory).orElseGet(HttpCommandExecutor::getDefaultClientFactory) + ); serviceOptional = ofNullable(service); } public AppiumCommandExecutor(Map additionalCommands, DriverService service, HttpClient.Factory httpClientFactory) { - this(additionalCommands, checkNotNull(service), null, httpClientFactory); + this(additionalCommands, checkNotNull(service), null, httpClientFactory, null); } public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { - this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory); + this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory, null); + } + + public AppiumCommandExecutor(Map additionalCommands, ClientConfig clientConfig) { + this(additionalCommands, null, checkNotNull(clientConfig.baseUrl()), null, clientConfig); } public AppiumCommandExecutor(Map additionalCommands, diff --git a/src/main/java/io/appium/java_client/safari/SafariDriver.java b/src/main/java/io/appium/java_client/safari/SafariDriver.java index c32d36b05..0b8a8400d 100644 --- a/src/main/java/io/appium/java_client/safari/SafariDriver.java +++ b/src/main/java/io/appium/java_client/safari/SafariDriver.java @@ -23,6 +23,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -81,6 +82,30 @@ public SafariDriver(HttpClient.Factory httpClientFactory, Capabilities capabilit capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * SafariOptions options = new SafariOptions();
+     * SafariDriver driver = new SafariDriver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public SafariDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + public SafariDriver(Capabilities capabilities) { super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 00b21a1ed..82af6e02d 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -28,6 +28,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -79,6 +80,30 @@ public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities capabili capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * WindowsOptions options = new WindowsOptions();
+     * WindowsDriver driver = new WindowsDriver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public WindowsDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + public WindowsDriver(Capabilities capabilities) { super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } From 9340f4fac8ed893e4fc8969e5b0c2642e15fa5b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Aug 2022 15:01:53 +0300 Subject: [PATCH 112/501] build(deps): bump webdrivermanager from 5.2.2 to 5.2.3 (#1737) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.2.2 to 5.2.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.2.2...webdrivermanager-5.2.3) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c67af1618..d0b13a131 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.2') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.3') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From 967f0996018cae4c1297e61bf6bdbcbedd9757dd Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 9 Aug 2022 12:12:42 +0300 Subject: [PATCH 113/501] ci: update Azure pipeline to use `macos-11` VM image (#1728) --- azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9d6f6fc5d..f158f224d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,15 +4,15 @@ # https://docs.microsoft.com/azure/devops/pipelines/languages/java pool: - vmImage: 'macOS-10.15' + vmImage: 'macos-11' variables: ANDROID_EMU_NAME: test ANDROID_EMU_ABI: x86 ANDROID_EMU_TARGET: android-28 ANDROID_EMU_TAG: default - XCODE_VERSION: 11.5 - IOS_PLATFORM_VERSION: 13.5 + XCODE_VERSION: 13.2 + IOS_PLATFORM_VERSION: 15.2 IOS_DEVICE_NAME: iPhone X NODE_VERSION: 16.x JDK_VERSION: 1.8 From 9e759b4d31857d9b17d2deb7835d1eb9b60c83a5 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 10 Aug 2022 16:37:50 +0300 Subject: [PATCH 114/501] fix: Bump minimum required Selenium version to `4.4.0` (#1738) --- gradle.properties | 2 +- .../remote/AppiumW3CHttpCommandCodec.java | 27 ------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/gradle.properties b/gradle.properties index 62048789f..b11361057 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile ossrhUsername=your-jira-id ossrhPassword=your-jira-password -selenium.version=4.2.1 +selenium.version=4.4.0 diff --git a/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java b/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java index e6b293921..cd2d6991c 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java +++ b/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java @@ -22,22 +22,13 @@ import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_SIZE; import static org.openqa.selenium.remote.DriverCommand.GET_PAGE_SOURCE; import static org.openqa.selenium.remote.DriverCommand.IS_ELEMENT_DISPLAYED; -import static org.openqa.selenium.remote.DriverCommand.SEND_KEYS_TO_ACTIVE_ELEMENT; import static org.openqa.selenium.remote.DriverCommand.SEND_KEYS_TO_ELEMENT; import static org.openqa.selenium.remote.DriverCommand.SET_TIMEOUT; import static org.openqa.selenium.remote.DriverCommand.SUBMIT_ELEMENT; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -import org.openqa.selenium.interactions.KeyInput; -import org.openqa.selenium.interactions.Sequence; import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; -import java.util.Collection; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class AppiumW3CHttpCommandCodec extends W3CHttpCommandCodec { /** @@ -51,7 +42,6 @@ public AppiumW3CHttpCommandCodec() { defineCommand(GET_ELEMENT_ATTRIBUTE, get("/session/:sessionId/element/:id/attribute/:name")); defineCommand(IS_ELEMENT_DISPLAYED, get("/session/:sessionId/element/:id/displayed")); defineCommand(GET_PAGE_SOURCE, get("/session/:sessionId/source")); - defineCommand(SEND_KEYS_TO_ACTIVE_ELEMENT, post("/session/:sessionId/actions")); } @Override @@ -76,23 +66,6 @@ public void alias(String commandName, String isAnAliasFor) { protected Map amendParameters(String name, Map parameters) { // This blocks parent constructor from undesirable parameters amending switch (name) { - case SEND_KEYS_TO_ACTIVE_ELEMENT: - Object rawValue = parameters.get("value"); - //noinspection unchecked - Stream source = (rawValue instanceof Collection) - ? ((Collection) rawValue).stream() - : Stream.of((CharSequence[]) rawValue); - String text = source.collect(Collectors.joining()); - - final KeyInput keyboard = new KeyInput("keyboard"); - Sequence sequence = new Sequence(keyboard, 0); - for (int i = 0; i < text.length(); ++i) { - sequence.addAction(keyboard.createKeyDown(text.charAt(i))) - .addAction(keyboard.createKeyUp(text.charAt(i))); - } - return ImmutableMap.builder() - .put("actions", ImmutableList.of(sequence.toJson())) - .build(); case SEND_KEYS_TO_ELEMENT: case SET_TIMEOUT: return super.amendParameters(name, parameters); From ab3fc1955bc3803fc5b671e884859bfb6e306627 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 10 Aug 2022 16:38:29 +0300 Subject: [PATCH 115/501] chore: Upgrade to Gradle 7.5.1 (#1739) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d0b13a131..f61424a81 100644 --- a/build.gradle +++ b/build.gradle @@ -181,7 +181,7 @@ signing { } wrapper { - gradleVersion = '7.5' + gradleVersion = '7.5.1' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2ec77e51a..8fad3f5a9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From f9cd5bb597e787cc325ff21aadc64661501cfebf Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 15 Aug 2022 11:41:04 +0300 Subject: [PATCH 116/501] refactor: Deprecate Appium `ByAll` (#1740) Appium `io.appium.java_client.pagefactory.bys.builder.ByAll` was implemented as an extension of Selenium `org.openqa.selenium.support.pagefactory.ByAll` and introduced a performance improvement: "By All was re-implemented, now it returns the first founded element for single search." (https://github.com/appium/java-client/pull/686 on 3 Aug 2017). However Selenium team introduced the same performance fix "https://github.com/SeleniumHQ/selenium/commit/18028ac9f065b81fbe99a9e84feabfa5d0091f13 ByAll.findElement should not not use remaining locators if an element is already found" on 7 Sep 2017. So there is no reason to keep Appium `ByAll`, this commit deprecates it. --- .../pagefactory/DefaultElementByBuilder.java | 2 +- .../pagefactory/bys/builder/AppiumByBuilder.java | 1 + .../pagefactory/bys/builder/ByAll.java | 15 ++++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index 135c2f423..23445fcf8 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -23,7 +23,6 @@ import io.appium.java_client.pagefactory.bys.ContentMappedBy; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder; -import io.appium.java_client.pagefactory.bys.builder.ByAll; import io.appium.java_client.pagefactory.bys.builder.ByChained; import io.appium.java_client.pagefactory.bys.builder.HowToUseSelectors; import org.openqa.selenium.By; @@ -32,6 +31,7 @@ import org.openqa.selenium.support.FindAll; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBys; +import org.openqa.selenium.support.pagefactory.ByAll; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java index 14db1767b..423645881 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java @@ -24,6 +24,7 @@ import org.openqa.selenium.By; import org.openqa.selenium.support.pagefactory.AbstractAnnotations; +import org.openqa.selenium.support.pagefactory.ByAll; import javax.annotation.Nullable; import java.lang.annotation.Annotation; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java index 7332fe389..59015ede7 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java @@ -13,7 +13,20 @@ import java.util.Optional; import java.util.function.Function; - +/** + * Mechanism used to locate elements within a document using a series of lookups. This class will + * find all DOM elements that matches any of the locators in sequence, e.g. + * + *
+ * driver.findElements(new ByAll(by1, by2))
+ * 
+ * + * will find all elements that match by1 and then all elements that match by2. + * This means that the list of elements returned may not be in document order. + * + * @deprecated Use {@link org.openqa.selenium.support.pagefactory.ByAll} + */ +@Deprecated public class ByAll extends org.openqa.selenium.support.pagefactory.ByAll { private final List bys; From c143f1ab5119119c163c4f5c09a532c28a54da7f Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 15 Aug 2022 11:41:19 +0300 Subject: [PATCH 117/501] test: Clean up unit tests asserting thrown exceptions (#1741) --- .../java_client/android/AndroidContextTest.java | 6 +----- .../java_client/android/AndroidFunctionTest.java | 6 ++---- .../io/appium/java_client/internal/ConfigTest.java | 6 ++---- .../io/appium/java_client/ios/IOSContextTest.java | 6 +----- .../pagefactory_tests/AndroidPageObjectTest.java | 6 ++---- .../java_client/service/local/ServerBuilderTest.java | 12 +++--------- 6 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/test/java/io/appium/java_client/android/AndroidContextTest.java b/src/test/java/io/appium/java_client/android/AndroidContextTest.java index 57f5895d8..ed832f9e3 100644 --- a/src/test/java/io/appium/java_client/android/AndroidContextTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidContextTest.java @@ -48,11 +48,7 @@ public class AndroidContextTest extends BaseAndroidTest { } @Test public void testContextError() { - assertThrows(NoSuchContextException.class, - () -> { - driver.context("Planet of the Ape-ium"); - assertEquals("Planet of the Ape-ium", driver.getContext()); - }); + assertThrows(NoSuchContextException.class, () -> driver.context("Planet of the Ape-ium")); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java index 735d0aeda..3b915eae1 100644 --- a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java @@ -6,7 +6,6 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.core.StringContains.containsString; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import io.appium.java_client.functions.AppiumFunction; import io.appium.java_client.functions.ExpectedCondition; @@ -132,8 +131,7 @@ public void complexWaitingTestWithPreCondition() { public void nullPointerExceptionSafetyTestWithPrecondition() { Wait wait = new FluentWait<>(Pattern.compile("Fake_context")) .withTimeout(ofSeconds(30)).pollingEvery(ofMillis(500)); - assertThrows(TimeoutException.class, - () -> assertTrue(wait.until(searchingFunction.compose(contextFunction)).size() > 0)); + assertThrows(TimeoutException.class, () -> wait.until(searchingFunction.compose(contextFunction))); } @Test @@ -141,6 +139,6 @@ public void nullPointerExceptionSafetyTestWithPostConditions() { Wait wait = new FluentWait<>(Pattern.compile("Fake_context")) .withTimeout(ofSeconds(30)).pollingEvery(ofMillis(500)); assertThrows(TimeoutException.class, - () -> assertTrue(wait.until(contextFunction.andThen(searchingFunction).andThen(filteringFunction)).size() > 0)); + () -> wait.until(contextFunction.andThen(searchingFunction).andThen(filteringFunction))); } } diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index 4ae2feb6c..cd2bd390c 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -20,14 +20,12 @@ public void verifyGettingExistingValue() { @Test public void verifyGettingNonExistingValue() { - assertThrows(IllegalArgumentException.class, - () -> assertThat(Config.main().getValue(MISSING_KEY, String.class).length(), greaterThan(0))); + assertThrows(IllegalArgumentException.class, () -> Config.main().getValue(MISSING_KEY, String.class)); } @Test public void verifyGettingExistingValueWithWrongClass() { - assertThrows(ClassCastException.class, - () -> assertThat(Config.main().getValue(EXISTING_KEY, Integer.class), greaterThan(0))); + assertThrows(ClassCastException.class, () -> Config.main().getValue(EXISTING_KEY, Integer.class)); } @Test diff --git a/src/test/java/io/appium/java_client/ios/IOSContextTest.java b/src/test/java/io/appium/java_client/ios/IOSContextTest.java index 57915a1f7..5c51aa677 100644 --- a/src/test/java/io/appium/java_client/ios/IOSContextTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSContextTest.java @@ -42,10 +42,6 @@ public class IOSContextTest extends BaseIOSWebViewTest { } @Test public void testContextError() { - assertThrows(NoSuchContextException.class, - () -> { - driver.context("Planet of the Ape-ium"); - assertEquals("Planet of the Ape-ium", driver.getContext()); - }); + assertThrows(NoSuchContextException.class, () -> driver.context("Planet of the Ape-ium")); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index c183c44e0..433aa2a1a 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -326,8 +326,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @Test public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy() { assertThrows(NoSuchElementException.class, - () -> assertNotNull( - elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.getAttribute("text"))); + () -> elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.getAttribute("text")); } @Test public void checkThatTestWillNotBeFailedBecauseOfInvalidFindByList() { @@ -351,8 +350,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @Test public void checkThatElementSearchingThrowsExpectedExceptionIfChainedLocatorIsInvalid() { - assertThrows(NoSuchElementException.class, - () -> assertNotNull(elementFoundByInvalidChainedSelector.getAttribute("text"))); + assertThrows(NoSuchElementException.class, () -> elementFoundByInvalidChainedSelector.getAttribute("text")); } @Test public void checkThatListSearchingWorksIfChainedLocatorIsInvalid() { diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index fe5b9a3b6..cb97479e8 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -339,22 +339,16 @@ public void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { @Test public void checkAbilityToValidateBasePathForEmptyBasePath() { - assertThrows(IllegalArgumentException.class, () -> { - new AppiumServiceBuilder().withArgument(BASEPATH, "").build(); - }); + assertThrows(IllegalArgumentException.class, () -> new AppiumServiceBuilder().withArgument(BASEPATH, "")); } @Test public void checkAbilityToValidateBasePathForBlankBasePath() { - assertThrows(IllegalArgumentException.class, () -> { - new AppiumServiceBuilder().withArgument(BASEPATH, " ").build(); - }); + assertThrows(IllegalArgumentException.class, () -> new AppiumServiceBuilder().withArgument(BASEPATH, " ")); } @Test public void checkAbilityToValidateBasePathForNullBasePath() { - assertThrows(NullPointerException.class, () -> { - new AppiumServiceBuilder().withArgument(BASEPATH, null).build(); - }); + assertThrows(NullPointerException.class, () -> new AppiumServiceBuilder().withArgument(BASEPATH, null)); } } From 843e719cc92a8c984b061780c3986a35f2fa3095 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 14:38:42 +0300 Subject: [PATCH 118/501] build(deps): bump org.owasp.dependencycheck from 7.1.1 to 7.1.2 (#1746) Bumps org.owasp.dependencycheck from 7.1.1 to 7.1.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f61424a81..0d4205919 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.1.1' + id 'org.owasp.dependencycheck' version '7.1.2' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 80be5584b0e231429dfe5c921fa17ecec34034f5 Mon Sep 17 00:00:00 2001 From: Anuj Kumar Date: Fri, 26 Aug 2022 18:33:46 +0200 Subject: [PATCH 119/501] test: Fix open notification test (#1749) --- build.gradle | 1 + .../io/appium/java_client/android/OpenNotificationsTest.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0d4205919..a044708d0 100644 --- a/build.gradle +++ b/build.gradle @@ -213,6 +213,7 @@ task uiAutomationTest( type: Test ) { filter { includeTestsMatching 'io.appium.java_client.android.SettingTest' includeTestsMatching 'io.appium.java_client.android.ClipboardTest' + includeTestsMatching 'io.appium.java_client.android.OpenNotificationsTest' includeTestsMatching '*.AndroidAppStringsTest' includeTestsMatching '*.pagefactory_tests.widget.tests.android.*' includeTestsMatching '*.pagefactory_tests.widget.tests.AndroidPageObjectTest' diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index dde09bbc1..e29e92c45 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -1,7 +1,7 @@ package io.appium.java_client.android; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.openqa.selenium.By.id; +import static org.openqa.selenium.By.xpath; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebElement; @@ -18,7 +18,7 @@ public void openNotification() { WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20)); assertNotEquals(0, wait.until(input -> { List result = input - .findElements(id("com.android.systemui:id/settings_button")); + .findElements(xpath("//android.widget.Switch[contains(@content-desc, 'Wi-Fi')]")); return result.isEmpty() ? null : result; }).size()); From 6d05b8be8c1f0287e02bb2e8c40f9d67a8f94c31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Aug 2022 13:27:55 +0300 Subject: [PATCH 120/501] build(deps): bump webdrivermanager from 5.2.3 to 5.3.0 (#1745) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.2.3 to 5.3.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.2.3...webdrivermanager-5.3.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a044708d0..885ff233e 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.2.3') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.0') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From 36cf25c82bdcc959fc8defbba6cf1142407adffe Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Tue, 30 Aug 2022 11:02:03 +0530 Subject: [PATCH 121/501] Release 8.2.0 and update release notes --- README.md | 20 ++++++++++++++++++++ build.gradle | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 39c936ba5..6af5f0be8 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,26 @@ dependencies { ``` ## Changelog +*8.2.0* +- **[ENHANCEMENTS]** + - AppiumDriverLocalService can handle outputStreams. [#1709](https://github.com/appium/java-client/pull/1709) + - Add creating a driver with ClientConfig. [#1735](https://github.com/appium/java-client/pull/1735) +- **[BUG FIX]** + - Update the environment argument type for mac SupportsEnvironmentOption. [#1712](https://github.com/appium/java-client/pull/1712) +- **[REFRACTOR]** + - Deprecate Appium ByAll in favour of Selenium ByAll. [#1740](https://github.com/appium/java-client/pull/1740) + - Bump Node.js version in pipeline. [#1713](https://github.com/appium/java-client/pull/1713) + - Switch unit tests to run on Junit 5 Jupiter Platform. [#1721](https://github.com/appium/java-client/pull/1721) + - Clean up unit tests asserting thrown exceptions. [#1741](https://github.com/appium/java-client/pull/1741) + - Fix open notification test. [#1749](https://github.com/appium/java-client/pull/1749) + - update Azure pipeline to use macos-11 VM image. [#1728](https://github.com/appium/java-client/pull/1728) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.4.0. + - `org.owasp.dependencycheck` was updated to 7.1.2. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.0. + - `gradle` was updated to 7.5.1. + - `com.google.code.gson:gson` was updated to 2.9.1. + *8.1.1* - **[BUG FIX]** - Perform safe typecast while getting the platform name. [#1702](https://github.com/appium/java-client/pull/1702) diff --git a/build.gradle b/build.gradle index 885ff233e..1552006d4 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '8.1.1' + version = '8.2.0' from components.java pom { name = 'java-client' From c9a5c920156c480bfb8bd71198c4dd3fc703b4c6 Mon Sep 17 00:00:00 2001 From: Bipin Kumar Chaurasia Date: Tue, 30 Aug 2022 17:27:49 +0530 Subject: [PATCH 122/501] feat!: Updated spell for deprecated BYACCESSABILITY to BYACCESSIBILITY strategies enum (#1752) --- .../pagefactory/bys/builder/Strategies.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index db06bdbc1..6212ffcf7 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -41,11 +41,21 @@ enum Strategies { return super.getBy(annotation); } }, + /** + * This has been deprecated due to misspelling. + * @deprecated Use {@link Strategies#BYACCESSIBILITY} instead. + */ + @Deprecated BYACCESSABILITY("accessibility") { @Override By getBy(Annotation annotation) { return AppiumBy.accessibilityId(getValue(annotation, this)); } }, + BYACCESSIBILITY("accessibility") { + @Override By getBy(Annotation annotation) { + return AppiumBy.accessibilityId(getValue(annotation, this)); + } + }, BYCLASSNAME("className") { @Override By getBy(Annotation annotation) { return AppiumBy.className(getValue(annotation, this)); From 54fdd4b8c6fc2303851d46b6310f25e96b690e39 Mon Sep 17 00:00:00 2001 From: Bipin Kumar Chaurasia Date: Fri, 2 Sep 2022 00:37:41 +0530 Subject: [PATCH 123/501] test: updated JUnit5 test classes and methods to have default package visibility (#1755) --- .../java_client/internal/ConfigTest.java | 10 +-- .../tests/combined/CombinedAppTest.java | 7 +- .../tests/combined/CombinedWidgetTest.java | 2 +- .../service/local/ServerBuilderTest.java | 65 +++++++++---------- .../local/StartingAppLocallyAndroidTest.java | 23 ++++--- .../local/StartingAppLocallyIosTest.java | 8 +-- .../service/local/ThreadSafetyTest.java | 10 +-- 7 files changed, 61 insertions(+), 64 deletions(-) diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index cd2bd390c..df8611458 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -8,28 +8,28 @@ import org.junit.jupiter.api.Test; -public class ConfigTest { +class ConfigTest { private static final String EXISTING_KEY = "selenium.version"; private static final String MISSING_KEY = "bla"; @Test - public void verifyGettingExistingValue() { + void verifyGettingExistingValue() { assertThat(Config.main().getValue(EXISTING_KEY, String.class).length(), greaterThan(0)); assertTrue(Config.main().getOptionalValue(EXISTING_KEY, String.class).isPresent()); } @Test - public void verifyGettingNonExistingValue() { + void verifyGettingNonExistingValue() { assertThrows(IllegalArgumentException.class, () -> Config.main().getValue(MISSING_KEY, String.class)); } @Test - public void verifyGettingExistingValueWithWrongClass() { + void verifyGettingExistingValueWithWrongClass() { assertThrows(ClassCastException.class, () -> Config.main().getValue(EXISTING_KEY, Integer.class)); } @Test - public void verifyGettingNonExistingOptionalValue() { + void verifyGettingNonExistingOptionalValue() { assertFalse(Config.main().getOptionalValue(MISSING_KEY, String.class).isPresent()); } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index 8c93632ec..80e6eb1b3 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -13,14 +13,13 @@ import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget; +import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.openqa.selenium.WebDriver; -import java.util.List; -import java.util.stream.Stream; - @SuppressWarnings({"unused", "unchecked"}) public class CombinedAppTest { @@ -53,7 +52,7 @@ public static Stream data() { @ParameterizedTest @MethodSource("data") - public void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { + void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { initElements(new AppiumFieldDecorator(driver), app); assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSelfReference().getClass(), diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java index 1d686c58e..342e37335 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java @@ -59,7 +59,7 @@ public static Stream data() { @ParameterizedTest @MethodSource("data") - public void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { + void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { initElements(new AppiumFieldDecorator(driver), app); assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSubWidget().getSelfReference().getClass(), diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index cb97479e8..ccdd117d2 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -27,20 +27,19 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.options.UiAutomator2Options; import io.github.bonigarcia.wdm.WebDriverManager; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - import java.io.File; -import java.io.FileOutputStream; import java.io.OutputStream; +import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; import java.util.ArrayList; import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; @SuppressWarnings("ResultOfMethodCallIgnored") -public class ServerBuilderTest { +class ServerBuilderTest { /** * It may be impossible to find the path to the instance of appium server due to different circumstance. @@ -93,7 +92,7 @@ public void tearDown() throws Exception { } @Test - public void checkAbilityToAddLogMessageConsumer() { + void checkAbilityToAddLogMessageConsumer() { List log = new ArrayList<>(); service = buildDefaultService(); service.clearOutPutStreams(); @@ -103,21 +102,21 @@ public void checkAbilityToAddLogMessageConsumer() { } @Test - public void checkAbilityToStartDefaultService() { + void checkAbilityToStartDefaultService() { service = buildDefaultService(); service.start(); assertTrue(service.isRunning()); } @Test - public void checkAbilityToFindNodeDefinedInProperties() { + void checkAbilityToFindNodeDefinedInProperties() { File definedNode = PATH_T0_TEST_MAIN_JS.toFile(); setProperty(APPIUM_PATH, definedNode.getAbsolutePath()); assertThat(new AppiumServiceBuilder().createArgs().get(0), is(definedNode.getAbsolutePath())); } @Test - public void checkAbilityToUseNodeDefinedExplicitly() { + void checkAbilityToUseNodeDefinedExplicitly() { File mainJS = PATH_T0_TEST_MAIN_JS.toFile(); AppiumServiceBuilder builder = new AppiumServiceBuilder() .withAppiumJS(mainJS); @@ -126,21 +125,21 @@ public void checkAbilityToUseNodeDefinedExplicitly() { } @Test - public void checkAbilityToStartServiceOnAFreePort() { + void checkAbilityToStartServiceOnAFreePort() { service = new AppiumServiceBuilder().usingAnyFreePort().build(); service.start(); assertTrue(service.isRunning()); } @Test - public void checkAbilityToStartServiceUsingNonLocalhostIP() { + void checkAbilityToStartServiceUsingNonLocalhostIP() { service = new AppiumServiceBuilder().withIPAddress(testIP).build(); service.start(); assertTrue(service.isRunning()); } @Test - public void checkAbilityToStartServiceUsingFlags() { + void checkAbilityToStartServiceUsingFlags() { service = new AppiumServiceBuilder() .withArgument(CALLBACK_ADDRESS, testIP) .withArgument(SESSION_OVERRIDE) @@ -150,7 +149,7 @@ public void checkAbilityToStartServiceUsingFlags() { } @Test - public void checkAbilityToStartServiceUsingCapabilities() { + void checkAbilityToStartServiceUsingCapabilities() { UiAutomator2Options options = new UiAutomator2Options() .fullReset() .setNewCommandTimeout(Duration.ofSeconds(60)) @@ -165,7 +164,7 @@ public void checkAbilityToStartServiceUsingCapabilities() { } @Test - public void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { + void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { File app = ROOT_TEST_PATH.resolve("ApiDemos-debug.apk").toFile(); UiAutomator2Options options = new UiAutomator2Options() @@ -191,10 +190,10 @@ public void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { } @Test - public void checkAbilityToChangeOutputStream() throws Exception { + void checkAbilityToChangeOutputStream() throws Exception { testLogFile = new File("test"); testLogFile.createNewFile(); - stream = new FileOutputStream(testLogFile); + stream = Files.newOutputStream(testLogFile.toPath()); service = buildDefaultService(); service.addOutPutStream(stream); service.start(); @@ -202,10 +201,10 @@ public void checkAbilityToChangeOutputStream() throws Exception { } @Test - public void checkAbilityToChangeOutputStreamAfterTheServiceIsStarted() throws Exception { + void checkAbilityToChangeOutputStreamAfterTheServiceIsStarted() throws Exception { testLogFile = new File("test"); testLogFile.createNewFile(); - stream = new FileOutputStream(testLogFile); + stream = Files.newOutputStream(testLogFile.toPath()); service = buildDefaultService(); service.start(); service.addOutPutStream(stream); @@ -214,7 +213,7 @@ public void checkAbilityToChangeOutputStreamAfterTheServiceIsStarted() throws Ex } @Test - public void checkAbilityToShutDownService() { + void checkAbilityToShutDownService() { service = buildDefaultService(); service.start(); service.stop(); @@ -222,7 +221,7 @@ public void checkAbilityToShutDownService() { } @Test - public void checkAbilityToStartAndShutDownFewServices() throws Exception { + void checkAbilityToStartAndShutDownFewServices() throws Exception { List services = asList( new AppiumServiceBuilder().usingAnyFreePort().build(), new AppiumServiceBuilder().usingAnyFreePort().build(), @@ -236,7 +235,7 @@ public void checkAbilityToStartAndShutDownFewServices() throws Exception { } @Test - public void checkAbilityToStartServiceWithLogFile() throws Exception { + void checkAbilityToStartServiceWithLogFile() throws Exception { testLogFile = new File("Log.txt"); testLogFile.createNewFile(); service = new AppiumServiceBuilder().withLogFile(testLogFile).build(); @@ -246,7 +245,7 @@ public void checkAbilityToStartServiceWithLogFile() throws Exception { } @Test - public void checkAbilityToStartServiceWithPortUsingFlag() { + void checkAbilityToStartServiceWithPortUsingFlag() { String port = "8996"; String expectedUrl = String.format("http://0.0.0.0:%s/", port); @@ -259,7 +258,7 @@ public void checkAbilityToStartServiceWithPortUsingFlag() { } @Test - public void checkAbilityToStartServiceWithPortUsingShortFlag() { + void checkAbilityToStartServiceWithPortUsingShortFlag() { String port = "8996"; String expectedUrl = String.format("http://0.0.0.0:%s/", port); @@ -272,7 +271,7 @@ public void checkAbilityToStartServiceWithPortUsingShortFlag() { } @Test - public void checkAbilityToStartServiceWithIpUsingFlag() { + void checkAbilityToStartServiceWithIpUsingFlag() { String expectedUrl = String.format("http://%s:4723/", testIP); service = new AppiumServiceBuilder() @@ -284,7 +283,7 @@ public void checkAbilityToStartServiceWithIpUsingFlag() { } @Test - public void checkAbilityToStartServiceWithIpUsingShortFlag() { + void checkAbilityToStartServiceWithIpUsingShortFlag() { String expectedUrl = String.format("http://%s:4723/", testIP); service = new AppiumServiceBuilder() @@ -296,7 +295,7 @@ public void checkAbilityToStartServiceWithIpUsingShortFlag() { } @Test - public void checkAbilityToStartServiceWithLogFileUsingFlag() { + void checkAbilityToStartServiceWithLogFileUsingFlag() { testLogFile = new File("Log2.txt"); service = new AppiumServiceBuilder() @@ -307,7 +306,7 @@ public void checkAbilityToStartServiceWithLogFileUsingFlag() { } @Test - public void checkAbilityToStartServiceWithLogFileUsingShortFlag() { + void checkAbilityToStartServiceWithLogFileUsingShortFlag() { testLogFile = new File("Log3.txt"); service = new AppiumServiceBuilder() @@ -318,7 +317,7 @@ public void checkAbilityToStartServiceWithLogFileUsingShortFlag() { } @Test - public void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() { + void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() { String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); String basePath = "wd/hub"; service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); @@ -328,7 +327,7 @@ public void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() } @Test - public void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { + void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); String basePath = "/wd/"; service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); @@ -338,17 +337,17 @@ public void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { } @Test - public void checkAbilityToValidateBasePathForEmptyBasePath() { + void checkAbilityToValidateBasePathForEmptyBasePath() { assertThrows(IllegalArgumentException.class, () -> new AppiumServiceBuilder().withArgument(BASEPATH, "")); } @Test - public void checkAbilityToValidateBasePathForBlankBasePath() { + void checkAbilityToValidateBasePathForBlankBasePath() { assertThrows(IllegalArgumentException.class, () -> new AppiumServiceBuilder().withArgument(BASEPATH, " ")); } @Test - public void checkAbilityToValidateBasePathForNullBasePath() { + void checkAbilityToValidateBasePathForNullBasePath() { assertThrows(NullPointerException.class, () -> new AppiumServiceBuilder().withArgument(BASEPATH, null)); } } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index 3d248f462..55906d13f 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -16,6 +16,12 @@ package io.appium.java_client.service.local; +import static io.appium.java_client.TestResources.apiDemosApk; +import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.remote.AutomationName; @@ -23,21 +29,14 @@ import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.github.bonigarcia.wdm.WebDriverManager; +import java.time.Duration; import org.junit.jupiter.api.Test; import org.openqa.selenium.Capabilities; -import java.time.Duration; - -import static io.appium.java_client.TestResources.apiDemosApk; -import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class StartingAppLocallyAndroidTest { +class StartingAppLocallyAndroidTest { @Test - public void startingAndroidAppWithCapabilitiesOnlyTest() { + void startingAndroidAppWithCapabilitiesOnlyTest() { AndroidDriver driver = new AndroidDriver(new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() @@ -57,7 +56,7 @@ public void startingAndroidAppWithCapabilitiesOnlyTest() { } @Test - public void startingAndroidAppWithCapabilitiesAndServiceTest() { + void startingAndroidAppWithCapabilitiesAndServiceTest() { AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS); @@ -79,7 +78,7 @@ public void startingAndroidAppWithCapabilitiesAndServiceTest() { } @Test - public void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { + void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { UiAutomator2Options serverOptions = new UiAutomator2Options() .setDeviceName("Android Emulator") .fullReset() diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index ec629f8ba..07bf8008a 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -33,9 +33,9 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; -public class StartingAppLocallyIosTest { +class StartingAppLocallyIosTest { @Test - public void startingIOSAppWithCapabilitiesOnlyTest() { + void startingIOSAppWithCapabilitiesOnlyTest() { XCUITestOptions options = new XCUITestOptions() .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) .setDeviceName(BaseIOSTest.DEVICE_NAME) @@ -57,7 +57,7 @@ public void startingIOSAppWithCapabilitiesOnlyTest() { @Test - public void startingIOSAppWithCapabilitiesAndServiceTest() { + void startingIOSAppWithCapabilitiesAndServiceTest() { XCUITestOptions options = new XCUITestOptions() .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) .setDeviceName(BaseIOSTest.DEVICE_NAME) @@ -80,7 +80,7 @@ public void startingIOSAppWithCapabilitiesAndServiceTest() { } @Test - public void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { + void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { XCUITestOptions serverOptions = new XCUITestOptions() .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) .setDeviceName(BaseIOSTest.DEVICE_NAME) diff --git a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java b/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java index 50d59a5df..f4fb55b42 100644 --- a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java +++ b/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java @@ -4,11 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import io.appium.java_client.service.local.AppiumServerHasNotBeenStartedLocallyException; import org.junit.jupiter.api.Test; -public class ThreadSafetyTest { +class ThreadSafetyTest { private final AppiumDriverLocalService service = AppiumDriverLocalService.buildDefaultService(); private final Action run = new Action() { @@ -32,7 +30,8 @@ public class ThreadSafetyTest { }; private final Action stop2 = stop.clone(); - @Test public void whenFewTreadsDoTheSameWork() throws Throwable { + @Test + void whenFewTreadsDoTheSameWork() throws Throwable { TestThread runTestThread = new TestThread<>(run); TestThread runTestThread2 = new TestThread<>(run2); @@ -116,7 +115,8 @@ public class ThreadSafetyTest { } - @Test public void whenFewTreadsDoDifferentWork() throws Throwable { + @Test + void whenFewTreadsDoDifferentWork() throws Throwable { TestThread runTestThread = new TestThread<>(run); TestThread runTestThread2 = new TestThread<>(run2); From c8757f5172221d9f395b2eea1286e83ce6cb6f52 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 5 Sep 2022 20:50:40 +0200 Subject: [PATCH 124/501] ci: Verify if the PR title complies with conventional commits spec (#1757) --- .github/workflows/pr-title.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/pr-title.yml diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml new file mode 100644 index 000000000..b7167560f --- /dev/null +++ b/.github/workflows/pr-title.yml @@ -0,0 +1,13 @@ +name: Conventional Commits +on: + pull_request: + + +jobs: + lint: + name: https://www.conventionalcommits.org + runs-on: ubuntu-latest + steps: + - uses: beemojs/conventional-pr-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4ec8753e94e5d989fe1ffa6fb40e56a492f951eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 14:44:59 +0300 Subject: [PATCH 125/501] build(deps): bump slf4j-api from 1.7.36 to 2.0.1 (#1762) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 1.7.36 to 2.0.1. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.36...v_2.0.1) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1552006d4..8de85a21a 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:1.7.36' + implementation 'org.slf4j:slf4j-api:2.0.1' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' testImplementation 'org.hamcrest:hamcrest:2.2' From fe17e854ad61605e2f4e1988fde2cd5615cfaf2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Sep 2022 12:56:23 +0300 Subject: [PATCH 126/501] build(deps): bump org.owasp.dependencycheck from 7.1.2 to 7.2.0 (#1763) Bumps org.owasp.dependencycheck from 7.1.2 to 7.2.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8de85a21a..bb996e42a 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.1.2' + id 'org.owasp.dependencycheck' version '7.2.0' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 3d6abbdd499de7733dd7bebfa8cd10448937d54f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 14:28:50 +0300 Subject: [PATCH 127/501] build(deps): bump junit-jupiter from 5.9.0 to 5.9.1 (#1768) Bumps [junit-jupiter](https://github.com/junit-team/junit5) from 5.9.0 to 5.9.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.0...r5.9.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bb996e42a..f1a417751 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.slf4j:slf4j-api:2.0.1' - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.0') { exclude group: 'org.seleniumhq.selenium' From abbcffed5df125a0e110b22dba6ed8df31444c5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 19:15:44 +0300 Subject: [PATCH 128/501] build(deps): bump slf4j-api from 2.0.1 to 2.0.2 (#1767) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.1...v_2.0.2) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f1a417751..32758b058 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:2.0.1' + implementation 'org.slf4j:slf4j-api:2.0.2' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' From 31e99f31d3f796742c2dee27b05f5e1b0c85613a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Sep 2022 10:13:42 +0530 Subject: [PATCH 129/501] build(deps): bump org.owasp.dependencycheck from 7.2.0 to 7.2.1 (#1766) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 32758b058..2e9865f5c 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.2.0' + id 'org.owasp.dependencycheck' version '7.2.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From a829beca70c2e4cd9ab00cf0f70e17a384323c1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 18:47:56 +0300 Subject: [PATCH 130/501] build(deps): bump slf4j-api from 2.0.2 to 2.0.3 (#1773) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.2 to 2.0.3. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.2...v_2.0.3) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2e9865f5c..084b502cb 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:2.0.2' + implementation 'org.slf4j:slf4j-api:2.0.3' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' From 45eaae0fc5605d604bb70d5b2332baafc4fc070d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 22 Oct 2022 21:20:08 +0200 Subject: [PATCH 131/501] ci: Tune conventional commit settings --- .github/workflows/pr-title.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index b7167560f..f3387333b 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -9,5 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: beemojs/conventional-pr-action@v2 + with: + config-preset: angular env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 898d7ee7826b6e97d3296110af54033af140ce7a Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 22 Oct 2022 20:22:44 -0700 Subject: [PATCH 132/501] feat: add directConnect feature (#1747) --- .github/workflows/gradle.yml | 2 +- build.gradle | 9 + gradle.properties | 2 +- .../java_client/AppiumClientConfig.java | 191 ++++++++++++++++++ .../io/appium/java_client/AppiumDriver.java | 3 +- .../java_client/android/AndroidDriver.java | 28 ++- .../appium/java_client/gecko/GeckoDriver.java | 27 ++- .../io/appium/java_client/ios/IOSDriver.java | 29 ++- .../io/appium/java_client/mac/Mac2Driver.java | 28 ++- .../remote/AppiumCommandExecutor.java | 126 +++++++++--- .../java_client/remote/DirectConnect.java | 77 +++++++ .../java_client/safari/SafariDriver.java | 28 ++- .../java_client/windows/WindowsDriver.java | 29 ++- .../events/stubs/EmptyWebDriver.java | 4 - .../java_client/internal/ConfigTest.java | 9 +- .../internal/DirectConnectTest.java | 56 +++++ .../widget/tests/AbstractStubWebDriver.java | 5 - 17 files changed, 602 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/appium/java_client/AppiumClientConfig.java create mode 100644 src/main/java/io/appium/java_client/remote/DirectConnect.java create mode 100644 src/test/java/io/appium/java_client/internal/DirectConnectTest.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e5981b475..caf838f59 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -27,4 +27,4 @@ jobs: java-version: ${{ matrix.java }} cache: 'gradle' - name: Build with Gradle - run: ./gradlew clean build -x test -x checkstyleTest + run: ./gradlew clean build -x unitTest -x checkstyleTest diff --git a/build.gradle b/build.gradle index 084b502cb..b0116c43b 100644 --- a/build.gradle +++ b/build.gradle @@ -191,6 +191,15 @@ processResources { ] } +task unitTest( type: Test ) { + useJUnitPlatform() + testLogging.showStandardStreams = true + testLogging.exceptionFormat = 'full' + filter { + includeTestsMatching 'io.appium.java_client.internal.*' + } +} + task xcuiTest( type: Test ) { useJUnitPlatform() testLogging.showStandardStreams = true diff --git a/gradle.properties b/gradle.properties index b11361057..9b086f575 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile ossrhUsername=your-jira-id ossrhPassword=your-jira-password -selenium.version=4.4.0 +selenium.version=4.5.0 diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java new file mode 100644 index 000000000..2e6128c03 --- /dev/null +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -0,0 +1,191 @@ +/* + * 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.Credentials; +import org.openqa.selenium.internal.Require; +import org.openqa.selenium.remote.http.AddSeleniumUserAgent; +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.Filter; + +import java.net.Proxy; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.time.Duration; + +/** + * A class to store the appium http client configuration. + */ +public class AppiumClientConfig extends ClientConfig { + private final boolean directConnect; + + private static final Filter DEFAULT_FILTER = new AddSeleniumUserAgent(); + + private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofMinutes(10); + + private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ofSeconds(10); + + /** + * Client side configuration. + * + * @param baseUri Base URL the client sends HTTP request to. + * @param connectionTimeout The client connection timeout. + * @param readTimeout The client read timeout. + * @param filters Filters to modify incoming {@link org.openqa.selenium.remote.http.HttpRequest} or outgoing + * {@link org.openqa.selenium.remote.http.HttpResponse}. + * @param proxy The client proxy preference. + * @param credentials Credentials used for authenticating http requests + * @param directConnect If directConnect is enabled. + */ + protected AppiumClientConfig( + URI baseUri, + Duration connectionTimeout, + Duration readTimeout, + Filter filters, + Proxy proxy, + Credentials credentials, + Boolean directConnect) { + super(baseUri, connectionTimeout, readTimeout, filters, proxy, credentials); + + this.directConnect = Require.nonNull("Direct Connect", directConnect); + } + + /** + * Return the instance of {@link AppiumClientConfig} with a default config. + * @return the instance of {@link AppiumClientConfig}. + */ + public static AppiumClientConfig defaultConfig() { + return new AppiumClientConfig( + null, + DEFAULT_CONNECTION_TIMEOUT, + DEFAULT_READ_TIMEOUT, + DEFAULT_FILTER, + null, + null, + false); + } + + /** + * Return the instance of {@link AppiumClientConfig} from the given {@link ClientConfig} parameters. + * @param clientConfig take a look at {@link ClientConfig} + * @return the instance of {@link AppiumClientConfig}. + */ + public static AppiumClientConfig fromClientConfig(ClientConfig clientConfig) { + return new AppiumClientConfig( + clientConfig.baseUri(), + clientConfig.connectionTimeout(), + clientConfig.readTimeout(), + clientConfig.filter(), + clientConfig.proxy(), + clientConfig.credentials(), + false); + } + + private AppiumClientConfig buildAppiumClientConfig(ClientConfig clientConfig, Boolean directConnect) { + return new AppiumClientConfig( + clientConfig.baseUri(), + clientConfig.connectionTimeout(), + clientConfig.readTimeout(), + clientConfig.filter(), + clientConfig.proxy(), + clientConfig.credentials(), + directConnect); + } + + @Override + public AppiumClientConfig baseUri(URI baseUri) { + ClientConfig clientConfig = super.baseUri(baseUri); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + @Override + public AppiumClientConfig baseUrl(URL baseUrl) { + try { + return baseUri(Require.nonNull("Base URL", baseUrl).toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + @Override + public AppiumClientConfig connectionTimeout(Duration timeout) { + ClientConfig clientConfig = super.connectionTimeout(timeout); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + @Override + public AppiumClientConfig readTimeout(Duration timeout) { + ClientConfig clientConfig = super.connectionTimeout(timeout); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + @Override + public AppiumClientConfig withFilter(Filter filter) { + ClientConfig clientConfig = super.withFilter(filter); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + @Override + public AppiumClientConfig withRetries() { + ClientConfig clientConfig = super.withRetries(); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + + @Override + public ClientConfig proxy(Proxy proxy) { + ClientConfig clientConfig = super.proxy(proxy); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + @Override + public AppiumClientConfig authenticateAs(Credentials credentials) { + ClientConfig clientConfig = super.authenticateAs(credentials); + return buildAppiumClientConfig(clientConfig, directConnect); + } + + /** + * Whether enable directConnect feature described in + * + * Connecting Directly to Appium Hosts in Distributed Environments. + * + * @param directConnect if enable the directConnect feature + * @return A new instance of AppiumClientConfig + */ + public AppiumClientConfig directConnect(boolean directConnect) { + // follows ClientConfig's design + return new AppiumClientConfig( + this.baseUri(), + this.connectionTimeout(), + this.readTimeout(), + this.filter(), + this.proxy(), + this.credentials(), + directConnect + ); + } + + /** + * Whether enable directConnect feature is enabled. + * + * @return If the directConnect is enabled. Defaults false. + */ + public boolean isDirectConnectEnabled() { + return directConnect; + } +} diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 0f109af2c..d814657c6 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -41,7 +41,6 @@ import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.html5.RemoteLocationContext; -import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; @@ -84,7 +83,7 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { this.remoteAddress = executor.getAddressOfRemoteServer(); } - public AppiumDriver(ClientConfig clientConfig, Capabilities capabilities) { + public AppiumDriver(AppiumClientConfig clientConfig, Capabilities capabilities) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, clientConfig), capabilities); } 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 76810cac3..92ed19370 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap; +import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecuteCDPCommand; @@ -203,7 +204,32 @@ public AndroidDriver(HttpClient.Factory httpClientFactory, Capabilities capabili * */ public AndroidDriver(ClientConfig clientConfig, Capabilities capabilities) { - super(clientConfig, ensurePlatformName(capabilities, ANDROID_PLATFORM)); + super(AppiumClientConfig.fromClientConfig(clientConfig), ensurePlatformName(capabilities, + ANDROID_PLATFORM)); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * UiAutomator2Options options = new UiAutomator2Options();
+     * AndroidDriver driver = new AndroidDriver(appiumClientConfig, options);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public AndroidDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensurePlatformName(capabilities, ANDROID_PLATFORM)); } /** diff --git a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java index 43d2072c8..6a7a55cab 100644 --- a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java +++ b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java @@ -16,6 +16,7 @@ package io.appium.java_client.gecko; +import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -94,7 +95,31 @@ public GeckoDriver(HttpClient.Factory httpClientFactory, Capabilities capabiliti * */ public GeckoDriver(ClientConfig clientConfig, Capabilities capabilities) { - super(clientConfig, ensureAutomationName(capabilities, AUTOMATION_NAME)); + super(AppiumClientConfig.fromClientConfig(clientConfig), ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * GeckoOptions options = new GeckoOptions();
+     * GeckoDriver driver = new GeckoDriver(options, appiumClientConfig);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public GeckoDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensureAutomationName(capabilities, AUTOMATION_NAME)); } public GeckoDriver(Capabilities capabilities) { 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 18ecf3065..00098b14c 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap; +import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.HasAppStrings; import io.appium.java_client.HasDeviceTime; @@ -192,9 +193,35 @@ public IOSDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities * */ public IOSDriver(ClientConfig clientConfig, Capabilities capabilities) { - super(clientConfig, ensurePlatformName(capabilities, PLATFORM_NAME)); + super(AppiumClientConfig.fromClientConfig(clientConfig), + ensurePlatformName(capabilities, PLATFORM_NAME)); } + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * XCUITestOptions options = new XCUITestOptions();
+     * IOSDriver driver = new IOSDriver(options, appiumClientConfig);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public IOSDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensurePlatformName(capabilities, PLATFORM_NAME)); + } + + /** * Creates a new instance based on {@code capabilities}. * diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index b76de5943..905cbec77 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -16,6 +16,7 @@ package io.appium.java_client.mac; +import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.remote.AutomationName; @@ -105,7 +106,32 @@ public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities capabilitie * */ public Mac2Driver(ClientConfig clientConfig, Capabilities capabilities) { - super(clientConfig, ensurePlatformAndAutomationNames( + super(AppiumClientConfig.fromClientConfig(clientConfig), ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * Mac2Options options = new Mac2Options();
+     * Mac2Driver driver = new Mac2Driver(appiumClientConfig, options);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public Mac2Driver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensurePlatformAndAutomationNames( capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 01c551fb4..ec792852a 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -24,9 +24,9 @@ import com.google.common.base.Supplier; import com.google.common.base.Throwables; +import io.appium.java_client.AppiumClientConfig; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandCodec; import org.openqa.selenium.remote.CommandExecutor; @@ -38,17 +38,18 @@ import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.ResponseCodec; import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; -import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; import org.openqa.selenium.remote.service.DriverService; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.lang.reflect.Field; import java.net.ConnectException; +import java.net.MalformedURLException; import java.net.URL; -import java.time.Duration; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -56,49 +57,71 @@ public class AppiumCommandExecutor extends HttpCommandExecutor { // https://github.com/appium/appium-base-driver/pull/400 private static final String IDEMPOTENCY_KEY_HEADER = "X-Idempotency-Key"; - private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofMinutes(10); private final Optional serviceOptional; - private AppiumCommandExecutor(Map additionalCommands, DriverService service, - URL addressOfRemoteServer, - HttpClient.Factory httpClientFactory, - ClientConfig clientConfig) { + private final HttpClient.Factory httpClientFactory; + + private final AppiumClientConfig appiumClientConfig; + + /** + * Create an AppiumCommandExecutor instance. + * + * @param additionalCommands is the map of Appium commands + * @param service take a look at {@link DriverService} + * @param httpClientFactory take a look at {@link HttpClient.Factory} + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + */ + public AppiumCommandExecutor( + @Nonnull Map additionalCommands, + @Nullable DriverService service, + @Nullable HttpClient.Factory httpClientFactory, + @Nonnull AppiumClientConfig appiumClientConfig) { super(additionalCommands, - ofNullable(clientConfig).orElse( - ClientConfig.defaultConfig() - .baseUrl(Require.nonNull("Server URL", ofNullable(service) - .map(DriverService::getUrl) - .orElse(addressOfRemoteServer))) - .readTimeout(DEFAULT_READ_TIMEOUT) - ), - ofNullable(httpClientFactory).orElseGet(HttpCommandExecutor::getDefaultClientFactory) + appiumClientConfig, + ofNullable(httpClientFactory).orElseGet(AppiumCommandExecutor::getDefaultClientFactory) ); serviceOptional = ofNullable(service); + + this.httpClientFactory = httpClientFactory; + this.appiumClientConfig = appiumClientConfig; } public AppiumCommandExecutor(Map additionalCommands, DriverService service, HttpClient.Factory httpClientFactory) { - this(additionalCommands, checkNotNull(service), null, httpClientFactory, null); + this(additionalCommands, checkNotNull(service), httpClientFactory, + AppiumClientConfig.defaultConfig().baseUrl(checkNotNull(service).getUrl())); } - public AppiumCommandExecutor(Map additionalCommands, - URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { - this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory, null); + public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, + HttpClient.Factory httpClientFactory) { + this(additionalCommands, null, httpClientFactory, + AppiumClientConfig.defaultConfig().baseUrl(checkNotNull(addressOfRemoteServer))); } - public AppiumCommandExecutor(Map additionalCommands, ClientConfig clientConfig) { - this(additionalCommands, null, checkNotNull(clientConfig.baseUrl()), null, clientConfig); + public AppiumCommandExecutor(Map additionalCommands, AppiumClientConfig appiumClientConfig) { + this(additionalCommands, null, null, appiumClientConfig); } - public AppiumCommandExecutor(Map additionalCommands, - URL addressOfRemoteServer) { - this(additionalCommands, addressOfRemoteServer, HttpClient.Factory.createDefault()); + public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer) { + this(additionalCommands, null, HttpClient.Factory.createDefault(), + AppiumClientConfig.defaultConfig().baseUrl(checkNotNull(addressOfRemoteServer))); + } + + public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, + AppiumClientConfig appiumClientConfig) { + this(additionalCommands, null, HttpClient.Factory.createDefault(), + appiumClientConfig.baseUrl(checkNotNull(addressOfRemoteServer))); + } + + public AppiumCommandExecutor(Map additionalCommands, DriverService service) { + this(additionalCommands, service, HttpClient.Factory.createDefault(), + AppiumClientConfig.defaultConfig().baseUrl(service.getUrl())); } public AppiumCommandExecutor(Map additionalCommands, - DriverService service) { - this(additionalCommands, service, HttpClient.Factory.createDefault()); + DriverService service, AppiumClientConfig appiumClientConfig) { + this(additionalCommands, service, HttpClient.Factory.createDefault(), appiumClientConfig); } @SuppressWarnings("SameParameterValue") @@ -147,6 +170,21 @@ protected HttpClient getClient() { return getPrivateFieldValue(HttpCommandExecutor.class, "client", HttpClient.class); } + /** + * Override the http client in the HttpCommandExecutor class with a new http client instance with the given URL. + * It uses the same http client factory and client config for the new http client instance + * if the constructor got them. + * @param serverUrl A url to override. + */ + protected void overrideServerUrl(URL serverUrl) { + if (this.appiumClientConfig == null) { + return; + } + setPrivateFieldValue(HttpCommandExecutor.class, "client", + ofNullable(this.httpClientFactory).orElseGet(AppiumCommandExecutor::getDefaultClientFactory) + .createClient(this.appiumClientConfig.baseUrl(serverUrl))); + } + private Response createSession(Command command) throws IOException { if (getCommandCodec() != null) { throw new SessionNotCreatedException("Session already exists"); @@ -166,13 +204,45 @@ private Response createSession(Command command) throws IOException { setCommandCodec(new AppiumW3CHttpCommandCodec()); refreshAdditionalCommands(); setResponseCodec(dialect.getResponseCodec()); - return result.createResponse(); + Response response = result.createResponse(); + if (this.appiumClientConfig != null && this.appiumClientConfig.isDirectConnectEnabled()) { + setDirectConnect(response); + } + + return response; } public void refreshAdditionalCommands() { getAdditionalCommands().forEach(this::defineCommand); } + @SuppressWarnings("unchecked") + private void setDirectConnect(Response response) throws SessionNotCreatedException { + Map responseValue = (Map) response.getValue(); + + DirectConnect directConnect = new DirectConnect(responseValue); + + if (!directConnect.isValid()) { + return; + } + + if (!directConnect.getProtocol().equals("https")) { + throw new SessionNotCreatedException( + String.format("The given protocol '%s' as the direct connection url returned by " + + "the remote server is not accurate. Only 'https' is supported.", + directConnect.getProtocol())); + } + + URL newUrl; + try { + newUrl = directConnect.getUrl(); + } catch (MalformedURLException e) { + throw new SessionNotCreatedException(e.getMessage()); + } + + overrideServerUrl(newUrl); + } + @Override public Response execute(Command command) throws WebDriverException { if (DriverCommand.NEW_SESSION.equals(command.getName())) { diff --git a/src/main/java/io/appium/java_client/remote/DirectConnect.java b/src/main/java/io/appium/java_client/remote/DirectConnect.java new file mode 100644 index 000000000..a2049c589 --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/DirectConnect.java @@ -0,0 +1,77 @@ +package io.appium.java_client.remote; + +import javax.annotation.Nullable; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; + +// TODO: simplify with lombok as another PR +public class DirectConnect { + private static final String DIRECT_CONNECT_PROTOCOL = "directConnectProtocol"; + private static final String DIRECT_CONNECT_PATH = "directConnectPath"; + private static final String DIRECT_CONNECT_HOST = "directConnectHost"; + private static final String DIRECT_CONNECT_PORT = "directConnectPort"; + + private final String protocol; + + private final String path; + + private final String host; + + private final String port; + + /** + * Create a DirectConnect instance. + * @param responseValue is the response body + */ + public DirectConnect(Map responseValue) { + this.protocol = this.getDirectConnectValue(responseValue, DIRECT_CONNECT_PROTOCOL); + this.path = this.getDirectConnectValue(responseValue, DIRECT_CONNECT_PATH); + this.host = this.getDirectConnectValue(responseValue, DIRECT_CONNECT_HOST); + this.port = this.getDirectConnectValue(responseValue, DIRECT_CONNECT_PORT); + } + + public String getProtocol() { + return protocol; + } + + @Nullable + private String getDirectConnectValue(Map responseValue, String key) { + Object directConnectPath = responseValue.get(APPIUM_PREFIX + key); + if (directConnectPath != null) { + return String.valueOf(directConnectPath); + } + directConnectPath = responseValue.get(key); + return directConnectPath == null ? null : String.valueOf(directConnectPath); + } + + /** + * Returns true if the {@link DirectConnect} instance member has nonnull values. + * @return true if each connection information has a nonnull value + */ + public boolean isValid() { + return Stream.of(this.protocol, this.path, this.host, this.port).noneMatch(Objects::isNull); + } + + /** + * Returns a URL instance built with members in the DirectConnect instance. + * @return A URL object + * @throws MalformedURLException if the built url was invalid + */ + public URL getUrl() throws MalformedURLException { + String newUrlCandidate = String.format("%s://%s:%s%s", this.protocol, this.host, this.port, this.path); + + try { + return new URL(newUrlCandidate); + } catch (MalformedURLException e) { + throw new MalformedURLException( + String.format("The remote server returned an invalid value to build the direct connect URL: %s", + newUrlCandidate) + ); + } + } +} diff --git a/src/main/java/io/appium/java_client/safari/SafariDriver.java b/src/main/java/io/appium/java_client/safari/SafariDriver.java index 0b8a8400d..97d1f96e4 100644 --- a/src/main/java/io/appium/java_client/safari/SafariDriver.java +++ b/src/main/java/io/appium/java_client/safari/SafariDriver.java @@ -16,6 +16,7 @@ package io.appium.java_client.safari; +import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -102,7 +103,32 @@ public SafariDriver(HttpClient.Factory httpClientFactory, Capabilities capabilit * */ public SafariDriver(ClientConfig clientConfig, Capabilities capabilities) { - super(clientConfig, ensurePlatformAndAutomationNames( + super(AppiumClientConfig.fromClientConfig(clientConfig), ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * SafariOptions options = new SafariOptions();
+     * SafariDriver driver = new SafariDriver(appiumClientConfig, options);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public SafariDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensurePlatformAndAutomationNames( capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 82af6e02d..9a441d68a 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -16,6 +16,7 @@ package io.appium.java_client.windows; +import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.MobileCommand; import io.appium.java_client.PerformsTouchActions; @@ -45,6 +46,7 @@ public WindowsDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + public WindowsDriver(URL remoteAddress, Capabilities capabilities) { super(remoteAddress, ensurePlatformAndAutomationNames( capabilities, PLATFORM_NAME, AUTOMATION_NAME)); @@ -100,7 +102,32 @@ public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities capabili * */ public WindowsDriver(ClientConfig clientConfig, Capabilities capabilities) { - super(clientConfig, ensurePlatformAndAutomationNames( + super(AppiumClientConfig.fromClientConfig(clientConfig), ensurePlatformAndAutomationNames( + capabilities, PLATFORM_NAME, AUTOMATION_NAME)); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * WindowsOptions options = new WindowsOptions();
+     * WindowsDriver driver = new WindowsDriver(appiumClientConfig, options);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public WindowsDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensurePlatformAndAutomationNames( capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java index 5316f56e4..01104b988 100644 --- a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -202,10 +202,6 @@ public Timeouts timeouts() { return null; } - public ImeHandler ime() { - return null; - } - public Window window() { return new StubWindow(); } diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index df8611458..05559de27 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -9,13 +9,14 @@ import org.junit.jupiter.api.Test; class ConfigTest { - private static final String EXISTING_KEY = "selenium.version"; + private static final String SELENIUM_EXISTING_KEY = "selenium.version"; + private static final String MISSING_KEY = "bla"; @Test void verifyGettingExistingValue() { - assertThat(Config.main().getValue(EXISTING_KEY, String.class).length(), greaterThan(0)); - assertTrue(Config.main().getOptionalValue(EXISTING_KEY, String.class).isPresent()); + assertThat(Config.main().getValue(SELENIUM_EXISTING_KEY, String.class).length(), greaterThan(0)); + assertTrue(Config.main().getOptionalValue(SELENIUM_EXISTING_KEY, String.class).isPresent()); } @Test @@ -25,7 +26,7 @@ void verifyGettingNonExistingValue() { @Test void verifyGettingExistingValueWithWrongClass() { - assertThrows(ClassCastException.class, () -> Config.main().getValue(EXISTING_KEY, Integer.class)); + assertThrows(ClassCastException.class, () -> Config.main().getValue(SELENIUM_EXISTING_KEY, Integer.class)); } @Test diff --git a/src/test/java/io/appium/java_client/internal/DirectConnectTest.java b/src/test/java/io/appium/java_client/internal/DirectConnectTest.java new file mode 100644 index 000000000..93b345474 --- /dev/null +++ b/src/test/java/io/appium/java_client/internal/DirectConnectTest.java @@ -0,0 +1,56 @@ +package io.appium.java_client.internal; + +import io.appium.java_client.remote.DirectConnect; +import org.junit.jupiter.api.Test; + +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class DirectConnectTest { + + @Test + void hasValidDirectConnectValuesWithoutAppiumPrefix() throws MalformedURLException { + Map responseValue = new HashMap<>(); + responseValue.put("directConnectProtocol", "https"); + responseValue.put("directConnectPath", "/path/to"); + responseValue.put("directConnectHost", "host"); + responseValue.put("directConnectPort", "8080"); + DirectConnect directConnect = new DirectConnect(responseValue); + assertTrue(directConnect.isValid()); + assertEquals(directConnect.getUrl().toString(), "https://host:8080/path/to"); + } + + @Test + void hasValidDirectConnectValuesWithAppiumPrefix() throws MalformedURLException { + Map responseValue = new HashMap<>(); + responseValue.put("appium:directConnectProtocol", "https"); + responseValue.put("appium:directConnectPath", "/path/to"); + responseValue.put("appium:directConnectHost", "host"); + responseValue.put("appium:directConnectPort", "8080"); + DirectConnect directConnect = new DirectConnect(responseValue); + assertTrue(directConnect.isValid()); + assertEquals(directConnect.getUrl().toString(), "https://host:8080/path/to"); + } + + @Test + void hasValidDirectConnectStringPort() { + Map responseValue = new HashMap<>(); + responseValue.put("appium:directConnectProtocol", "https"); + responseValue.put("appium:directConnectPath", "/path/to"); + responseValue.put("appium:directConnectHost", "host"); + responseValue.put("appium:directConnectPort", "port"); + DirectConnect directConnect = new DirectConnect(responseValue); + assertTrue(directConnect.isValid()); + assertThrowsExactly(MalformedURLException.class, directConnect::getUrl); + } + + @Test + void hasInvalidDirectConnect() { + Map responseValue = new HashMap<>(); + DirectConnect directConnect = new DirectConnect(responseValue); + assertFalse(directConnect.isValid()); + } +} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index bea245a99..f71d1d8c4 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -173,11 +173,6 @@ public Timeouts pageLoadTimeout(long time, TimeUnit unit) { }; } - @Override - public ImeHandler ime() { - return null; - } - @Override public Window window() { return null; From f185039f9f75e86e041320324e314b9f1b655d71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 15:47:45 +0300 Subject: [PATCH 133/501] build(deps): bump org.owasp.dependencycheck from 7.2.1 to 7.3.0 (#1780) Bumps org.owasp.dependencycheck from 7.2.1 to 7.3.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b0116c43b..58f80d652 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.2.1' + id 'org.owasp.dependencycheck' version '7.3.0' id 'com.github.johnrengelman.shadow' version '7.1.2' } From b5c9e39487d60c56e45bc3e59f14912d7791b77e Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 27 Oct 2022 23:24:53 +0300 Subject: [PATCH 134/501] fix: Enforce usage of Base64 compliant with RFC 4648 for all operations (#1785) --- build.gradle | 1 - .../java/io/appium/java_client/ComparesImages.java | 14 +++++++------- .../java/io/appium/java_client/PushesFiles.java | 4 ++-- .../imagecomparison/ComparisonResult.java | 4 ++-- .../java_client/android/AndroidDriverTest.java | 4 ++-- .../java_client/android/ImagesComparisonTest.java | 9 +++++---- .../java_client/ios/ImagesComparisonTest.java | 9 +++++---- 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index 58f80d652..54be347a1 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,6 @@ dependencies { } } implementation 'com.google.code.gson:gson:2.9.1' - implementation 'commons-codec:commons-codec:1.15' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' diff --git a/src/main/java/io/appium/java_client/ComparesImages.java b/src/main/java/io/appium/java_client/ComparesImages.java index 3cb85036c..c1c97abc9 100644 --- a/src/main/java/io/appium/java_client/ComparesImages.java +++ b/src/main/java/io/appium/java_client/ComparesImages.java @@ -25,11 +25,11 @@ import io.appium.java_client.imagecomparison.OccurrenceMatchingResult; import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; +import java.util.Base64; import java.util.Map; import javax.annotation.Nullable; @@ -93,8 +93,8 @@ default FeaturesMatchingResult matchImagesFeatures(File image1, File image2) thr */ default FeaturesMatchingResult matchImagesFeatures(File image1, File image2, @Nullable FeaturesMatchingOptions options) throws IOException { - return matchImagesFeatures(Base64.encodeBase64(FileUtils.readFileToByteArray(image1)), - Base64.encodeBase64(FileUtils.readFileToByteArray(image2)), options); + return matchImagesFeatures(Base64.getEncoder().encode(FileUtils.readFileToByteArray(image1)), + Base64.getEncoder().encode(FileUtils.readFileToByteArray(image2)), options); } /** @@ -160,8 +160,8 @@ default OccurrenceMatchingResult findImageOccurrence(File fullImage, File partia default OccurrenceMatchingResult findImageOccurrence(File fullImage, File partialImage, @Nullable OccurrenceMatchingOptions options) throws IOException { - return findImageOccurrence(Base64.encodeBase64(FileUtils.readFileToByteArray(fullImage)), - Base64.encodeBase64(FileUtils.readFileToByteArray(partialImage)), options); + return findImageOccurrence(Base64.getEncoder().encode(FileUtils.readFileToByteArray(fullImage)), + Base64.getEncoder().encode(FileUtils.readFileToByteArray(partialImage)), options); } /** @@ -227,7 +227,7 @@ default SimilarityMatchingResult getImagesSimilarity(File image1, File image2) t default SimilarityMatchingResult getImagesSimilarity(File image1, File image2, @Nullable SimilarityMatchingOptions options) throws IOException { - return getImagesSimilarity(Base64.encodeBase64(FileUtils.readFileToByteArray(image1)), - Base64.encodeBase64(FileUtils.readFileToByteArray(image2)), options); + return getImagesSimilarity(Base64.getEncoder().encode(FileUtils.readFileToByteArray(image1)), + Base64.getEncoder().encode(FileUtils.readFileToByteArray(image2)), options); } } \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java index d6da2ca82..a79e58ba9 100644 --- a/src/main/java/io/appium/java_client/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -19,11 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.pushFileCommand; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; +import java.util.Base64; public interface PushesFiles extends ExecutesMethod { @@ -57,7 +57,7 @@ default void pushFile(String remotePath, File file) throws IOException { throw new IOException(String.format("The given file %s doesn't exist", file.getAbsolutePath())); } - pushFile(remotePath, Base64.encodeBase64(FileUtils.readFileToByteArray(file))); + pushFile(remotePath, Base64.getEncoder().encode(FileUtils.readFileToByteArray(file))); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java index 1dcfa3e68..1ad0639b3 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java @@ -18,7 +18,6 @@ import lombok.AccessLevel; import lombok.Getter; -import org.apache.commons.codec.binary.Base64; import org.openqa.selenium.Point; import org.openqa.selenium.Rectangle; @@ -28,6 +27,7 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.Map; public abstract class ComparisonResult { @@ -70,7 +70,7 @@ public byte[] getVisualization() { * @throws IOException On file system I/O error. */ public void storeVisualization(File destination) throws IOException { - final byte[] data = Base64.decodeBase64(getVisualization()); + final byte[] data = Base64.getDecoder().decode(getVisualization()); try (OutputStream stream = new FileOutputStream(destination)) { stream.write(data); } diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index 145bd32dc..f2e502781 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -27,7 +27,6 @@ import static org.junit.jupiter.api.Assertions.fail; import io.appium.java_client.appmanagement.ApplicationState; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; @@ -37,6 +36,7 @@ import java.io.File; import java.time.Duration; import java.util.ArrayList; +import java.util.Base64; import java.util.List; public class AndroidDriverTest extends BaseAndroidTest { @@ -155,7 +155,7 @@ public void closeAppTest() { @Test public void pushFileTest() { - byte[] data = Base64.encodeBase64( + byte[] data = Base64.getEncoder().encode( "The eventual code is no more than the deposit of your understanding. ~E. W. Dijkstra" .getBytes()); driver.pushFile("/data/local/tmp/remote.txt", data); diff --git a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java b/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java index adc8795ea..e49463b87 100644 --- a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java +++ b/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java @@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.util.Base64; + import io.appium.java_client.imagecomparison.FeatureDetector; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; import io.appium.java_client.imagecomparison.FeaturesMatchingResult; @@ -30,7 +32,6 @@ import io.appium.java_client.imagecomparison.OccurrenceMatchingResult; import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; -import org.apache.commons.codec.binary.Base64; import org.junit.jupiter.api.Test; import org.openqa.selenium.OutputType; @@ -38,7 +39,7 @@ public class ImagesComparisonTest extends BaseAndroidTest { @Test public void verifyFeaturesMatching() { - byte[] screenshot = Base64.encodeBase64(driver.getScreenshotAs(OutputType.BYTES)); + byte[] screenshot = Base64.getEncoder().encode(driver.getScreenshotAs(OutputType.BYTES)); FeaturesMatchingResult result = driver .matchImagesFeatures(screenshot, screenshot, new FeaturesMatchingOptions() .withDetectorName(FeatureDetector.ORB) @@ -56,7 +57,7 @@ public void verifyFeaturesMatching() { @Test public void verifyOccurrencesLookup() { - byte[] screenshot = Base64.encodeBase64(driver.getScreenshotAs(OutputType.BYTES)); + byte[] screenshot = Base64.getEncoder().encode(driver.getScreenshotAs(OutputType.BYTES)); OccurrenceMatchingResult result = driver .findImageOccurrence(screenshot, screenshot, new OccurrenceMatchingOptions() .withEnabledVisualization()); @@ -66,7 +67,7 @@ public void verifyOccurrencesLookup() { @Test public void verifySimilarityCalculation() { - byte[] screenshot = Base64.encodeBase64(driver.getScreenshotAs(OutputType.BYTES)); + byte[] screenshot = Base64.getEncoder().encode(driver.getScreenshotAs(OutputType.BYTES)); SimilarityMatchingResult result = driver .getImagesSimilarity(screenshot, screenshot, new SimilarityMatchingOptions() .withEnabledVisualization()); diff --git a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java b/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java index ef52196b5..d724b4ecb 100644 --- a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java +++ b/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java @@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.util.Base64; + import io.appium.java_client.imagecomparison.FeatureDetector; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; import io.appium.java_client.imagecomparison.FeaturesMatchingResult; @@ -30,7 +32,6 @@ import io.appium.java_client.imagecomparison.OccurrenceMatchingResult; import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; -import org.apache.commons.codec.binary.Base64; import org.junit.jupiter.api.Test; import org.openqa.selenium.OutputType; @@ -38,7 +39,7 @@ public class ImagesComparisonTest extends AppIOSTest { @Test public void verifyFeaturesMatching() { - byte[] screenshot = Base64.encodeBase64(driver.getScreenshotAs(OutputType.BYTES)); + byte[] screenshot = Base64.getEncoder().encode(driver.getScreenshotAs(OutputType.BYTES)); FeaturesMatchingResult result = driver .matchImagesFeatures(screenshot, screenshot, new FeaturesMatchingOptions() .withDetectorName(FeatureDetector.ORB) @@ -56,7 +57,7 @@ public void verifyFeaturesMatching() { @Test public void verifyOccurrencesSearch() { - byte[] screenshot = Base64.encodeBase64(driver.getScreenshotAs(OutputType.BYTES)); + byte[] screenshot = Base64.getEncoder().encode(driver.getScreenshotAs(OutputType.BYTES)); OccurrenceMatchingResult result = driver .findImageOccurrence(screenshot, screenshot, new OccurrenceMatchingOptions() .withEnabledVisualization()); @@ -66,7 +67,7 @@ public void verifyOccurrencesSearch() { @Test public void verifySimilarityCalculation() { - byte[] screenshot = Base64.encodeBase64(driver.getScreenshotAs(OutputType.BYTES)); + byte[] screenshot = Base64.getEncoder().encode(driver.getScreenshotAs(OutputType.BYTES)); SimilarityMatchingResult result = driver .getImagesSimilarity(screenshot, screenshot, new SimilarityMatchingOptions() .withEnabledVisualization()); From c7dcb1bf2e8e7cecea0ff1a23625211d6aaae84d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 29 Oct 2022 20:06:11 +0200 Subject: [PATCH 135/501] fix: Override getScreenshotAs to support the legacy base64 encoding (#1787) --- .../io/appium/java_client/AppiumDriver.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index d814657c6..450822a69 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -31,6 +31,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.OutputType; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; @@ -270,4 +271,24 @@ public Response execute(String driverCommand, Map parameters) { public Response execute(String command) { return super.execute(command, Collections.emptyMap()); } + + @Override + public X getScreenshotAs(OutputType outputType) { + // TODO: Eventually we should not override this method. + // TODO: Although, we have a legacy burden, + // TODO: so it's impossible to do it the other way as of Oct 29 2022. + // TODO: See https://github.com/SeleniumHQ/selenium/issues/11168 + return super.getScreenshotAs(new OutputType() { + @Override + public X convertFromBase64Png(String base64Png) { + String rfc4648Base64 = base64Png.replaceAll("\\r?\\n", ""); + return outputType.convertFromBase64Png(rfc4648Base64); + } + + @Override + public X convertFromPngBytes(byte[] png) { + return outputType.convertFromPngBytes(png); + } + }); + } } From cca6268ff8c4708f065571361b69f25c80f25a09 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 31 Oct 2022 00:08:56 -0700 Subject: [PATCH 136/501] feat: use own User Agent (#1779) * refer to com.google.common.net.HttpHeaders * tweak the logic to include UA * use parameterized test * use parameterized more, defined const * modify the logic to customize the UA, add tests * match as case insensitive * tweak, fixed addHeader not to add headers twice * add annotation * define a method to build UA --- build.gradle | 6 +- gradle.properties | 2 + .../java_client/AppiumClientConfig.java | 3 +- .../java_client/AppiumUserAgentFilter.java | 91 +++++++++++++++++++ .../remote/AppiumCommandExecutor.java | 4 + src/main/resources/main.properties | 1 + .../internal/AppiumUserAgentFilterTest.java | 67 ++++++++++++++ .../java_client/internal/ConfigTest.java | 23 +++-- 8 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 src/main/java/io/appium/java_client/AppiumUserAgentFilter.java create mode 100644 src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java diff --git a/build.gradle b/build.gradle index 54be347a1..51e50d861 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ java { ext { seleniumVersion = project.property('selenium.version') + appiumClientVersion = project.property('appiumClient.version') } dependencies { @@ -110,7 +111,7 @@ publishing { mavenJava(MavenPublication) { groupId = 'io.appium' artifactId = 'java-client' - version = '8.2.0' + version = appiumClientVersion from components.java pom { name = 'java-client' @@ -186,7 +187,8 @@ wrapper { processResources { filter ReplaceTokens, tokens: [ - 'selenium.version': seleniumVersion + 'selenium.version': seleniumVersion, + 'appiumClient.version': appiumClientVersion ] } diff --git a/gradle.properties b/gradle.properties index 9b086f575..239efd600 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,3 +8,5 @@ ossrhUsername=your-jira-id ossrhPassword=your-jira-password selenium.version=4.5.0 +# Please increment the value in a release +appiumClient.version=8.2.0 diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java index 2e6128c03..317d85314 100644 --- a/src/main/java/io/appium/java_client/AppiumClientConfig.java +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -18,7 +18,6 @@ import org.openqa.selenium.Credentials; import org.openqa.selenium.internal.Require; -import org.openqa.selenium.remote.http.AddSeleniumUserAgent; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.Filter; @@ -34,7 +33,7 @@ public class AppiumClientConfig extends ClientConfig { private final boolean directConnect; - private static final Filter DEFAULT_FILTER = new AddSeleniumUserAgent(); + private static final Filter DEFAULT_FILTER = new AppiumUserAgentFilter(); private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofMinutes(10); diff --git a/src/main/java/io/appium/java_client/AppiumUserAgentFilter.java b/src/main/java/io/appium/java_client/AppiumUserAgentFilter.java new file mode 100644 index 000000000..a36da9d08 --- /dev/null +++ b/src/main/java/io/appium/java_client/AppiumUserAgentFilter.java @@ -0,0 +1,91 @@ +/* + * 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 com.google.common.annotations.VisibleForTesting; +import com.google.common.net.HttpHeaders; +import io.appium.java_client.internal.Config; +import org.openqa.selenium.remote.http.AddSeleniumUserAgent; +import org.openqa.selenium.remote.http.Filter; +import org.openqa.selenium.remote.http.HttpHandler; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Manage Appium Client configurations. + */ + +public class AppiumUserAgentFilter implements Filter { + + public static final String VERSION_KEY = "appiumClient.version"; + + private static final String USER_AGENT_PREFIX = "appium/"; + + /** + * A default User Agent name for Appium Java client. + * e.g. appium/8.2.0 (selenium/4.5.0 (java mac)) + */ + public static final String USER_AGENT = buildUserAgentHeaderValue(AddSeleniumUserAgent.USER_AGENT); + + private static String buildUserAgentHeaderValue(@Nonnull String previousUA) { + return String.format("%s%s (%s)", + USER_AGENT_PREFIX, Config.main().getValue(VERSION_KEY, String.class), previousUA); + } + + /** + * Returns true if the given User Agent includes "appium/", which + * implies the User Agent already has the Appium UA by this method. + * The matching is case-insensitive. + * @param userAgent the User Agent in the request headers. + * @return whether the given User Agent includes Appium UA + * like by this filter. + */ + @VisibleForTesting + public static boolean containsAppiumName(@Nullable String userAgent) { + return userAgent != null && userAgent.toLowerCase().contains(USER_AGENT_PREFIX.toLowerCase()); + } + + /** + * Returns the User Agent. If the given UA already has + * {@link USER_AGENT_PREFIX}, it returns the UA. + * IF the given UA does not have {@link USER_AGENT_PREFIX}, + * it returns UA with the Appium prefix. + * @param userAgent the User Agent in the request headers. + * @return the User Agent for the request + */ + public static String buildUserAgent(@Nullable String userAgent) { + if (userAgent == null) { + return USER_AGENT; + } + + if (containsAppiumName(userAgent)) { + return userAgent; + } + + return buildUserAgentHeaderValue(userAgent); + } + + @Override + public HttpHandler apply(HttpHandler next) { + + return req -> { + req.setHeader(HttpHeaders.USER_AGENT, buildUserAgent(req.getHeader(HttpHeaders.USER_AGENT))); + return next.execute(req); + }; + } +} diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index ec792852a..43ce9fc01 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -24,6 +24,8 @@ import com.google.common.base.Supplier; import com.google.common.base.Throwables; +import com.google.common.net.HttpHeaders; +import io.appium.java_client.AppiumUserAgentFilter; import io.appium.java_client.AppiumClientConfig; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; @@ -192,6 +194,8 @@ private Response createSession(Command command) throws IOException { ProtocolHandshake.Result result = new AppiumProtocolHandshake().createSession( getClient().with((httpHandler) -> (req) -> { + req.setHeader(HttpHeaders.USER_AGENT, + AppiumUserAgentFilter.buildUserAgent(req.getHeader(HttpHeaders.USER_AGENT))); req.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); return httpHandler.execute(req); }), command diff --git a/src/main/resources/main.properties b/src/main/resources/main.properties index a4236a9fe..9875b0c49 100644 --- a/src/main/resources/main.properties +++ b/src/main/resources/main.properties @@ -1 +1,2 @@ selenium.version=@selenium.version@ +appiumClient.version=@appiumClient.version@ diff --git a/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java b/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java new file mode 100644 index 000000000..10e33a1ee --- /dev/null +++ b/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java @@ -0,0 +1,67 @@ +package io.appium.java_client.internal; + +import io.appium.java_client.AppiumUserAgentFilter; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +public class AppiumUserAgentFilterTest { + @Test + void validateUserAgent() { + assertTrue(AppiumUserAgentFilter.USER_AGENT.startsWith("appium/")); + } + + public static Stream userAgentParams() { + return Stream.of( + Arguments.of("selenium/4.5.0 (java mac)", false), + Arguments.of("appium/8.2.0 (selenium/4.5.0 (java mac))", true), + Arguments.of("APPIUM/8.2.0 (selenium/4.5.0 (java mac))", true), + Arguments.of("something (Appium/8.2.0 (selenium/4.5.0 (java mac)))", true), + Arguments.of("something (appium/8.2.0 (selenium/4.5.0 (java mac)))", true) + ); + } + + @ParameterizedTest + @MethodSource("userAgentParams") + void validUserAgentIfContainsAppiumName(String userAgent, boolean expected) { + assertEquals(AppiumUserAgentFilter.containsAppiumName(userAgent), expected); + } + + @Test + void validBuildUserAgentNoUA() { + assertEquals(AppiumUserAgentFilter.buildUserAgent(null), AppiumUserAgentFilter.USER_AGENT); + } + + @Test + void validBuildUserAgentNoAppium1() { + String ua = AppiumUserAgentFilter.buildUserAgent("selenium/4.5.0 (java mac)"); + assertTrue(ua.startsWith("appium/")); + assertTrue(ua.endsWith("selenium/4.5.0 (java mac))")); + } + + @Test + void validBuildUserAgentNoAppium2() { + String ua = AppiumUserAgentFilter.buildUserAgent("customSelenium/4.5.0 (java mac)"); + assertTrue(ua.startsWith("appium/")); + assertTrue(ua.endsWith("customSelenium/4.5.0 (java mac))")); + } + + @Test + void validBuildUserAgentAlreadyHasAppium1() { + // Won't modify since the UA already has appium prefix + String ua = AppiumUserAgentFilter.buildUserAgent("appium/8.1.0 (selenium/4.5.0 (java mac))"); + assertEquals("appium/8.1.0 (selenium/4.5.0 (java mac))", ua); + } + + @Test + void validBuildUserAgentAlreadyHasAppium2() { + // Won't modify since the UA already has appium prefix + String ua = AppiumUserAgentFilter.buildUserAgent("something (appium/8.1.0 (selenium/4.5.0 (java mac)))"); + assertEquals("something (appium/8.1.0 (selenium/4.5.0 (java mac)))", ua); + } +} diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index 05559de27..67518eca7 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -6,17 +6,25 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import io.appium.java_client.AppiumUserAgentFilter; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.stream.Stream; class ConfigTest { private static final String SELENIUM_EXISTING_KEY = "selenium.version"; private static final String MISSING_KEY = "bla"; - @Test - void verifyGettingExistingValue() { - assertThat(Config.main().getValue(SELENIUM_EXISTING_KEY, String.class).length(), greaterThan(0)); - assertTrue(Config.main().getOptionalValue(SELENIUM_EXISTING_KEY, String.class).isPresent()); + @ParameterizedTest + @ValueSource(strings = {SELENIUM_EXISTING_KEY, AppiumUserAgentFilter.VERSION_KEY}) + void verifyGettingExistingValue(String key) { + assertThat(Config.main().getValue(key, String.class).length(), greaterThan(0)); + assertTrue(Config.main().getOptionalValue(key, String.class).isPresent()); } @Test @@ -24,9 +32,10 @@ void verifyGettingNonExistingValue() { assertThrows(IllegalArgumentException.class, () -> Config.main().getValue(MISSING_KEY, String.class)); } - @Test - void verifyGettingExistingValueWithWrongClass() { - assertThrows(ClassCastException.class, () -> Config.main().getValue(SELENIUM_EXISTING_KEY, Integer.class)); + @ParameterizedTest + @ValueSource(strings = {SELENIUM_EXISTING_KEY, AppiumUserAgentFilter.VERSION_KEY}) + void verifyGettingExistingValueWithWrongClass(String key) { + assertThrows(ClassCastException.class, () -> Config.main().getValue(key, Integer.class)); } @Test From 4bb67a59f82d02b3de2be20e8db6604dc8cf2133 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 15:24:10 +0300 Subject: [PATCH 137/501] build(deps): bump gson from 2.9.1 to 2.10 (#1788) Bumps [gson](https://github.com/google/gson) from 2.9.1 to 2.10. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.9.1...gson-parent-2.10) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 51e50d861..bf02a50a4 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ dependencies { prefer "${seleniumVersion}" } } - implementation 'com.google.code.gson:gson:2.9.1' + implementation 'com.google.code.gson:gson:2.10' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' From abee0bd396e6404c6503351b878b338f73c77ef9 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 1 Nov 2022 14:17:48 -0700 Subject: [PATCH 138/501] chore: use Lombok (#1789) * chore: use Lambok * Update src/main/java/io/appium/java_client/remote/DirectConnect.java Co-authored-by: Valery Yatsynovich Co-authored-by: Valery Yatsynovich --- .../java_client/remote/DirectConnect.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/DirectConnect.java b/src/main/java/io/appium/java_client/remote/DirectConnect.java index a2049c589..bfd0f4129 100644 --- a/src/main/java/io/appium/java_client/remote/DirectConnect.java +++ b/src/main/java/io/appium/java_client/remote/DirectConnect.java @@ -1,5 +1,9 @@ package io.appium.java_client.remote; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.Accessors; + import javax.annotation.Nullable; import java.net.MalformedURLException; import java.net.URL; @@ -9,20 +13,20 @@ import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; -// TODO: simplify with lombok as another PR +@Accessors public class DirectConnect { private static final String DIRECT_CONNECT_PROTOCOL = "directConnectProtocol"; private static final String DIRECT_CONNECT_PATH = "directConnectPath"; private static final String DIRECT_CONNECT_HOST = "directConnectHost"; private static final String DIRECT_CONNECT_PORT = "directConnectPort"; - private final String protocol; + @Getter(AccessLevel.PUBLIC) private final String protocol; - private final String path; + @Getter(AccessLevel.PUBLIC) private final String path; - private final String host; + @Getter(AccessLevel.PUBLIC) private final String host; - private final String port; + @Getter(AccessLevel.PUBLIC) private final String port; /** * Create a DirectConnect instance. @@ -35,10 +39,6 @@ public DirectConnect(Map responseValue) { this.port = this.getDirectConnectValue(responseValue, DIRECT_CONNECT_PORT); } - public String getProtocol() { - return protocol; - } - @Nullable private String getDirectConnectValue(Map responseValue, String key) { Object directConnectPath = responseValue.get(APPIUM_PREFIX + key); From 57ce03be427466e57a71f30a9174ebc08fd0d60d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 3 Nov 2022 14:40:34 +0100 Subject: [PATCH 139/501] feat: Add alternative proxy implementation (#1790) --- build.gradle | 1 + docs/The-event_firing.md | 82 ++++++++- .../io/appium/java_client/proxy/Helpers.java | 157 ++++++++++++++++++ .../appium/java_client/proxy/Interceptor.java | 129 ++++++++++++++ .../java_client/proxy/MethodCallListener.java | 82 +++++++++ .../proxy/NotImplementedException.java | 20 +++ .../java_client/proxy/ProxyHelpersTest.java | 136 +++++++++++++++ 7 files changed, 606 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/appium/java_client/proxy/Helpers.java create mode 100644 src/main/java/io/appium/java_client/proxy/Interceptor.java create mode 100644 src/main/java/io/appium/java_client/proxy/MethodCallListener.java create mode 100644 src/main/java/io/appium/java_client/proxy/NotImplementedException.java create mode 100644 src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java diff --git a/build.gradle b/build.gradle index bf02a50a4..8918b815d 100644 --- a/build.gradle +++ b/build.gradle @@ -198,6 +198,7 @@ task unitTest( type: Test ) { testLogging.exceptionFormat = 'full' filter { includeTestsMatching 'io.appium.java_client.internal.*' + includeTestsMatching 'io.appium.java_client.proxy.*' } } diff --git a/docs/The-event_firing.md b/docs/The-event_firing.md index 7fa0a58d6..527fddeb8 100644 --- a/docs/The-event_firing.md +++ b/docs/The-event_firing.md @@ -3,7 +3,7 @@ since v8.0.0 # The purpose This feature allows end user to organize the event logging on the client side. -Also this feature may be useful in a binding with standard or custom reporting +Also, this feature may be useful in a binding with standard or custom reporting frameworks. The feature has been introduced first since Selenium API v4. # The API @@ -40,6 +40,7 @@ Listeners should implement WebDriverListener. It supports three types of events: To use this decorator you have to prepare a listener, create a decorator using this listener, decorate the original WebDriver instance with this decorator and use the new WebDriver instance created by the decorator instead of the original one: + ```java WebDriver original = new AndroidDriver(); // it is expected that MyListener class implements WebDriverListener @@ -66,6 +67,7 @@ decorated.get("http://example.com/"); WebElement header = decorated.findElement(By.tagName("h1")); // if an error happens during any of these calls the the onError event is fired ``` + The instance of WebDriver created by the decorator implements all the same interfaces as the original driver. A listener can subscribe to "specific" or "generic" events (or both). A "specific" event correspond to a single specific method, a "generic" event correspond to any @@ -74,3 +76,81 @@ implement a method with a name derived from the target method to be watched. The for "before"-events receive the parameters passed to the decorated method. The listener methods for "after"-events receive the parameters passed to the decorated method as well as the result returned by this method. + +## createProxy API (since Java Client 8.3.0) + +This API is unique to Appium Java Client and does not exist in Selenium. The reason for +its existence is the fact that the original event listeners API provided by Selenium is limited +because it can only use interface types for decorator objects. For example, the code below won't +work: + +```java +IOSDriver driver = new IOSDriver(new URL("http://doesnot.matter/"), new ImmutableCapabilities()) +{ + @Override + protected void startSession(Capabilities capabilities) + { + // Override in a sake of simplicity to avoid the actual session start + } +}; +WebDriverListener webDriverListener = new WebDriverListener() +{ +}; +IOSDriver decoratedDriver = (IOSDriver) new EventFiringDecorator(IOSDriver.class, webDriverListener).decorate( + driver); +``` + +The last line throws `ClassCastException` because `decoratedDriver` is of type `IOSDriver`, +which is a class rather than an interface. +See the issue [#1694](https://github.com/appium/java-client/issues/1694) for more +details. In order to workaround this limitation a special proxy implementation has been created, +which is capable of decorating class types: + +```java +import io.appium.java_client.proxy.MethodCallListener; +import io.appium.java_client.proxy.NotImplementedException; + +import static io.appium.java_client.proxy.Helpers.createProxy; + +// ... + +MethodCallListener listener = new MethodCallListener() { + @Override + public void beforeCall(Object target, Method method, Object[] args) { + if (!method.getName().equals("get")) { + throw new NotImplementedException(); + } + acc.append("beforeCall ").append(method.getName()).append("\n"); + } + + @Override + public void afterCall(Object target, Method method, Object[] args, Object result) { + if (!method.getName().equals("get")) { + throw new NotImplementedException(); + } + acc.append("afterCall ").append(method.getName()).append("\n"); + } +}; + +IOSDriver decoratedDriver = createProxy( + IOSDriver.class, + new Object[] {new URL("http://localhost:4723/"), new XCUITestOptions()}, + new Class[] {URL.class, Capabilities.class}, + listener +); + +decoratedDriver.get("http://example.com/"); + +assertThat(acc.toString().trim()).isEqualTo( + String.join("\n", + "beforeCall get", + "afterCall get" + ) +); +``` + +This proxy is not tied to WebDriver descendants and could be used to any classes that have +**public** constructors. It also allows to intercept exceptions thrown by **public** class methods and/or +change/replace the original methods behavior. It is important to know that callbacks are **not** invoked +for methods derived from the standard `Object` class, like `toString` or `equals`. +Check [unit tests](../src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java) for more examples. diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java new file mode 100644 index 000000000..286d7fc31 --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -0,0 +1,157 @@ +/* + * 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.proxy; + +import com.google.common.base.Preconditions; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.MethodDelegation; +import net.bytebuddy.matcher.ElementMatchers; + +import java.util.Collection; +import java.util.Collections; + +public class Helpers { + private Helpers() { + } + + /** + * Creates a transparent proxy instance for the given class. + * It is possible to provide one or more method execution listeners + * or replace particular method calls completely. Callbacks + * defined in these listeners are going to be called when any + * **public** method of the given class is invoked. Overridden callbacks + * are expected to be skipped if they throw + * {@link io.appium.java_client.proxy.NotImplementedException}. + * + * @param cls the class to which the proxy should be created. + * Must not be an interface. + * @param constructorArgs Array of constructor arguments. Could be an + * empty array if the class provides a constructor without arguments. + * @param constructorArgTypes Array of constructor argument types. Must + * represent types of constructorArgs. + * @param listeners One or more method invocation listeners. + * @param Any class derived from Object + * @return Proxy instance + */ + public static T createProxy( + Class cls, + Object[] constructorArgs, + Class[] constructorArgTypes, + Collection listeners + ) { + Preconditions.checkArgument(constructorArgs.length == constructorArgTypes.length, + String.format( + "Constructor arguments array length %d must be equal to the types array length %d", + constructorArgs.length, constructorArgTypes.length + ) + ); + Preconditions.checkArgument(!listeners.isEmpty(), "The collection of listeners must not be empty"); + Preconditions.checkArgument(cls != null, "Class must not be null"); + Preconditions.checkArgument(!cls.isInterface(), "Class must not be an interface"); + + //noinspection resource + Class proxy = new ByteBuddy() + .subclass(cls) + .method(ElementMatchers.isPublic() + .and(ElementMatchers.not( + ElementMatchers.isDeclaredBy(Object.class) + .or(ElementMatchers.isOverriddenFrom(Object.class)) + ))) + .intercept(MethodDelegation.to(Interceptor.class)) + .make() + .load(cls.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) + .getLoaded() + .asSubclass(cls); + + try { + //noinspection unchecked + T instance = (T) proxy + .getConstructor(constructorArgTypes) + .newInstance(constructorArgs); + Interceptor.LISTENERS.put(instance, listeners); + return instance; + } catch (SecurityException | ReflectiveOperationException e) { + throw new IllegalStateException(String.format("Unable to create a proxy of %s", cls.getName()), e); + } + } + + /** + * Creates a transparent proxy instance for the given class. + * It is possible to provide one or more method execution listeners + * or replace particular method calls completely. Callbacks + * defined in these listeners are going to be called when any + * **public** method of the given class is invoked. Overridden callbacks + * are expected to be skipped if they throw NotImplementedException. + * + * @param cls the class to which the proxy should be created. + * Must not be an interface. Must expose a constructor + * without arguments. + * @param listeners One or more method invocation listeners. + * @param Any class derived from Object + * @return Proxy instance + */ + public static T createProxy(Class cls, Collection listeners) { + return createProxy(cls, new Object[]{}, new Class[]{}, listeners); + } + + /** + * Creates a transparent proxy instance for the given class. + * It is possible to provide one or more method execution listeners + * or replace particular method calls completely. Callbacks + * defined in these listeners are going to be called when any + * **public** method of the given class is invoked. Overridden callbacks + * are expected to be skipped if they throw NotImplementedException. + * + * @param cls the class to which the proxy should be created. + * Must not be an interface. Must expose a constructor + * without arguments. + * @param listener Method invocation listener. + * @param Any class derived from Object + * @return Proxy instance + */ + public static T createProxy(Class cls, MethodCallListener listener) { + return createProxy(cls, new Object[]{}, new Class[]{}, Collections.singletonList(listener)); + } + + /** + * Creates a transparent proxy instance for the given class. + * It is possible to provide one or more method execution listeners + * or replace particular method calls completely. Callbacks + * defined in these listeners are going to be called when any + * **public** method of the given class is invoked. Overridden callbacks + * are expected to be skipped if they throw NotImplementedException. + * + * @param cls the class to which the proxy should be created. + * Must not be an interface. + * @param constructorArgs Array of constructor arguments. Could be an + * empty array if the class provides a constructor without arguments. + * @param constructorArgTypes Array of constructor argument types. Must + * represent types of constructorArgs. + * @param listener Method invocation listener. + * @param Any class derived from Object + * @return Proxy instance + */ + public static T createProxy( + Class cls, + Object[] constructorArgs, + Class[] constructorArgTypes, + MethodCallListener listener + ) { + return createProxy(cls, constructorArgs, constructorArgTypes, Collections.singletonList(listener)); + } +} diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java new file mode 100644 index 000000000..921b86124 --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -0,0 +1,129 @@ +/* + * 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.proxy; + +import net.bytebuddy.implementation.bind.annotation.AllArguments; +import net.bytebuddy.implementation.bind.annotation.Origin; +import net.bytebuddy.implementation.bind.annotation.RuntimeType; +import net.bytebuddy.implementation.bind.annotation.SuperCall; +import net.bytebuddy.implementation.bind.annotation.This; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.WeakHashMap; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Interceptor { + private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); + public static final Map> LISTENERS = new WeakHashMap<>(); + private static final Set OBJECT_METHOD_NAMES = Stream.of(Object.class.getMethods()) + .map(Method::getName) + .collect(Collectors.toSet()); + + /** + * A magic method used to wrap public method calls in classes + * patched by ByteBuddy and acting as proxies. + * + * @param self The reference to the original instance. + * @param method The reference to the original method. + * @param args The reference to method args. + * @param callable The reference to the non-patched callable to avoid call recursion. + * @return Either the original method result or the patched one. + */ + @RuntimeType + public static Object intercept( + @This Object self, + @Origin Method method, + @AllArguments Object[] args, + @SuperCall Callable callable + ) throws Throwable { + if (OBJECT_METHOD_NAMES.contains(method.getName())) { + return callable.call(); + } + Collection listeners = LISTENERS.get(self); + if (listeners == null || listeners.isEmpty()) { + return callable.call(); + } + + listeners.forEach(listener -> { + try { + listener.beforeCall(self, method, args); + } catch (NotImplementedException e) { + // ignore + } catch (Exception e) { + logger.error( + String.format("Got an unexpected error in beforeCall listener of %s.%s method", + self.getClass().getName(), method.getName()), e + ); + } + }); + + final UUID noResult = UUID.randomUUID(); + Object result = noResult; + for (MethodCallListener listener : listeners) { + try { + result = listener.call(self, method, args, callable); + break; + } catch (NotImplementedException e) { + // ignore + } catch (Exception e) { + try { + return listener.onError(self, method, args, e); + } catch (NotImplementedException ignore) { + // ignore + } + throw e; + } + } + if (noResult.equals(result)) { + try { + result = callable.call(); + } catch (Exception e) { + for (MethodCallListener listener : listeners) { + try { + return listener.onError(self, method, args, e); + } catch (NotImplementedException ignore) { + // ignore + } + } + throw e; + } + } + + final Object endResult = result == noResult ? null : result; + listeners.forEach(listener -> { + try { + listener.afterCall(self, method, args, endResult); + } catch (NotImplementedException e) { + // ignore + } catch (Exception e) { + logger.error( + String.format("Got an unexpected error in afterCall listener of %s.%s method", + self.getClass().getName(), method.getName()), e + ); + } + }); + return endResult; + } +} diff --git a/src/main/java/io/appium/java_client/proxy/MethodCallListener.java b/src/main/java/io/appium/java_client/proxy/MethodCallListener.java new file mode 100644 index 000000000..f0cc1be7a --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/MethodCallListener.java @@ -0,0 +1,82 @@ +/* + * 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.proxy; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +public interface MethodCallListener { + + /** + * The callback to be invoked before any public method of the proxy is called. + * The implementation is not expected to throw any exceptions. If a + * runtime exception is thrown then it is going to be silently logged. + * + * @param obj The proxy instance + * @param method Method to be called + * @param args Array of method arguments + */ + default void beforeCall(Object obj, Method method, Object[] args) { + throw new NotImplementedException(); + } + + /** + * Override this callback in order to change/customize the behavior + * of a single or multiple methods. The original method result + * will be replaced with the result returned by this callback. + * Also, any exception thrown by it will replace original method(s) + * exception. + * + * @param obj The proxy instance + * @param method Method to be replaced + * @param args Array of method arguments + * @param original The reference to the original method in case it is necessary to instrument its result. + * @return The type of the returned result should be castable to the returned type of the original method. + */ + default Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { + throw new NotImplementedException(); + } + + /** + * The callback to be invoked after any public method of the proxy is called. + * The implementation is not expected to throw any exceptions. If a + * runtime exception is thrown then it is going to be silently logged. + * + * @param obj The proxy instance + * @param method Method to be called + * @param args Array of method arguments + */ + default void afterCall(Object obj, Method method, Object[] args, Object result) { + throw new NotImplementedException(); + } + + /** + * The callback to be invoked if a public method or its + * {@link #call(Object, Method, Object[], Callable) Call} replacement throws an exception. + * + * @param obj The proxy instance + * @param method Method to be called + * @param args Array of method arguments + * @param e Exception instance thrown by the original method invocation. + * @return You could either (re)throw the exception in this callback or + * overwrite the behavior and return a result from it. It is expected that the + * type of the returned argument could be cast to the returned type of the original method. + */ + default Object onError(Object obj, Method method, Object[] args, Throwable e) throws Throwable { + throw new NotImplementedException(); + } +} diff --git a/src/main/java/io/appium/java_client/proxy/NotImplementedException.java b/src/main/java/io/appium/java_client/proxy/NotImplementedException.java new file mode 100644 index 000000000..861c114c8 --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/NotImplementedException.java @@ -0,0 +1,20 @@ +/* + * 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.proxy; + +public class NotImplementedException extends RuntimeException { +} diff --git a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java new file mode 100644 index 000000000..fc389b6c6 --- /dev/null +++ b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java @@ -0,0 +1,136 @@ +/* + * 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.proxy; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.UnreachableBrowserException; + +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.concurrent.Callable; + +import static io.appium.java_client.proxy.Helpers.createProxy; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ProxyHelpersTest { + + public static class FakeIOSDriver extends IOSDriver { + public FakeIOSDriver(URL url, Capabilities caps) { + super(url, caps); + } + + @Override + protected void startSession(Capabilities capabilities) {} + } + + @Test + void shouldFireBeforeAndAfterEvents() { + final StringBuilder acc = new StringBuilder(); + MethodCallListener listener = new MethodCallListener() { + @Override + public void beforeCall(Object target, Method method, Object[] args) { + acc.append("beforeCall ").append(method.getName()).append("\n"); + // should be ignored + throw new IllegalStateException(); + } + + @Override + public void afterCall(Object target, Method method, Object[] args, Object result) { + acc.append("afterCall ").append(method.getName()).append("\n"); + // should be ignored + throw new IllegalStateException(); + } + }; + RemoteWebDriver driver = createProxy(RemoteWebDriver.class, Collections.singletonList(listener)); + + assertThrows( + UnreachableBrowserException.class, + () -> driver.get("http://example.com/") + ); + + assertThat(acc.toString().trim(), is(equalTo( + String.join("\n", + "beforeCall get", + "beforeCall getSessionId", + "afterCall getSessionId", + "beforeCall getCapabilities", + "afterCall getCapabilities", + "beforeCall getCapabilities", + "afterCall getCapabilities") + ))); + } + + @Test + void shouldFireErrorEvents() { + MethodCallListener listener = new MethodCallListener() { + @Override + public Object onError(Object obj, Method method, Object[] args, Throwable e) { + throw new IllegalStateException(); + } + }; + RemoteWebDriver driver = createProxy(RemoteWebDriver.class, Collections.singletonList(listener)); + + assertThrows( + IllegalStateException.class, + () -> driver.get("http://example.com/") + ); + } + + @Test + void shouldFireCallEvents() throws MalformedURLException { + final StringBuilder acc = new StringBuilder(); + MethodCallListener listener = new MethodCallListener() { + @Override + public Object call(Object obj, Method method, Object[] args, Callable original) { + acc.append("onCall ").append(method.getName()).append("\n"); + throw new IllegalStateException(); + } + + @Override + public Object onError(Object obj, Method method, Object[] args, Throwable e) throws Throwable { + acc.append("onError ").append(method.getName()).append("\n"); + throw e; + } + }; + FakeIOSDriver driver = createProxy( + FakeIOSDriver.class, + new Object[] {new URL("http://localhost:4723/"), new XCUITestOptions()}, + new Class[] {URL.class, Capabilities.class}, + listener + ); + + assertThrows( + IllegalStateException.class, + () -> driver.get("http://example.com/") + ); + + assertThat(acc.toString().trim(), is(equalTo( + String.join("\n", + "onCall get", + "onError get") + ))); + } +} From e0ab871e6b8de72fc9d376a58fe1e24a26c7c9fe Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 3 Nov 2022 17:35:42 +0100 Subject: [PATCH 140/501] docs: Update readme and remove obsolete documents (#1792) --- README.md | 170 +++++++++++++++--- docs/Functions.md | 147 --------------- docs/Page-objects.md | 5 +- docs/Tech-stack.md | 19 -- docs/The-starting-of-an-Android-app.md | 156 ---------------- ...um-node-server-started-programmatically.md | 25 +-- docs/The-starting-of-an-iOS-app.md | 122 ------------- docs/Touch-actions.md | 44 ----- 8 files changed, 153 insertions(+), 535 deletions(-) delete mode 100644 docs/Functions.md delete mode 100644 docs/Tech-stack.md delete mode 100644 docs/The-starting-of-an-Android-app.md delete mode 100644 docs/The-starting-of-an-iOS-app.md delete mode 100644 docs/Touch-actions.md diff --git a/README.md b/README.md index 6af5f0be8..e2da9ca63 100644 --- a/README.md +++ b/README.md @@ -4,31 +4,48 @@ [![Javadocs](https://www.javadoc.io/badge/io.appium/java-client.svg)](https://www.javadoc.io/doc/io.appium/java-client) [![Build Status](https://travis-ci.org/appium/java-client.svg?branch=master)](https://travis-ci.org/appium/java-client) -This is the Java language binding for writing Appium Tests, conforms to [Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) +This is the Java language bindings for writing Appium Tests that conform to [WebDriver Protocol](https://w3c.github.io/webdriver/) -[API docs](https://www.javadoc.io/doc/io.appium/java-client) +## v8 Migration -### Features and other interesting information +Since version 8 Appium Java Client had several major changes, which might require to +update your client code. Make sure to follow the [v7 to v8 Migration Guide](https://github.com/appium/java-client/blob/master/docs/v7-to-v8-migration-guide.md) +in order to streamline the migration process. -[Tech stack](https://github.com/appium/java-client/blob/master/docs/Tech-stack.md) +## Add Appium java client to your test framework -[How to install the project](https://github.com/appium/java-client/blob/master/docs/Installing-the-project.md) +### Stable -[WIKI](https://github.com/appium/java-client/wiki) +#### Maven -## v8 Migration +Add the following to pom.xml: -Since version 8 Appium Java Client had several major changes, which might require to -update your client code. Make sure to follow the [v7 to v8 Migration Guide](https://github.com/appium/java-client/blob/master/docs/v7-to-v8-migration-guide.md) -in order to streamline the migration process. +```xml + + io.appium + java-client + ${version.you.require} + test + +``` + +#### Gradle + +Add the following to build.gradle: + +```groovy +dependencies { + testImplementation 'io.appium:java-client:${version.you.require}' +} +``` -## How to install latest java client Beta/Snapshots +### Beta/Snapshots Java client project is available to use even before it is officially published to maven central. Refer [jitpack.io](https://jitpack.io/#appium/java-client) -### Maven +#### Maven - - Add the following to pom.xml: +Add the following to pom.xml: ```xml @@ -39,7 +56,7 @@ Java client project is available to use even before it is officially published t ``` - - Add the dependency: +Add the dependency: ```xml @@ -49,27 +66,140 @@ Java client project is available to use even before it is officially published t ``` -### Gradle +#### Gradle - - Add the JitPack repository to your build file. Add it in your root build.gradle at the end of repositories: +Add the JitPack repository to your build file. Add it in your root build.gradle at the end of repositories: -``` +```groovy allprojects { repositories { - ... + // ... maven { url 'https://jitpack.io' } } } ``` - - Add the dependency: +Add the dependency: -``` +```groovy dependencies { implementation 'com.github.appium:java-client:latest commit id from master branch' } ``` +## Drivers Support + +Appium java client has dedicated classes to support the following Appium drivers: + +- [UiAutomator2](https://github.com/appium/appium-uiautomator2-driver) and [Espresso](https://github.com/appium/appium-espresso-driver): [AndroidDriver](src/main/java/io/appium/java_client/android/AndroidDriver.java) +- [XCUITest](https://github.com/appium/appium-xcuitest-driver): [IOSDriver](src/main/java/io/appium/java_client/ios/IOSDriver.java) +- [Windows](https://github.com/appium/appium-windows-driver): [WindowsDriver](src/main/java/io/appium/java_client/windows/WindowsDriver.java) +- [Safari](https://github.com/appium/appium-safari-driver): [SafariDriver](src/main/java/io/appium/java_client/safari/SafariDriver.java) +- [Gecko](https://github.com/appium/appium-geckodriver): [GeckoDriver](src/main/java/io/appium/java_client/gecko/GeckoDriver.java) +- [Mac2](https://github.com/appium/appium-mac2-driver): [Mac2Driver](src/main/java/io/appium/java_client/mac/Mac2Driver.java) + +To automate other platforms that are not listed above you could use +[AppiumDriver](src/main/java/io/appium/java_client/AppiumDriver.java) or its custom derivatives. + +Appium java client is built on top of Selenium and implements same interfaces that the foundation +[RemoteWebDriver](https://github.com/SeleniumHQ/selenium/blob/trunk/java/src/org/openqa/selenium/remote/RemoteWebDriver.java) +does. However, Selenium lib is mostly focused on web browsers automation while +Appium is universal and covers wide range of possible platforms, e.g. mobile and desktop +operating systems, IOT devices, etc. Thus, the foundation `AppiumDriver` class in this package +extends `RemoteWebDriver` with additional features, and makes it more flexible, so it is not so +strictly focused on web-browser related operations. + +## Appium Server Service Wrapper + +Appium java client provides a dedicated class to control Appium server execution. +The class is [AppiumDriverLocalService](src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java). +It allows to run and verify the Appium server **locally** from your test framework code +and provides several convenient shortcuts. The service could be used as below: + +```java +AppiumDriverLocalService service = AppiumDriverLocalService.buildDefaultService(); +service.start(); +try { + // do stuff with drivers +} finally { + service.stop(); +} +``` + +You could customize the service behavior, for example, provide custom +command line arguments or change paths to server executables +using [AppiumServiceBuilder](src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java) + +**Note** + +> AppiumDriverLocalService does not support the server management on non-local hosts + +## Usage Examples + +### UiAutomator2 + +```java +UiAutomator2Options options = new UiAutomator2Options() + .setUdid('123456') + .setApp("/home/myapp.apk"); +AndroidDriver driver = new AndroidDriver( + // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub + new URL("http://127.0.0.1:4723"), options +); +try { + WebElement el = driver.findElement(AppiumBy.xpath, "//Button"); + el.click(); + driver.getPageSource(); +} finally { + driver.quit(); +} +``` + +### XCUITest + +```java +XCUITestOptions options = new XCUITestOptions() + .setUdid('123456') + .setApp("/home/myapp.ipa"); +IOSDriver driver = new IOSDriver( + // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub + new URL("http://127.0.0.1:4723"), options +); +try { + WebElement el = driver.findElement(AppiumBy.accessibilityId, "myId"); + el.click(); + driver.getPageSource(); +} finally { + driver.quit(); +} +``` + +### Any generic driver that does not have a dedicated class + +```java +BaseOptions options = new BaseOptions() + .setPlatformName("myplatform") + .setAutomationName("mydriver") + .amend("mycapability1", "capvalue1") + .amend("mycapability2", "capvalue2"); +AppiumDriver driver = new AppiumDriver( + // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub + new URL("http://127.0.0.1:4723"), options +); +try { + WebElement el = driver.findElement(AppiumBy.className, "myClass"); + el.click(); + driver.getPageSource(); +} finally { + driver.quit(); +} +``` + +Check the corresponding driver's READMEs to know the list of capabilities and features it supports. + +You could find much more code examples by checking client's +[unit and integration tests](src/test/java/io/appium/java_client). + ## Changelog *8.2.0* - **[ENHANCEMENTS]** diff --git a/docs/Functions.md b/docs/Functions.md deleted file mode 100644 index bdf962f7c..000000000 --- a/docs/Functions.md +++ /dev/null @@ -1,147 +0,0 @@ -Appium java client has some features based on [Java 8 Functional interfaces](https://www.oreilly.com/learning/java-8-functional-interfaces). - -# Conditions - -```java -io.appium.java_client.functions.AppiumFunction -``` -It extends -```java -java.util.function.Function -``` -and -```java -com.google.common.base.Function -``` -to make end user available to use _org.openqa.selenium.support.ui.Wait_. There is additional interface -```java -io.appium.java_client.functions.ExpectedCondition -``` -which extends -```java -io.appium.java_client.functions.AppiumFunction -``` - -and - -```java -org.openqa.selenium.support.ui.ExpectedCondition -``` - -This feature provides the ability to create complex condition of the waiting for something. - -```java -//waiting for elements - private final AppiumFunction> searchingFunction = input -> { - List result = input.findElements(By.tagName("a")); - - if (result.size() > 0) { - return result; - } - return null; -}; - -//waiting for some context using regular expression pattern -private final AppiumFunction contextFunction = input -> { - Set contexts = driver.getContextHandles(); - String current = driver.getContext(); - contexts.forEach(context -> { - Matcher m = input.matcher(context); - if (m.find()) { - driver.context(context); - } - }); - if (!current.equals(driver.getContext())) { - return driver; - } - return null; -}; -``` - -## using one function as pre-condition - -```java -@Test public void tezt() { - .... - Wait wait = new FluentWait<>(Pattern.compile("WEBVIEW")) - .withTimeout(30, TimeUnit.SECONDS); - List elements = wait.until(searchingFunction.compose(contextFunction)); - .... -} -``` - -## using one function as post-condition - -```java -import org.openqa.selenium.support.ui.FluentWait; -import org.openqa.selenium.support.ui.Wait; - -@Test public void tezt() { - .... - Wait wait = new FluentWait<>(Pattern.compile("WEBVIEW")) - .withTimeout(30, TimeUnit.SECONDS); - List elements = wait.until(contextFunction.andThen(searchingFunction)); - .... -} -``` - -# Touch action supplier - -[About touch actions](https://github.com/appium/java-client/blob/master/docs/Touch-actions.md) - -You can use suppliers to declare touch/multitouch actions for some screens/tests. Also it is possible to -create gesture libraries/utils using suppliers. Appium java client provides this interface - -```java -io.appium.java_client.functions.ActionSupplier -``` - -## Samples - -```java -private final ActionSupplier horizontalSwipe = () -> { - driver.findElementById("io.appium.android.apis:id/gallery"); - - AndroidElement gallery = driver.findElementById("io.appium.android.apis:id/gallery"); - List images = gallery - .findElementsByClassName("android.widget.ImageView"); - Point location = gallery.getLocation(); - Point center = gallery.getCenter(); - - return new TouchAction(driver).press(images.get(2), -10, center.y - location.y) - .waitAction(2000).moveTo(gallery, 10, center.y - location.y).release(); -}; - -private final ActionSupplier verticalSwiping = () -> - new TouchAction(driver).press(driver.findElementByAccessibilityId("Gallery")) - .waitAction(2000).moveTo(driver.findElementByAccessibilityId("Auto Complete")).release(); - -@Test public void tezt() { - ... - horizontalSwipe.get().perform(); - ... - verticalSwiping.get().perform(); - ... -} -``` - -```java -public class GestureUtils { - - public static ActionSupplier swipe(final AppiumDriver driver, final params) { - return () -> { - new TouchAction(driver).press(params) - .waitAction(params).moveTo(params).release(); - }; - } -} - -public class SomeTest { - @Test public void tezt() { - ... - GestureUtils.swipe(driver, params).get().perform(); - ... - } -} - -``` \ No newline at end of file diff --git a/docs/Page-objects.md b/docs/Page-objects.md index 7bc36a267..ce7a04f1f 100644 --- a/docs/Page-objects.md +++ b/docs/Page-objects.md @@ -46,16 +46,15 @@ List someElements; # The example for the crossplatform mobile native testing ```java -import io.appium.java_client.MobileElement; import io.appium.java_client.pagefactory.*; @AndroidFindBy(someStrategy) @iOSFindBy(someStrategy) -MobileElement someElement; +WebElement someElement; @AndroidFindBy(someStrategy) //for the crossplatform mobile native @iOSFindBy(someStrategy) //testing -List someElements; +List someElements; ``` # The fully cross platform example diff --git a/docs/Tech-stack.md b/docs/Tech-stack.md deleted file mode 100644 index cbaa01b2e..000000000 --- a/docs/Tech-stack.md +++ /dev/null @@ -1,19 +0,0 @@ -![](https://cloud.githubusercontent.com/assets/4927589/21467582/df8ab94e-ca03-11e6-969c-c6d30c6add67.png) -![](https://cloud.githubusercontent.com/assets/4927589/21467509/a97e084e-ca01-11e6-9d04-4f2b8e1c72df.png) -![](https://cloud.githubusercontent.com/assets/4927589/21467524/187a333a-ca02-11e6-8e3c-14c411448fdb.png) -![](https://cloud.githubusercontent.com/assets/4927589/21467531/6f576f1a-ca02-11e6-9f2b-2551ea0e0753.png) + **AspectJ** and **CGlib** - -This project is based on [Selenium java client](https://github.com/SeleniumHQ/selenium/tree/master/java/client). It already depends on it and extends it to mobile platforms. - -This project is built by [gradle](https://gradle.org/) - -Also tech stack includes [Spring framework](https://spring.io/projects/spring-framework) in binding with AspectJ. This is used by [event firing feature](https://github.com/appium/java-client/blob/master/docs/The-event_firing.md). Also **CGlib** is used by [Page Object tools](https://github.com/appium/java-client/blob/master/docs/Page-objects.md). - -It is the client framework. It is the thin client which just sends requests to Appium server and receives responses. Also it has some -high-level features which were designed to simplify user's work. - -# It supports: - -![](https://cloud.githubusercontent.com/assets/4927589/21467612/4b6b3f70-ca05-11e6-9a31-d3820e98dac6.png) -![](https://cloud.githubusercontent.com/assets/4927589/21467614/73883828-ca05-11e6-846d-3ed8847a7e08.jpg) -![](https://cloud.githubusercontent.com/assets/4927589/21467621/aab3ff6c-ca05-11e6-9170-2e7a19d3307c.png) \ No newline at end of file diff --git a/docs/The-starting-of-an-Android-app.md b/docs/The-starting-of-an-Android-app.md deleted file mode 100644 index 466756677..000000000 --- a/docs/The-starting-of-an-Android-app.md +++ /dev/null @@ -1,156 +0,0 @@ -# Steps: - -- you have to prepare environment for Android. [Details are provided here](https://appium.io/docs/en/drivers/android-uiautomator2/#basic-setup) - -- it needs to launch the appium server. You can launch Appium desktop application. If you use the server installed via npm then - - _$ node **the_path_to_main.js_file** --arg1 value1 --arg2 value2_ -It is not necessary to use arguments. [The list of arguments](https://appium.io/docs/en/writing-running-appium/server-args/) - - -# The starting of an app - -It looks like creation of a common [RemoteWebDriver](https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/remote/RemoteWebDriver.html) instance. - -[Common capabilities](https://appium.io/docs/en/writing-running-appium/caps/#general-capabilities) - -[Android-specific capabilities](https://appium.io/docs/en/writing-running-appium/caps/#android-only) - -[Common capabilities provided by Java client](https://javadoc.io/page/io.appium/java-client/latest/io/appium/java_client/remote/MobileCapabilityType.html) - -[Android-specific capabilities provided by Java client](https://javadoc.io/page/io.appium/java-client/latest/io/appium/java_client/remote/AndroidMobileCapabilityType.html) - -```java -import java.io.File; -import org.openqa.selenium.remote.DesiredCapabilities; -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.MobileElement; -import java.net.URL; - -... -File app = new File("The absolute or relative path to an *.apk file"); -DesiredCapabilities capabilities = new DesiredCapabilities(); -capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); -capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); -capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); -//you are free to set additional capabilities -AppiumDriver driver = new AppiumDriver<>( -new URL("http://target_ip:used_port/wd/hub"), //if it needs to use locally started server -//then the target_ip is 127.0.0.1 or 0.0.0.0 -//the default port is 4723 -capabilities); -``` - -or - -```java -import java.io.File; -import org.openqa.selenium.remote.DesiredCapabilities; -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileElement; -import java.net.URL; - -... -File app = new File("The absolute or relative path to an *.apk file"); -DesiredCapabilities capabilities = new DesiredCapabilities(); -capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); -capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); -//you are free to set additional capabilities -AppiumDriver driver = new AndroidDriver<>( -new URL("http://target_ip:used_port/wd/hub"), //if it needs to use locally started server -//then the target_ip is 127.0.0.1 or 0.0.0.0 -//the default port is 4723 -capabilities); -``` - - -## If it needs to start browser then - -This capability should be used - -```java -capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.CHROME); -//if it is necessary to use the default Android browser then MobileBrowserType.BROWSER -//is your choice -``` - -## There are three automation types - -```java -capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.SELENDROID); -``` - -This automation type is usually recommended for old versions (<4.2) of Android. - -Default Android UIAutomator does not require any specific capability. However you can -```java -capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.APPIUM); -``` - -You have to define this automation type to be able to use Android UIAutomator2 for new Android versions -```java -capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2); -``` - -# Possible cases - -You can use ```io.appium.java_client.AppiumDriver``` and ```io.appium.java_client.android.AndroidDriver``` as well. The main difference -is that ```AndroidDriver``` implements all API that describes interaction with Android native/hybrid app. ```AppiumDriver``` allows to -use Android-specific API eventually. - - _The sample of the activity starting by_ ```io.appium.java_client.AppiumDriver``` - - ```java - import io.appium.java_client.android.StartsActivity; - import io.appium.java_client.android.Activity; - -... - -StartsActivity startsActivity = new StartsActivity() { - @Override - public Response execute(String driverCommand, Map parameters) { - return driver.execute(driverCommand, parameters); - } - - @Override - public Response execute(String driverCommand) { - return driver.execute(driverCommand); - } -}; - -Activity activity = new Activity("app package goes here", "app activity goes here") - .setWaitAppPackage("app wait package goes here"); - .setWaitAppActivity("app wait activity goes here"); -StartsActivity startsActivity.startActivity(activity); - ``` - -_Samples of the searching by AndroidUIAutomator using_ ```io.appium.java_client.AppiumDriver``` - -```java -import io.appium.java_client.FindsByAndroidUIAutomator; -import io.appium.java_client.android.AndroidElement; - -... - -FindsByAndroidUIAutomator findsByAndroidUIAutomator = - new FindsByAndroidUIAutomator() { - @Override - public AndroidElement findElement(String by, String using) { - return driver.findElement(by, using); - } - - @Override - public List findElements(String by, String using) { - return driver.findElements(by, using); - }; -}; - -findsByAndroidUIAutomator.findElementByAndroidUIAutomator("automatorString"); -``` - -```java -driver.findElement(MobileBy.AndroidUIAutomator("automatorString")); -``` - -All that ```AndroidDriver``` can do by design. diff --git a/docs/The-starting-of-an-app-using-Appium-node-server-started-programmatically.md b/docs/The-starting-of-an-app-using-Appium-node-server-started-programmatically.md index 5d0fc1e13..9397385c5 100644 --- a/docs/The-starting-of-an-app-using-Appium-node-server-started-programmatically.md +++ b/docs/The-starting-of-an-app-using-Appium-node-server-started-programmatically.md @@ -7,30 +7,6 @@ It works the similar way as common [ChromeDriver](https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/chrome/ChromeDriver.html), [InternetExplorerDriver](https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/ie/InternetExplorerDriver.html) of Selenium project or [PhantomJSDriver](https://cdn.rawgit.com/detro/ghostdriver/master/binding/java/docs/javadoc/org/openqa/selenium/phantomjs/PhantomJSDriver.html). They use subclasses of the [DriverService](https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/remote/service/DriverService.html). -# Which capabilities this feature provides - -This feature provides abilities and options of the starting of a local Appium node server. End users still able to open apps as usual - -```java - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, ""); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); - capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 120); - driver = new AndroidDriver<>(new URL("remoteOrLocalAddress"), capabilities); -``` - -when the server is launched locally\remotely. Also user is free to launch a local Appium node server and open their app for the further testing the following way: - -```java - DesiredCapabilities capabilities = new DesiredCapabilities(); - capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, ""); - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); - capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); - capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 120); - driver = new AndroidDriver<>(capabilities); -``` - # How to prepare the local service before the starting @@ -49,6 +25,7 @@ when the server is launched locally\remotely. Also user is free to launch a loca ### FYI There are possible problems related to local environment which could break this: + ```java AppiumDriverLocalService service = AppiumDriverLocalService.buildDefaultService(); ``` diff --git a/docs/The-starting-of-an-iOS-app.md b/docs/The-starting-of-an-iOS-app.md deleted file mode 100644 index 19b5ba2a0..000000000 --- a/docs/The-starting-of-an-iOS-app.md +++ /dev/null @@ -1,122 +0,0 @@ -# Steps: - -- you have to prepare environment for iOS. [Details are provided here](https://appium.io/docs/en/drivers/ios-xcuitest/#basic-setup) - -- it needs to launch the appium server. You can launch Appium desktop application. If you use the server installed via npm then - - _$ node **the_path_to_js_file** --arg1 value1 --arg2 value2_ -It is not necessary to use arguments. [The list of arguments](https://appium.io/docs/en/writing-running-appium/server-args/) - -# The starting of an app - -It looks like creation of a common [RemoteWebDriver](https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/remote/RemoteWebDriver.html) instance. - -[Common capabilities](https://appium.io/docs/en/writing-running-appium/caps/#general-capabilities) - -[iOS-specific capabilities](https://appium.io/docs/en/writing-running-appium/caps/#ios-only) - -[Common capabilities provided by Java client](https://javadoc.io/page/io.appium/java-client/latest/io/appium/java_client/remote/MobileCapabilityType.html) - -[iOS-specific capabilities provided by Java client](https://javadoc.io/page/io.appium/java-client/latest/io/appium/java_client/remote/IOSMobileCapabilityType.html) - - -```java -import java.io.File; -import org.openqa.selenium.remote.DesiredCapabilities; -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileElement; -import java.net.URL; - -... -File app = new File("The absolute or relative path to an *.app, *.zip or ipa file"); -DesiredCapabilities capabilities = new DesiredCapabilities(); -capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator"); -capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "The_target_version"); -capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS); -//The_target_version is the supported iOS version, e.g. 8.1, 8.2, 9.2 etc -capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); -//you are free to set additional capabilities -AppiumDriver driver = new AppiumDriver<>( -new URL("http://target_ip:used_port/wd/hub"), //if it needs to use locally started server -//then the target_ip is 127.0.0.1 or 0.0.0.0 -//the default port is 4723 -capabilities); -``` - -or - -```java -import java.io.File; -import org.openqa.selenium.remote.DesiredCapabilities; -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.MobileElement; -import java.net.URL; - -... -File app = new File("The absolute or relative path to an *.app, *.zip or ipa file"); -DesiredCapabilities capabilities = new DesiredCapabilities(); -capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator"); -capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "The_target_version"); -//The_target_version is the supported iOS version, e.g. 8.1, 8.2, 9.2 etc -capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); -//you are free to set additional capabilities -AppiumDriver driver = new IOSDriver<>( -new URL("http://target_ip:used_port/wd/hub"), //if it needs to use locally started server -//then the target_ip is 127.0.0.1 or 0.0.0.0 -//the default port is 4723 -capabilities); -``` - -## If it needs to start browser then - -```java -capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.SAFARI); -``` - -## There are two automation types - -Default iOS Automation (v < iOS 10.x) does not require any specific capability. However you can -```java -capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.APPIUM); -``` - -You have to define this automation type to be able to use XCUIT mode for new iOS versions (v > 10.x) -```java -capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); -``` - -# Possible cases - -You can use ```io.appium.java_client.AppiumDriver``` and ```io.appium.java_client.ios.IOSDriver``` as well. The main difference -is that ```IOSDriver``` implements all API that describes interaction with iOS native/hybrid app. ```AppiumDriver``` allows to -use iOS-specific API eventually. - -_Samples of the searching by iOSNsPredicateString using_ ```io.appium.java_client.AppiumDriver``` - -```java -import io.appium.java_client.FindsByIosNSPredicate; -import io.appium.java_client.ios.IOSElement; - -... - -FindsByIosNSPredicate findsByIosNSPredicate = new FindsByIosNSPredicate() { - @Override - public IOSElement findElement(String by, String using) { - return driver.findElement(by, using); - } - - @Override - public List findElements(String by, String using) { - return driver.findElements(by, using); - } -}; - -findsByIosNSPredicate.findElementByIosNsPredicate("some predicate"); -``` - -```java -driver.findElement(MobileBy.iOSNsPredicateString("some predicate")); -``` - -All that ```IOSDriver``` can do by design. diff --git a/docs/Touch-actions.md b/docs/Touch-actions.md deleted file mode 100644 index 920a8d898..000000000 --- a/docs/Touch-actions.md +++ /dev/null @@ -1,44 +0,0 @@ -Appium server side provides abilities to emulate touch actions. It is possible construct single, complex and multiple touch actions. - -# How to use a single touch action - -```java -import io.appium.java_client.TouchAction; - -... -//tap -new TouchAction(driver) - .tap(driver - .findElementById("io.appium.android.apis:id/start")).perform(); -``` - -# How to construct complex actions - -```java -import io.appium.java_client.TouchAction; - -... -//swipe -TouchAction swipe = new TouchAction(driver).press(images.get(2), -10, center.y - location.y) - .waitAction(2000).moveTo(gallery, 10, center.y - location.y).release(); -swipe.perform(); -``` - -# How to construct multiple touch action. - -```java -import io.appium.java_client.TouchAction; -import io.appium.java_client.MultiTouchAction; - -... -//tap by few fingers - MultiTouchAction multiTouch = new MultiTouchAction(driver); - -for (int i = 0; i < fingers; i++) { - TouchAction tap = new TouchAction(driver); - multiTouch.add(tap.press(element).waitAction(duration).release()); -} - -multiTouch.perform(); -``` - From 8f6e2cffb101bf0d34a721ba9cb435e633d59b4c Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 3 Nov 2022 10:29:29 -0700 Subject: [PATCH 141/501] chore: remove unnecessary annotation (#1791) * chore: remove unnecessary annotation * add copyright * remove unused import --- .../java_client/remote/DirectConnect.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/DirectConnect.java b/src/main/java/io/appium/java_client/remote/DirectConnect.java index bfd0f4129..809fdc736 100644 --- a/src/main/java/io/appium/java_client/remote/DirectConnect.java +++ b/src/main/java/io/appium/java_client/remote/DirectConnect.java @@ -1,8 +1,23 @@ +/* + * 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.remote; import lombok.AccessLevel; import lombok.Getter; -import lombok.experimental.Accessors; import javax.annotation.Nullable; import java.net.MalformedURLException; @@ -13,7 +28,6 @@ import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; -@Accessors public class DirectConnect { private static final String DIRECT_CONNECT_PROTOCOL = "directConnectProtocol"; private static final String DIRECT_CONNECT_PATH = "directConnectPath"; From 83f2ac257bd40c6d6edeb8594fa57ce95e5f525d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 4 Nov 2022 14:15:31 +0300 Subject: [PATCH 142/501] chore: Force unified imports order (#1793) --- google-style.xml => appium-style.xml | 27 ++++++++--------- build.gradle | 2 +- .../io/appium/java_client/AppiumDriver.java | 10 +++---- .../java_client/AppiumExecutionMethod.java | 1 - .../appium/java_client/AppiumFluentWait.java | 1 - .../io/appium/java_client/ComparesImages.java | 6 ++-- .../appium/java_client/ErrorCodesMobile.java | 1 - .../io/appium/java_client/HasAppStrings.java | 6 ++-- .../io/appium/java_client/HasDeviceTime.java | 5 ++-- .../io/appium/java_client/HasSettings.java | 6 ++-- .../appium/java_client/InteractsWithApps.java | 21 +++++++------- .../io/appium/java_client/LocksDevice.java | 4 +-- .../io/appium/java_client/LogsEvents.java | 13 +++++---- .../java/io/appium/java_client/MobileBy.java | 4 +-- .../io/appium/java_client/MobileCommand.java | 3 +- .../appium/java_client/MultiTouchAction.java | 6 ++-- .../java_client/PerformsTouchActions.java | 6 ++-- .../io/appium/java_client/PullsFiles.java | 7 ++--- .../io/appium/java_client/PushesFiles.java | 6 ++-- .../appium/java_client/ScreenshotState.java | 7 ++--- .../io/appium/java_client/TouchAction.java | 9 +++--- .../java_client/android/AndroidDriver.java | 13 ++++----- .../android/AndroidMobileCommandHelper.java | 6 ++-- .../AndroidStartScreenRecordingOptions.java | 5 ++-- .../android/AuthenticatesByFinger.java | 4 +-- .../android/HasAndroidClipboard.java | 8 ++--- .../android/HasAndroidDeviceDetails.java | 6 ++-- .../HasSupportedPerformanceDataType.java | 6 ++-- .../android/ListensToLogcatMessages.java | 7 ++--- .../java_client/android/StartsActivity.java | 6 ++-- .../SupportsNetworkStateManagement.java | 6 ++-- .../SupportsSpecialEmulatorCommands.java | 6 ++-- .../AndroidInstallApplicationOptions.java | 9 +++--- .../AndroidRemoveApplicationOptions.java | 9 +++--- .../AndroidTerminateApplicationOptions.java | 9 +++--- .../connection/HasNetworkConnection.java | 6 ++-- .../android/nativekey/KeyEvent.java | 4 +-- .../android/nativekey/PressesKey.java | 6 ++-- .../android/options/EspressoOptions.java | 4 +-- .../android/options/UiAutomator2Options.java | 6 ++-- .../SupportsAndroidInstallTimeoutOption.java | 2 -- .../java_client/clipboard/HasClipboard.java | 10 +++---- .../BaseComparisonOptions.java | 4 +-- .../imagecomparison/ComparisonResult.java | 1 - .../FeaturesMatchingOptions.java | 6 ++-- .../OccurrenceMatchingOptions.java | 4 +-- .../java_client/ios/HasIOSClipboard.java | 6 ++-- .../io/appium/java_client/ios/IOSDriver.java | 9 +++--- .../ios/IOSMobileCommandHelper.java | 1 - .../ios/IOSStartScreenRecordingOptions.java | 7 ++--- .../ios/ListensToSyslogMessages.java | 7 ++--- .../java_client/ios/PerformsTouchID.java | 6 ++-- .../appium/java_client/ios/ShakesDevice.java | 4 +-- .../ios/touch/IOSPressOptions.java | 4 +-- .../pagefactory/AndroidFindAll.java | 8 ++--- .../pagefactory/AndroidFindBy.java | 8 ++--- .../pagefactory/AndroidFindByAllSet.java | 6 ++-- .../pagefactory/AndroidFindByChainSet.java | 6 ++-- .../pagefactory/AndroidFindBySet.java | 6 ++-- .../pagefactory/AndroidFindBys.java | 8 ++--- .../pagefactory/AppiumElementLocator.java | 13 ++++----- .../AppiumElementLocatorFactory.java | 8 ++--- .../pagefactory/AppiumFieldDecorator.java | 9 +++--- .../pagefactory/DefaultElementByBuilder.java | 8 ++--- .../pagefactory/ElementInterceptor.java | 4 +-- .../pagefactory/ElementListInterceptor.java | 4 +-- .../pagefactory/OverrideWidgetReader.java | 11 ++++--- .../java_client/pagefactory/Widget.java | 4 +-- .../pagefactory/WidgetByBuilder.java | 8 ++--- .../pagefactory/WidgetInterceptor.java | 6 ++-- .../pagefactory/WidgetListInterceptor.java | 8 ++--- .../pagefactory/WindowsFindAll.java | 8 ++--- .../pagefactory/WindowsFindBy.java | 8 ++--- .../pagefactory/WindowsFindByAllSet.java | 6 ++-- .../pagefactory/WindowsFindByChainSet.java | 6 ++-- .../pagefactory/WindowsFindBySet.java | 6 ++-- .../pagefactory/WindowsFindBys.java | 8 ++--- .../pagefactory/bys/ContentMappedBy.java | 8 ++--- .../bys/builder/AppiumByBuilder.java | 12 ++++---- .../pagefactory/bys/builder/ByAll.java | 6 ++-- .../pagefactory/bys/builder/ByChained.java | 4 +-- .../pagefactory/bys/builder/Strategies.java | 13 ++++----- .../pagefactory/iOSXCUITFindAll.java | 8 ++--- .../pagefactory/iOSXCUITFindBy.java | 8 ++--- .../pagefactory/iOSXCUITFindByAllSet.java | 6 ++-- .../pagefactory/iOSXCUITFindByChainSet.java | 6 ++-- .../pagefactory/iOSXCUITFindBySet.java | 6 ++-- .../pagefactory/iOSXCUITFindBys.java | 8 ++--- .../utils/WebDriverUnpackUtility.java | 10 +++---- .../remote/AppiumCommandExecutor.java | 13 ++++----- .../remote/AppiumW3CHttpCommandCodec.java | 8 ++--- .../options/SupportsBrowserVersionOption.java | 2 -- .../BaseScreenRecordingOptions.java | 6 ++-- .../BaseStartScreenRecordingOptions.java | 6 ++-- .../screenrecording/CanRecordScreen.java | 6 ++-- .../ScreenRecordingUploadOptions.java | 6 ++-- .../serverevents/ServerEvents.java | 3 +- .../java_client/serverevents/TimedEvent.java | 3 +- .../local/AppiumDriverLocalService.java | 14 ++++----- .../service/local/AppiumServiceBuilder.java | 11 +++---- .../java_client/touch/LongPressOptions.java | 8 ++--- .../appium/java_client/touch/TapOptions.java | 6 ++-- .../appium/java_client/touch/WaitOptions.java | 6 ++-- .../AbstractOptionCombinedWithPosition.java | 4 +-- .../touch/offset/ElementOption.java | 8 ++--- .../java_client/touch/offset/PointOption.java | 4 +-- .../options/SupportsAppArgumentsOption.java | 1 - .../java_client/ws/StringWebSocketClient.java | 15 +++++----- .../AndroidAbilityToUseSupplierTest.java | 12 ++++---- .../android/AndroidActivityTest.java | 4 +-- .../android/AndroidAppStringsTest.java | 4 +-- .../android/AndroidConnectionTest.java | 6 ++-- .../android/AndroidContextTest.java | 6 ++-- .../android/AndroidDriverTest.java | 20 ++++++------- .../android/AndroidElementTest.java | 8 ++--- .../android/AndroidFunctionTest.java | 14 ++++----- .../android/AndroidLogcatListenerTest.java | 4 +-- .../android/AndroidScreenRecordTest.java | 10 +++---- .../android/AndroidSearchingTest.java | 8 ++--- .../java_client/android/AndroidTouchTest.java | 21 +++++++------- .../java_client/android/BaseAndroidTest.java | 1 - .../java_client/android/BatteryTest.java | 4 +-- .../java_client/android/ClipboardTest.java | 4 +-- .../android/ExecuteCDPCommandTest.java | 1 - .../java_client/android/FingerPrintTest.java | 4 +-- .../android/ImagesComparisonTest.java | 16 +++++----- .../java_client/android/IntentTest.java | 8 ++--- .../java_client/android/KeyCodeTest.java | 8 ++--- .../java_client/android/LogEventTest.java | 8 ++--- .../android/OpenNotificationsTest.java | 6 ++-- .../java_client/android/UIAutomator2Test.java | 6 ++-- .../events/stubs/StubWebElement.java | 5 ++-- .../internal/AppiumUserAgentFilterTest.java | 3 +- .../java_client/internal/ConfigTest.java | 14 ++++----- .../internal/DirectConnectTest.java | 5 +++- .../appium/java_client/ios/ClipboardTest.java | 4 +-- .../appium/java_client/ios/IOSAlertTest.java | 8 ++--- .../java_client/ios/IOSAppStringsTest.java | 4 +-- .../java_client/ios/IOSContextTest.java | 6 ++-- .../appium/java_client/ios/IOSDriverTest.java | 18 ++++++------ .../java_client/ios/IOSElementTest.java | 13 ++++----- .../ios/IOSNativeWebTapSettingTest.java | 8 ++--- .../java_client/ios/IOSScreenRecordTest.java | 8 ++--- .../java_client/ios/IOSSearchingTest.java | 5 ++-- .../ios/IOSSyslogListenerTest.java | 4 +-- .../appium/java_client/ios/IOSTouchTest.java | 18 ++++++------ .../java_client/ios/IOSWebViewTest.java | 8 ++--- .../java_client/ios/ImagesComparisonTest.java | 16 +++++----- .../appium/java_client/ios/RotationTest.java | 4 +-- .../appium/java_client/ios/SettingTest.java | 4 +-- .../AndroidPageObjectTest.java | 17 +++++------ .../DesktopBrowserCompatibilityTest.java | 14 ++++----- .../MobileBrowserCompatibilityTest.java | 4 +-- .../pagefactory_tests/TimeoutTest.java | 24 +++++++-------- .../pagefactory_tests/XCUITModeTest.java | 22 +++++++------- .../widget/tests/AbstractStubWebDriver.java | 16 +++++----- .../widget/tests/DefaultStubWidget.java | 1 - .../widget/tests/StubWebElement.java | 6 ++-- .../widget/tests/WidgetTest.java | 12 ++++---- .../tests/android/AndroidWidgetTest.java | 10 +++---- .../tests/combined/CombinedAppTest.java | 17 ++++++----- .../tests/combined/CombinedWidgetTest.java | 12 ++++---- .../widget/tests/ios/XCUITWidgetTest.java | 10 +++---- .../tests/windows/WindowsWidgetTest.java | 10 +++---- .../service/local/ServerBuilderTest.java | 29 ++++++++++--------- .../local/StartingAppLocallyAndroidTest.java | 15 +++++----- .../local/StartingAppLocallyIosTest.java | 12 ++++---- .../service/local/ThreadSafetyTest.java | 4 +-- .../java_client/touch/FailsWithMatcher.java | 6 ++-- .../java_client/touch/TouchOptionsTests.java | 22 +++++++------- 170 files changed, 649 insertions(+), 692 deletions(-) rename google-style.xml => appium-style.xml (93%) diff --git a/google-style.xml b/appium-style.xml similarity index 93% rename from google-style.xml rename to appium-style.xml index 5762dbafb..03937a66d 100755 --- a/google-style.xml +++ b/appium-style.xml @@ -2,20 +2,10 @@ - - - @@ -41,9 +31,16 @@ - - - + + + + + + + + + + diff --git a/build.gradle b/build.gradle index 8918b815d..b64f8cebb 100644 --- a/build.gradle +++ b/build.gradle @@ -96,7 +96,7 @@ jacocoTestReport.dependsOn test checkstyle { toolVersion = '8.32' - configFile = file("$projectDir/google-style.xml") + configFile = file("$projectDir/appium-style.xml") showViolations = true ignoreFailures = false } diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 450822a69..0c72f9c86 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -16,11 +16,6 @@ package io.appium.java_client; -import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; -import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME; -import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; -import static org.apache.commons.lang3.StringUtils.isBlank; - import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; @@ -51,6 +46,11 @@ import java.util.Collections; import java.util.Map; +import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; +import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME; +import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; +import static org.apache.commons.lang3.StringUtils.isBlank; + /** * Default Appium driver implementation. */ diff --git a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java index 3abe1ef4f..9b9f79cb9 100644 --- a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java +++ b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java @@ -17,7 +17,6 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; - import org.openqa.selenium.remote.ExecuteMethod; import org.openqa.selenium.remote.Response; diff --git a/src/main/java/io/appium/java_client/AppiumFluentWait.java b/src/main/java/io/appium/java_client/AppiumFluentWait.java index 8f197ef47..d914f6c16 100644 --- a/src/main/java/io/appium/java_client/AppiumFluentWait.java +++ b/src/main/java/io/appium/java_client/AppiumFluentWait.java @@ -17,7 +17,6 @@ package io.appium.java_client; import com.google.common.base.Throwables; - import lombok.AccessLevel; import lombok.Getter; import org.openqa.selenium.TimeoutException; diff --git a/src/main/java/io/appium/java_client/ComparesImages.java b/src/main/java/io/appium/java_client/ComparesImages.java index c1c97abc9..4aeefec6a 100644 --- a/src/main/java/io/appium/java_client/ComparesImages.java +++ b/src/main/java/io/appium/java_client/ComparesImages.java @@ -16,8 +16,6 @@ package io.appium.java_client; -import static io.appium.java_client.MobileCommand.compareImagesCommand; - import io.appium.java_client.imagecomparison.ComparisonMode; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; import io.appium.java_client.imagecomparison.FeaturesMatchingResult; @@ -27,11 +25,13 @@ import io.appium.java_client.imagecomparison.SimilarityMatchingResult; import org.apache.commons.io.FileUtils; +import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.util.Base64; import java.util.Map; -import javax.annotation.Nullable; + +import static io.appium.java_client.MobileCommand.compareImagesCommand; public interface ComparesImages extends ExecutesMethod { diff --git a/src/main/java/io/appium/java_client/ErrorCodesMobile.java b/src/main/java/io/appium/java_client/ErrorCodesMobile.java index 924625b08..6e7e66d69 100644 --- a/src/main/java/io/appium/java_client/ErrorCodesMobile.java +++ b/src/main/java/io/appium/java_client/ErrorCodesMobile.java @@ -18,7 +18,6 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; - import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.ErrorCodes; diff --git a/src/main/java/io/appium/java_client/HasAppStrings.java b/src/main/java/io/appium/java_client/HasAppStrings.java index 0c9b3905f..1983d4667 100644 --- a/src/main/java/io/appium/java_client/HasAppStrings.java +++ b/src/main/java/io/appium/java_client/HasAppStrings.java @@ -16,12 +16,12 @@ 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; +import static io.appium.java_client.MobileCommand.GET_STRINGS; +import static io.appium.java_client.MobileCommand.prepareArguments; + public interface HasAppStrings extends ExecutesMethod { /** * Get all defined Strings from an app for the default language. diff --git a/src/main/java/io/appium/java_client/HasDeviceTime.java b/src/main/java/io/appium/java_client/HasDeviceTime.java index fa9df8997..fb9fc59b6 100644 --- a/src/main/java/io/appium/java_client/HasDeviceTime.java +++ b/src/main/java/io/appium/java_client/HasDeviceTime.java @@ -16,16 +16,15 @@ package io.appium.java_client; -import static io.appium.java_client.MobileCommand.GET_DEVICE_TIME; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; - import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.Response; import java.util.Map; +import static io.appium.java_client.MobileCommand.GET_DEVICE_TIME; + public interface HasDeviceTime extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/HasSettings.java b/src/main/java/io/appium/java_client/HasSettings.java index 8210123a7..73befa6f5 100644 --- a/src/main/java/io/appium/java_client/HasSettings.java +++ b/src/main/java/io/appium/java_client/HasSettings.java @@ -16,9 +16,6 @@ package io.appium.java_client; -import static io.appium.java_client.MobileCommand.getSettingsCommand; -import static io.appium.java_client.MobileCommand.setSettingsCommand; - import org.openqa.selenium.remote.Response; import java.util.EnumMap; @@ -26,6 +23,9 @@ import java.util.Map.Entry; import java.util.stream.Collectors; +import static io.appium.java_client.MobileCommand.getSettingsCommand; +import static io.appium.java_client.MobileCommand.setSettingsCommand; + public interface HasSettings extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index f1a15146e..eb73e6e30 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -16,26 +16,25 @@ package io.appium.java_client; -import static io.appium.java_client.MobileCommand.ACTIVATE_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.QUERY_APP_STATE; -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.TERMINATE_APP; -import static io.appium.java_client.MobileCommand.prepareArguments; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.appmanagement.BaseActivateApplicationOptions; import io.appium.java_client.appmanagement.BaseInstallApplicationOptions; import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; +import javax.annotation.Nullable; import java.time.Duration; import java.util.AbstractMap; -import javax.annotation.Nullable; + +import static io.appium.java_client.MobileCommand.ACTIVATE_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.QUERY_APP_STATE; +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.TERMINATE_APP; +import static io.appium.java_client.MobileCommand.prepareArguments; @SuppressWarnings("rawtypes") public interface InteractsWithApps extends ExecutesMethod { diff --git a/src/main/java/io/appium/java_client/LocksDevice.java b/src/main/java/io/appium/java_client/LocksDevice.java index 944624002..ce4d794c8 100644 --- a/src/main/java/io/appium/java_client/LocksDevice.java +++ b/src/main/java/io/appium/java_client/LocksDevice.java @@ -16,12 +16,12 @@ package io.appium.java_client; +import java.time.Duration; + import static io.appium.java_client.MobileCommand.getIsDeviceLockedCommand; import static io.appium.java_client.MobileCommand.lockDeviceCommand; import static io.appium.java_client.MobileCommand.unlockDeviceCommand; -import java.time.Duration; - public interface LocksDevice extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/LogsEvents.java b/src/main/java/io/appium/java_client/LogsEvents.java index 7844b56a6..a29d9eecf 100644 --- a/src/main/java/io/appium/java_client/LogsEvents.java +++ b/src/main/java/io/appium/java_client/LogsEvents.java @@ -16,19 +16,20 @@ package io.appium.java_client; -import static io.appium.java_client.MobileCommand.GET_EVENTS; -import static io.appium.java_client.MobileCommand.LOG_EVENT; - import com.google.common.collect.ImmutableMap; import io.appium.java_client.serverevents.CommandEvent; import io.appium.java_client.serverevents.CustomEvent; -import io.appium.java_client.serverevents.TimedEvent; import io.appium.java_client.serverevents.ServerEvents; +import io.appium.java_client.serverevents.TimedEvent; +import org.openqa.selenium.json.Json; +import org.openqa.selenium.remote.Response; + import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.openqa.selenium.json.Json; -import org.openqa.selenium.remote.Response; + +import static io.appium.java_client.MobileCommand.GET_EVENTS; +import static io.appium.java_client.MobileCommand.LOG_EVENT; public interface LogsEvents extends ExecutesMethod { diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index 65f382ec7..7d30bd855 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -16,10 +16,10 @@ package io.appium.java_client; -import java.io.Serializable; - import org.openqa.selenium.By; +import java.io.Serializable; + /** * Appium locating strategies. * diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 4d20164ad..b87e76949 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -17,7 +17,6 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; - import io.appium.java_client.imagecomparison.BaseComparisonOptions; import io.appium.java_client.imagecomparison.ComparisonMode; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; @@ -26,12 +25,12 @@ import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.http.HttpMethod; +import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.AbstractMap; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nullable; /** * The repository of mobile commands defined in the Mobile JSON diff --git a/src/main/java/io/appium/java_client/MultiTouchAction.java b/src/main/java/io/appium/java_client/MultiTouchAction.java index ac66594dc..1549fbdf5 100644 --- a/src/main/java/io/appium/java_client/MultiTouchAction.java +++ b/src/main/java/io/appium/java_client/MultiTouchAction.java @@ -16,15 +16,15 @@ package io.appium.java_client; -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.stream.Collectors.toList; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.List; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.stream.Collectors.toList; + /** * Used for Webdriver 3 multi-touch gestures * See the Webriver 3 spec https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html diff --git a/src/main/java/io/appium/java_client/PerformsTouchActions.java b/src/main/java/io/appium/java_client/PerformsTouchActions.java index 0ac7776d6..539a38a52 100644 --- a/src/main/java/io/appium/java_client/PerformsTouchActions.java +++ b/src/main/java/io/appium/java_client/PerformsTouchActions.java @@ -16,12 +16,12 @@ package io.appium.java_client; -import static io.appium.java_client.MobileCommand.PERFORM_MULTI_TOUCH; -import static io.appium.java_client.MobileCommand.PERFORM_TOUCH_ACTION; - import java.util.List; import java.util.Map; +import static io.appium.java_client.MobileCommand.PERFORM_MULTI_TOUCH; +import static io.appium.java_client.MobileCommand.PERFORM_TOUCH_ACTION; + /** * Touch actions are deprecated. * Please use W3C Actions instead or the corresponding diff --git a/src/main/java/io/appium/java_client/PullsFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java index 590e4aaa0..f85c18a6e 100644 --- a/src/main/java/io/appium/java_client/PullsFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -16,16 +16,15 @@ package io.appium.java_client; -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 java.nio.charset.StandardCharsets; import java.util.Base64; +import static io.appium.java_client.MobileCommand.PULL_FILE; +import static io.appium.java_client.MobileCommand.PULL_FOLDER; + public interface PullsFiles extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java index a79e58ba9..552c25a83 100644 --- a/src/main/java/io/appium/java_client/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -16,15 +16,15 @@ package io.appium.java_client; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.pushFileCommand; - import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.util.Base64; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.MobileCommand.pushFileCommand; + public interface PushesFiles extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/ScreenshotState.java b/src/main/java/io/appium/java_client/ScreenshotState.java index 5645b79e2..8c88397e5 100644 --- a/src/main/java/io/appium/java_client/ScreenshotState.java +++ b/src/main/java/io/appium/java_client/ScreenshotState.java @@ -21,9 +21,7 @@ import lombok.Setter; import lombok.experimental.Accessors; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - +import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -33,7 +31,8 @@ import java.util.function.Function; import java.util.function.Supplier; -import javax.imageio.ImageIO; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; @Accessors(chain = true) public class ScreenshotState { diff --git a/src/main/java/io/appium/java_client/TouchAction.java b/src/main/java/io/appium/java_client/TouchAction.java index 866e87140..98abeaafb 100644 --- a/src/main/java/io/appium/java_client/TouchAction.java +++ b/src/main/java/io/appium/java_client/TouchAction.java @@ -16,13 +16,8 @@ package io.appium.java_client; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.ImmutableList.builder; -import static java.util.stream.Collectors.toList; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; - import io.appium.java_client.touch.ActionOptions; import io.appium.java_client.touch.LongPressOptions; import io.appium.java_client.touch.TapOptions; @@ -33,6 +28,10 @@ import java.util.List; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.ImmutableList.builder; +import static java.util.stream.Collectors.toList; + /** * Used for Webdriver 3 touch actions * See the Webriver 3 spec 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 92ed19370..f3b812584 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -16,13 +16,7 @@ package io.appium.java_client.android; -import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; @@ -32,9 +26,9 @@ import io.appium.java_client.HasOnScreenKeyboard; import io.appium.java_client.HidesKeyboard; import io.appium.java_client.InteractsWithApps; -import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PullsFiles; import io.appium.java_client.PushesFiles; import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.android.connection.HasNetworkConnection; @@ -59,6 +53,11 @@ import java.util.Collections; import java.util.Map; +import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + /** * Android driver implementation. */ 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 867e96fdd..c5fa63080 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -16,18 +16,16 @@ package io.appium.java_client.android; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.MobileCommand; - import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.remote.RemoteWebElement; import java.util.AbstractMap; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; + /** * This util class helps to prepare parameters of Android-specific JSONWP * commands. diff --git a/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java index c8378a86b..2ef6cdc29 100644 --- a/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java @@ -16,16 +16,15 @@ package io.appium.java_client.android; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import io.appium.java_client.screenrecording.ScreenRecordingUploadOptions; import java.time.Duration; import java.util.Map; +import static java.util.Optional.ofNullable; + public class AndroidStartScreenRecordingOptions extends BaseStartScreenRecordingOptions { private Integer bitRate; diff --git a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java index 717d5150d..15503e239 100644 --- a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java +++ b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java @@ -1,10 +1,10 @@ package io.appium.java_client.android; -import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand; + public interface AuthenticatesByFinger extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java b/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java index 063f689cc..40fc24a83 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java @@ -16,10 +16,6 @@ package io.appium.java_client.android; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; -import static io.appium.java_client.MobileCommand.prepareArguments; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.clipboard.ClipboardContentType; import io.appium.java_client.clipboard.HasClipboard; @@ -28,6 +24,10 @@ import java.util.AbstractMap; import java.util.Base64; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; +import static io.appium.java_client.MobileCommand.prepareArguments; + public interface HasAndroidClipboard extends HasClipboard { /** * Set the content of device's clipboard. diff --git a/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java b/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java index 7984a0b43..66c084480 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java @@ -1,13 +1,13 @@ package io.appium.java_client.android; -import static io.appium.java_client.android.AndroidMobileCommandHelper.getDisplayDensityCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.getSystemBarsCommand; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import java.util.Map; +import static io.appium.java_client.android.AndroidMobileCommandHelper.getDisplayDensityCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.getSystemBarsCommand; + public interface HasAndroidDeviceDetails extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java b/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java index f64f87332..3afea7552 100644 --- a/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java +++ b/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java @@ -1,13 +1,13 @@ package io.appium.java_client.android; -import static io.appium.java_client.android.AndroidMobileCommandHelper.getPerformanceDataCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.getSupportedPerformanceDataTypesCommand; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import java.util.List; +import static io.appium.java_client.android.AndroidMobileCommandHelper.getPerformanceDataCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.getSupportedPerformanceDataTypesCommand; + public interface HasSupportedPerformanceDataType extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java index 4fffed837..44cae6765 100644 --- a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java +++ b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java @@ -16,11 +16,7 @@ package io.appium.java_client.android; -import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.ExecutesMethod; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.remote.RemoteWebDriver; @@ -30,6 +26,9 @@ import java.util.Collections; import java.util.function.Consumer; +import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + public interface ListensToLogcatMessages extends ExecutesMethod { StringWebSocketClient getLogcatClient(); 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 bd21d9d86..ea4c04ce5 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -16,13 +16,13 @@ package io.appium.java_client.android; +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + import static io.appium.java_client.android.AndroidMobileCommandHelper.currentActivityCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.currentPackageCommand; 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 diff --git a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java index df63b6e1a..9100fbb69 100644 --- a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java +++ b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java @@ -1,12 +1,12 @@ package io.appium.java_client.android; +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleAirplaneCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleDataCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleWifiCommand; -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; - public interface SupportsNetworkStateManagement extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java index 9da6dfaec..6baeef8a0 100644 --- a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java +++ b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java @@ -1,5 +1,8 @@ package io.appium.java_client.android; +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + import static io.appium.java_client.android.AndroidMobileCommandHelper.gsmCallCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.gsmSignalStrengthCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.gsmVoiceCommand; @@ -8,9 +11,6 @@ import static io.appium.java_client.android.AndroidMobileCommandHelper.powerCapacityCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.sendSMSCommand; -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; - public interface SupportsSpecialEmulatorCommands extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java index a6eb8e088..67f2e09db 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java @@ -16,17 +16,16 @@ package io.appium.java_client.android.appmanagement; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.appmanagement.BaseInstallApplicationOptions; import java.time.Duration; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class AndroidInstallApplicationOptions extends BaseInstallApplicationOptions { private Boolean replace; diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java index c09253c51..2a4899f13 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java @@ -16,17 +16,16 @@ package io.appium.java_client.android.appmanagement; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import java.time.Duration; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class AndroidRemoveApplicationOptions extends BaseRemoveApplicationOptions { private Duration timeout; diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java index 6ad6c83f5..0e11e569d 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java @@ -16,17 +16,16 @@ package io.appium.java_client.android.appmanagement; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; import java.time.Duration; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class AndroidTerminateApplicationOptions extends BaseTerminateApplicationOptions { private Duration timeout; diff --git a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java index c17d450a1..7f76340a3 100644 --- a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java +++ b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java @@ -16,12 +16,12 @@ package io.appium.java_client.android.connection; -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 static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand; + public interface HasNetworkConnection extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java b/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java index a8538b629..8bf0a99e2 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java +++ b/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java @@ -16,12 +16,12 @@ package io.appium.java_client.android.nativekey; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.util.Map; +import static java.util.Optional.ofNullable; + public class KeyEvent { private Integer keyCode; private Integer metaState; diff --git a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java index b4c39767c..6c9f36212 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java +++ b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java @@ -16,14 +16,14 @@ package io.appium.java_client.android.nativekey; -import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE; -import static io.appium.java_client.MobileCommand.PRESS_KEY_CODE; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import java.util.AbstractMap; +import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE; +import static io.appium.java_client.MobileCommand.PRESS_KEY_CODE; + public interface PressesKey extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java index 0baebf02f..c081be4f9 100644 --- a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java +++ b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java @@ -32,13 +32,13 @@ import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption; import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption; import io.appium.java_client.android.options.app.SupportsAppActivityOption; -import io.appium.java_client.android.options.app.SupportsIntentOptionsOption; -import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; import io.appium.java_client.android.options.app.SupportsAppPackageOption; import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption; +import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption; import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption; import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption; +import io.appium.java_client.android.options.app.SupportsIntentOptionsOption; import io.appium.java_client.android.options.app.SupportsRemoteAppsCacheLimitOption; import io.appium.java_client.android.options.app.SupportsUninstallOtherPackagesOption; import io.appium.java_client.android.options.avd.SupportsAvdArgsOption; diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index 14eddf9eb..adc161950 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -31,9 +31,9 @@ import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption; import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption; import io.appium.java_client.android.options.app.SupportsAppActivityOption; -import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; import io.appium.java_client.android.options.app.SupportsAppPackageOption; import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption; +import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; import io.appium.java_client.android.options.app.SupportsAppWaitForLaunchOption; import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption; import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption; @@ -50,7 +50,6 @@ import io.appium.java_client.android.options.avd.SupportsAvdOption; import io.appium.java_client.android.options.avd.SupportsAvdReadyTimeoutOption; import io.appium.java_client.android.options.avd.SupportsGpsEnabledOption; -import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.android.options.avd.SupportsNetworkSpeedOption; import io.appium.java_client.android.options.context.SupportsAutoWebviewTimeoutOption; import io.appium.java_client.android.options.context.SupportsChromeLoggingPrefsOption; @@ -78,7 +77,6 @@ import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption; import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption; import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption; -import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption; import io.appium.java_client.android.options.other.SupportsUserProfileOption; import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption; import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption; @@ -97,10 +95,12 @@ import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; import io.appium.java_client.remote.options.SupportsDeviceNameOption; import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.remote.options.SupportsLanguageOption; import io.appium.java_client.remote.options.SupportsLocaleOption; import io.appium.java_client.remote.options.SupportsOrientationOption; import io.appium.java_client.remote.options.SupportsOtherAppsOption; +import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption; import io.appium.java_client.remote.options.SupportsUdidOption; import org.openqa.selenium.Capabilities; diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java index 40a588c2e..ead32780b 100644 --- a/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsAndroidInstallTimeoutOption.java @@ -24,8 +24,6 @@ import java.time.Duration; import java.util.Optional; -import static io.appium.java_client.internal.CapabilityHelpers.toDuration; - public interface SupportsAndroidInstallTimeoutOption> extends Capabilities, CanSetCapability { String ANDROID_INSTALL_TIMEOUT_OPTION = "androidInstallTimeout"; diff --git a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java index ca813c4e0..637a35caf 100644 --- a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java +++ b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java @@ -16,11 +16,6 @@ package io.appium.java_client.clipboard; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.GET_CLIPBOARD; -import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; -import static io.appium.java_client.MobileCommand.prepareArguments; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; @@ -28,6 +23,11 @@ import java.util.AbstractMap; import java.util.Base64; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.MobileCommand.GET_CLIPBOARD; +import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; +import static io.appium.java_client.MobileCommand.prepareArguments; + public interface HasClipboard extends ExecutesMethod { /** * Set the content of device's clipboard. diff --git a/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java b/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java index 5489b9686..2563055cc 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java @@ -16,12 +16,12 @@ package io.appium.java_client.imagecomparison; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.util.Map; +import static java.util.Optional.ofNullable; + public abstract class BaseComparisonOptions> { private Boolean visualize; diff --git a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java index 1ad0639b3..49e487b59 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java @@ -18,7 +18,6 @@ import lombok.AccessLevel; import lombok.Getter; - import org.openqa.selenium.Point; import org.openqa.selenium.Rectangle; diff --git a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java index d4c89161f..5e72c6591 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java @@ -16,13 +16,13 @@ package io.appium.java_client.imagecomparison; -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Optional.ofNullable; + public class FeaturesMatchingOptions extends BaseComparisonOptions { private String detectorName; private String matchFunc; diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java index d4a7810e6..818c9f2da 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java @@ -16,12 +16,12 @@ package io.appium.java_client.imagecomparison; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.util.Map; +import static java.util.Optional.ofNullable; + public class OccurrenceMatchingOptions extends BaseComparisonOptions { private Double threshold; private Boolean multiple; diff --git a/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java b/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java index 538c8cee3..f1dd7300e 100644 --- a/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java +++ b/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java @@ -16,11 +16,10 @@ package io.appium.java_client.ios; -import static com.google.common.base.Preconditions.checkNotNull; - import io.appium.java_client.clipboard.ClipboardContentType; import io.appium.java_client.clipboard.HasClipboard; +import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -29,7 +28,8 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Base64; -import javax.imageio.ImageIO; + +import static com.google.common.base.Preconditions.checkNotNull; public interface HasIOSClipboard extends HasClipboard { /** 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 00098b14c..d450c1b0f 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -16,11 +16,7 @@ package io.appium.java_client.ios; -import static io.appium.java_client.MobileCommand.prepareArguments; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.HasAppStrings; @@ -29,9 +25,9 @@ import io.appium.java_client.HidesKeyboard; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.InteractsWithApps; -import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PullsFiles; import io.appium.java_client.PushesFiles; import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.battery.HasBattery; @@ -56,6 +52,9 @@ import java.util.Collections; import java.util.Map; +import static io.appium.java_client.MobileCommand.prepareArguments; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + /** * iOS driver implementation. */ 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 d7f6af6b1..8e61cb5cf 100644 --- a/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java @@ -17,7 +17,6 @@ package io.appium.java_client.ios; import com.google.common.collect.ImmutableMap; - import io.appium.java_client.MobileCommand; import java.util.AbstractMap; diff --git a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java index d9b918977..a86dabac7 100644 --- a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java @@ -16,17 +16,16 @@ package io.appium.java_client.ios; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import io.appium.java_client.screenrecording.ScreenRecordingUploadOptions; import java.time.Duration; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class IOSStartScreenRecordingOptions extends BaseStartScreenRecordingOptions { private String videoType; diff --git a/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java b/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java index 6bb15821c..3341f753d 100644 --- a/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java +++ b/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java @@ -16,11 +16,7 @@ package io.appium.java_client.ios; -import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; - import com.google.common.collect.ImmutableMap; - import io.appium.java_client.ExecutesMethod; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.remote.RemoteWebDriver; @@ -30,6 +26,9 @@ import java.util.Collections; import java.util.function.Consumer; +import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + public interface ListensToSyslogMessages extends ExecutesMethod { StringWebSocketClient getSyslogClient(); diff --git a/src/main/java/io/appium/java_client/ios/PerformsTouchID.java b/src/main/java/io/appium/java_client/ios/PerformsTouchID.java index 90e088e93..907a86655 100644 --- a/src/main/java/io/appium/java_client/ios/PerformsTouchID.java +++ b/src/main/java/io/appium/java_client/ios/PerformsTouchID.java @@ -16,12 +16,12 @@ package io.appium.java_client.ios; -import static io.appium.java_client.ios.IOSMobileCommandHelper.toggleTouchIdEnrollmentCommand; -import static io.appium.java_client.ios.IOSMobileCommandHelper.touchIdCommand; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import static io.appium.java_client.ios.IOSMobileCommandHelper.toggleTouchIdEnrollmentCommand; +import static io.appium.java_client.ios.IOSMobileCommandHelper.touchIdCommand; + public interface PerformsTouchID extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/ios/ShakesDevice.java b/src/main/java/io/appium/java_client/ios/ShakesDevice.java index 208f05bb1..abd601852 100644 --- a/src/main/java/io/appium/java_client/ios/ShakesDevice.java +++ b/src/main/java/io/appium/java_client/ios/ShakesDevice.java @@ -16,11 +16,11 @@ package io.appium.java_client.ios; -import static io.appium.java_client.ios.IOSMobileCommandHelper.shakeCommand; - import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import static io.appium.java_client.ios.IOSMobileCommandHelper.shakeCommand; + public interface ShakesDevice extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/ios/touch/IOSPressOptions.java b/src/main/java/io/appium/java_client/ios/touch/IOSPressOptions.java index 0720bd325..a6b8cdf7f 100644 --- a/src/main/java/io/appium/java_client/ios/touch/IOSPressOptions.java +++ b/src/main/java/io/appium/java_client/ios/touch/IOSPressOptions.java @@ -16,12 +16,12 @@ package io.appium.java_client.ios.touch; -import static java.util.Optional.ofNullable; - import io.appium.java_client.touch.offset.AbstractOptionCombinedWithPosition; import java.util.Map; +import static java.util.Optional.ofNullable; + public class IOSPressOptions extends AbstractOptionCombinedWithPosition { private Double pressure = null; diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindAll.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindAll.java index 69fe8c1e0..63deca31f 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AndroidFindAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindAll.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page/Screen Object to indicate that lookup should use a * series of {@link AndroidBy} tags diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java index 25b37c0b6..aa245d971 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page Object to indicate an alternative mechanism for locating the diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindByAllSet.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindByAllSet.java index ab6afda28..fed03d755 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AndroidFindByAllSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindByAllSet.java @@ -1,12 +1,12 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link AndroidFindAll} diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindByChainSet.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindByChainSet.java index 365146650..3fda1f27a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AndroidFindByChainSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindByChainSet.java @@ -1,12 +1,12 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link io.appium.java_client.pagefactory.AndroidFindBys} diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBySet.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBySet.java index 6e35ebccd..9b1f62519 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBySet.java +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBySet.java @@ -16,13 +16,13 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link io.appium.java_client.pagefactory.AndroidFindBy} diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java index eabfeb7c2..db278a9ce 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page Object to indicate that lookup should use * a series of {@link io.appium.java_client.pagefactory.AndroidBy} tags. diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java index b8b0fbe8f..5208add47 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java @@ -16,15 +16,8 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; -import static io.appium.java_client.pagefactory.ThrowableUtil.isInvalidSelectorRootCause; -import static io.appium.java_client.pagefactory.ThrowableUtil.isStaleElementReferenceException; -import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; -import static java.lang.String.format; - import io.appium.java_client.pagefactory.bys.ContentMappedBy; import io.appium.java_client.pagefactory.locator.CacheableLocator; - import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.SearchContext; @@ -40,6 +33,12 @@ import java.util.function.Function; import java.util.function.Supplier; +import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; +import static io.appium.java_client.pagefactory.ThrowableUtil.isInvalidSelectorRootCause; +import static io.appium.java_client.pagefactory.ThrowableUtil.isStaleElementReferenceException; +import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; +import static java.lang.String.format; + class AppiumElementLocator implements CacheableLocator { private static final String exceptionMessageIfElementNotFound = "Can't locate an element by this strategy: %s"; diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java index 179ecbcc4..170cffa38 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -16,19 +16,19 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.WithTimeout.DurationBuilder.build; -import static java.util.Optional.ofNullable; - import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder; import io.appium.java_client.pagefactory.locator.CacheableElementLocatorFactory; import io.appium.java_client.pagefactory.locator.CacheableLocator; import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; +import javax.annotation.Nullable; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.time.Duration; -import javax.annotation.Nullable; + +import static io.appium.java_client.pagefactory.WithTimeout.DurationBuilder.build; +import static java.util.Optional.ofNullable; public class AppiumElementLocatorFactory implements CacheableElementLocatorFactory { private final SearchContext searchContext; diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index ea3b35e5a..8bb282859 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -16,12 +16,7 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; -import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; -import static java.time.Duration.ofSeconds; - import com.google.common.collect.ImmutableList; - import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; @@ -49,6 +44,10 @@ import java.util.List; import java.util.Map; +import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; +import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; +import static java.time.Duration.ofSeconds; + /** * Default decorator for use with PageFactory. Will decorate 1) all of the * WebElement fields and 2) List of WebElement that have diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index 23445fcf8..512c978cc 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -16,10 +16,6 @@ package io.appium.java_client.pagefactory; -import static java.lang.Integer.signum; -import static java.util.Arrays.asList; -import static java.util.Optional.ofNullable; - import io.appium.java_client.pagefactory.bys.ContentMappedBy; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder; @@ -46,6 +42,10 @@ import java.util.Map; import java.util.Optional; +import static java.lang.Integer.signum; +import static java.util.Arrays.asList; +import static java.util.Optional.ofNullable; + public class DefaultElementByBuilder extends AppiumByBuilder { private static final String PRIORITY = "priority"; diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java index 35a703e8a..efe7bd95f 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java @@ -16,8 +16,6 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; - import io.appium.java_client.pagefactory.interceptors.InterceptorOfASingleElement; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -25,6 +23,8 @@ import java.lang.reflect.Method; +import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; + /** * Intercepts requests to {@link WebElement}. */ diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java index 5dd385b29..fc7164533 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java @@ -16,8 +16,6 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; - import io.appium.java_client.pagefactory.interceptors.InterceptorOfAListOfElements; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; @@ -25,6 +23,8 @@ import java.lang.reflect.Method; import java.util.List; +import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; + /** * Intercepts requests to the list of {@link WebElement}. */ diff --git a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java index 4060e4fae..be25f1c31 100644 --- a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java +++ b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java @@ -16,13 +16,7 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.WidgetConstructorUtil.findConvenientConstructor; -import static io.appium.java_client.remote.MobilePlatform.ANDROID; -import static io.appium.java_client.remote.MobilePlatform.IOS; -import static io.appium.java_client.remote.MobilePlatform.WINDOWS; - import io.appium.java_client.pagefactory.bys.ContentType; -import io.appium.java_client.remote.AutomationName; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; @@ -30,6 +24,11 @@ import java.util.HashMap; import java.util.Map; +import static io.appium.java_client.pagefactory.WidgetConstructorUtil.findConvenientConstructor; +import static io.appium.java_client.remote.MobilePlatform.ANDROID; +import static io.appium.java_client.remote.MobilePlatform.IOS; +import static io.appium.java_client.remote.MobilePlatform.WINDOWS; + class OverrideWidgetReader { private static final Class EMPTY = Widget.class; private static final String HTML = "html"; diff --git a/src/main/java/io/appium/java_client/pagefactory/Widget.java b/src/main/java/io/appium/java_client/pagefactory/Widget.java index fe8a7f9e3..1b2fdaebe 100644 --- a/src/main/java/io/appium/java_client/pagefactory/Widget.java +++ b/src/main/java/io/appium/java_client/pagefactory/Widget.java @@ -16,8 +16,6 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; - import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; @@ -27,6 +25,8 @@ import java.util.List; +import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; + /** * It is the Appium-specific extension of the Page Object design pattern. It allows user * to create objects which typify some element with nested sub-elements. Also it allows to diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java index 4f509598b..905844e4a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java @@ -16,10 +16,6 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.OverrideWidgetReader.getDefaultOrHTMLWidgetClass; -import static io.appium.java_client.pagefactory.OverrideWidgetReader.getMobileNativeWidgetClass; -import static java.util.Optional.ofNullable; - import org.openqa.selenium.By; import java.lang.reflect.AnnotatedElement; @@ -28,6 +24,10 @@ import java.lang.reflect.Type; import java.util.List; +import static io.appium.java_client.pagefactory.OverrideWidgetReader.getDefaultOrHTMLWidgetClass; +import static io.appium.java_client.pagefactory.OverrideWidgetReader.getMobileNativeWidgetClass; +import static java.util.Optional.ofNullable; + public class WidgetByBuilder extends DefaultElementByBuilder { public WidgetByBuilder(String platform, String automation) { diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java index 747a9eadd..2c3296d35 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java @@ -16,9 +16,6 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; -import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; - import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.interceptors.InterceptorOfASingleElement; import io.appium.java_client.pagefactory.locator.CacheableLocator; @@ -34,6 +31,9 @@ import java.util.HashMap; import java.util.Map; +import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; +import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; + class WidgetInterceptor extends InterceptorOfASingleElement { private final Map> instantiationMap; diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java index 580de7fb2..04115aaa9 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java @@ -16,10 +16,6 @@ package io.appium.java_client.pagefactory; -import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; -import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; -import static java.util.Optional.ofNullable; - import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.interceptors.InterceptorOfAListOfElements; import io.appium.java_client.pagefactory.locator.CacheableLocator; @@ -34,6 +30,10 @@ import java.util.List; import java.util.Map; +import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; +import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; +import static java.util.Optional.ofNullable; + class WidgetListInterceptor extends InterceptorOfAListOfElements { private final Map> instantiationMap; diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java index 03be2f654..206c1dd08 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page/Screen Object to indicate that lookup should use a series * of {@link WindowsBy} tags diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java index 9ba86d6c3..2222d0312 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page Object to indicate an alternative mechanism for locating the * element or a list of elements. Used in conjunction with diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java index 9a1e2f3cd..31caf953d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java @@ -1,12 +1,12 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link WindowsFindAll} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java index 583d0f5d5..b6518ba6a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java @@ -1,12 +1,12 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link WindowsFindBys} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java index 5efd79322..2f7cda9f4 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java @@ -16,13 +16,13 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link WindowsFindBy} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java index 605986de3..9120a41d6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page Object to indicate that lookup should use * a series of {@link WindowsBy} tags. diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java index 1f995bbe3..fe7edf9b9 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java @@ -16,16 +16,16 @@ package io.appium.java_client.pagefactory.bys; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; - import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; +import javax.annotation.Nonnull; import java.util.List; import java.util.Map; -import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; public class ContentMappedBy extends By { private final Map map; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java index 423645881..330362140 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java @@ -16,12 +16,6 @@ package io.appium.java_client.pagefactory.bys.builder; -import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; -import static io.appium.java_client.remote.MobilePlatform.ANDROID; -import static io.appium.java_client.remote.MobilePlatform.IOS; -import static io.appium.java_client.remote.MobilePlatform.TVOS; -import static io.appium.java_client.remote.MobilePlatform.WINDOWS; - import org.openqa.selenium.By; import org.openqa.selenium.support.pagefactory.AbstractAnnotations; import org.openqa.selenium.support.pagefactory.ByAll; @@ -38,6 +32,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; +import static io.appium.java_client.remote.MobilePlatform.ANDROID; +import static io.appium.java_client.remote.MobilePlatform.IOS; +import static io.appium.java_client.remote.MobilePlatform.TVOS; +import static io.appium.java_client.remote.MobilePlatform.WINDOWS; + /** * It is the basic handler of Appium-specific page object annotations * About the Page Object design pattern please read these documents: diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java index 59015ede7..243d49306 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java @@ -1,8 +1,5 @@ package io.appium.java_client.pagefactory.bys.builder; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.SearchContext; @@ -13,6 +10,9 @@ import java.util.Optional; import java.util.function.Function; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Mechanism used to locate elements within a document using a series of lookups. This class will * find all DOM elements that matches any of the locators in sequence, e.g. diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java index f8d2240cb..9a4196f23 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java @@ -16,8 +16,6 @@ package io.appium.java_client.pagefactory.bys.builder; -import static com.google.common.base.Preconditions.checkNotNull; - import io.appium.java_client.functions.AppiumFunction; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; @@ -28,6 +26,8 @@ import java.util.Optional; +import static com.google.common.base.Preconditions.checkNotNull; + public class ByChained extends org.openqa.selenium.support.pagefactory.ByChained { private final By[] bys; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 6212ffcf7..a353e0257 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -16,6 +16,12 @@ package io.appium.java_client.pagefactory.bys.builder; +import io.appium.java_client.AppiumBy; +import io.appium.java_client.MobileBy; +import io.appium.java_client.pagefactory.AndroidBy; +import io.appium.java_client.pagefactory.AndroidFindBy; +import org.openqa.selenium.By; + import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -23,13 +29,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.openqa.selenium.By; - -import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileBy; -import io.appium.java_client.pagefactory.AndroidBy; -import io.appium.java_client.pagefactory.AndroidFindBy; - enum Strategies { BYUIAUTOMATOR("uiAutomator") { @Override By getBy(Annotation annotation) { diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindAll.java b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindAll.java index c388f47d2..94a2241c6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindAll.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page/Screen Object to indicate that lookup should use a series * of {@link io.appium.java_client.pagefactory.iOSXCUITBy} tags. diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBy.java b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBy.java index 5194e4094..dbc6d23c0 100644 --- a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBy.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + @Retention(RUNTIME) @Target({FIELD, TYPE}) @Repeatable(iOSXCUITFindBySet.class) public @interface iOSXCUITFindBy { diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByAllSet.java b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByAllSet.java index 0bb769ea7..240efa73d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByAllSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByAllSet.java @@ -1,12 +1,12 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link io.appium.java_client.pagefactory.iOSXCUITFindAll} diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByChainSet.java b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByChainSet.java index 2b5fc28de..fcc1a9e87 100644 --- a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByChainSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindByChainSet.java @@ -1,12 +1,12 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link io.appium.java_client.pagefactory.iOSXCUITFindBys} diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBySet.java b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBySet.java index f1fea5a89..ce7464d2a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBySet.java +++ b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBySet.java @@ -16,13 +16,13 @@ package io.appium.java_client.pagefactory; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - @Retention(RUNTIME) @Target({FIELD, TYPE}) public @interface iOSXCUITFindBySet { /** diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBys.java b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBys.java index 78a0eba3a..ec8424569 100644 --- a/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBys.java +++ b/src/main/java/io/appium/java_client/pagefactory/iOSXCUITFindBys.java @@ -16,14 +16,14 @@ package io.appium.java_client.pagefactory; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Used to mark a field on a Page Object to indicate that lookup should use * a series of {@link io.appium.java_client.pagefactory.iOSXCUITBy} tags. diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 8aa5f7634..e6bb6f6d6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -16,11 +16,6 @@ package io.appium.java_client.pagefactory.utils; -import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; -import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; -import static java.util.Optional.ofNullable; -import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; - import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; import org.openqa.selenium.ContextAware; @@ -29,6 +24,11 @@ import org.openqa.selenium.WrapsDriver; import org.openqa.selenium.WrapsElement; +import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; +import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; + public final class WebDriverUnpackUtility { private static final String NATIVE_APP_PATTERN = "NATIVE_APP"; diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 43ce9fc01..b3acea991 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -16,17 +16,11 @@ package io.appium.java_client.remote; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Throwables.throwIfUnchecked; -import static java.util.Optional.ofNullable; -import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; - import com.google.common.base.Supplier; import com.google.common.base.Throwables; - import com.google.common.net.HttpHeaders; -import io.appium.java_client.AppiumUserAgentFilter; import io.appium.java_client.AppiumClientConfig; +import io.appium.java_client.AppiumUserAgentFilter; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Command; @@ -56,6 +50,11 @@ import java.util.Optional; import java.util.UUID; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.throwIfUnchecked; +import static java.util.Optional.ofNullable; +import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; + public class AppiumCommandExecutor extends HttpCommandExecutor { // https://github.com/appium/appium-base-driver/pull/400 private static final String IDEMPOTENCY_KEY_HEADER = "X-Idempotency-Key"; diff --git a/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java b/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java index cd2d6991c..1fc6943a3 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java +++ b/src/main/java/io/appium/java_client/remote/AppiumW3CHttpCommandCodec.java @@ -16,6 +16,10 @@ package io.appium.java_client.remote; +import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; + +import java.util.Map; + import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_ATTRIBUTE; import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_LOCATION; import static org.openqa.selenium.remote.DriverCommand.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW; @@ -26,10 +30,6 @@ import static org.openqa.selenium.remote.DriverCommand.SET_TIMEOUT; import static org.openqa.selenium.remote.DriverCommand.SUBMIT_ELEMENT; -import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; - -import java.util.Map; - public class AppiumW3CHttpCommandCodec extends W3CHttpCommandCodec { /** * This class overrides the built-in Selenium W3C commands codec, diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java index 4eece6cdb..0e940b5d6 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsBrowserVersionOption.java @@ -18,8 +18,6 @@ import org.openqa.selenium.Capabilities; -import java.util.Optional; - public interface SupportsBrowserVersionOption> extends Capabilities, CanSetCapability { String BROWSER_VERSION_OPTION = "browserVersion"; diff --git a/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java b/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java index 127cc29a9..308a9b05a 100644 --- a/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java @@ -16,13 +16,13 @@ package io.appium.java_client.screenrecording; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public abstract class BaseScreenRecordingOptions> { private ScreenRecordingUploadOptions uploadOptions; diff --git a/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java index 206cc1a6c..43dff24cc 100644 --- a/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java @@ -16,14 +16,14 @@ package io.appium.java_client.screenrecording; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.time.Duration; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public abstract class BaseStartScreenRecordingOptions> extends BaseScreenRecordingOptions> { private Boolean forceRestart; diff --git a/src/main/java/io/appium/java_client/screenrecording/CanRecordScreen.java b/src/main/java/io/appium/java_client/screenrecording/CanRecordScreen.java index cea74c04c..9743edb0a 100644 --- a/src/main/java/io/appium/java_client/screenrecording/CanRecordScreen.java +++ b/src/main/java/io/appium/java_client/screenrecording/CanRecordScreen.java @@ -16,14 +16,14 @@ package io.appium.java_client.screenrecording; +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + import static io.appium.java_client.MobileCommand.START_RECORDING_SCREEN; import static io.appium.java_client.MobileCommand.STOP_RECORDING_SCREEN; import static io.appium.java_client.MobileCommand.startRecordingScreenCommand; import static io.appium.java_client.MobileCommand.stopRecordingScreenCommand; -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; - public interface CanRecordScreen extends ExecutesMethod { /** diff --git a/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java b/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java index 424bfeddd..62509b4eb 100644 --- a/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java @@ -16,13 +16,13 @@ package io.appium.java_client.screenrecording; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import com.google.common.collect.ImmutableMap; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class ScreenRecordingUploadOptions { private String remotePath; private String user; diff --git a/src/main/java/io/appium/java_client/serverevents/ServerEvents.java b/src/main/java/io/appium/java_client/serverevents/ServerEvents.java index 901241ce5..283aa3b66 100644 --- a/src/main/java/io/appium/java_client/serverevents/ServerEvents.java +++ b/src/main/java/io/appium/java_client/serverevents/ServerEvents.java @@ -1,10 +1,11 @@ package io.appium.java_client.serverevents; +import lombok.Data; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import lombok.Data; @Data public class ServerEvents { diff --git a/src/main/java/io/appium/java_client/serverevents/TimedEvent.java b/src/main/java/io/appium/java_client/serverevents/TimedEvent.java index dca5f1218..999ecbd39 100644 --- a/src/main/java/io/appium/java_client/serverevents/TimedEvent.java +++ b/src/main/java/io/appium/java_client/serverevents/TimedEvent.java @@ -1,8 +1,9 @@ package io.appium.java_client.serverevents; -import java.util.List; import lombok.Data; +import java.util.List; + @Data public class TimedEvent { public final String name; diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index d4cedc033..62d2a98ce 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -16,16 +16,9 @@ package io.appium.java_client.service.local; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP_ADDRESS; -import static org.slf4j.event.Level.DEBUG; -import static org.slf4j.event.Level.INFO; - import com.google.common.annotations.VisibleForTesting; - import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; - import org.openqa.selenium.net.UrlChecker; import org.openqa.selenium.os.CommandLine; import org.openqa.selenium.remote.service.DriverService; @@ -33,13 +26,13 @@ import org.slf4j.LoggerFactory; import org.slf4j.event.Level; +import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.time.Duration; import java.util.List; @@ -52,7 +45,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP_ADDRESS; +import static org.slf4j.event.Level.DEBUG; +import static org.slf4j.event.Level.INFO; public final class AppiumDriverLocalService extends DriverService { diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index e0ce11520..1e6885c48 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -16,12 +16,7 @@ package io.appium.java_client.service.local; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; - import com.google.common.collect.ImmutableList; - import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.appium.java_client.remote.AndroidMobileCapabilityType; @@ -29,7 +24,6 @@ import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.appium.java_client.service.local.flags.ServerArgument; - import lombok.SneakyThrows; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -44,7 +38,6 @@ import javax.annotation.Nullable; import java.io.File; import java.io.IOException; - import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; @@ -57,6 +50,10 @@ import java.util.Set; import java.util.function.Function; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; + public final class AppiumServiceBuilder extends DriverService.Builder { diff --git a/src/main/java/io/appium/java_client/touch/LongPressOptions.java b/src/main/java/io/appium/java_client/touch/LongPressOptions.java index 198f476b5..ac8600b49 100644 --- a/src/main/java/io/appium/java_client/touch/LongPressOptions.java +++ b/src/main/java/io/appium/java_client/touch/LongPressOptions.java @@ -16,15 +16,15 @@ package io.appium.java_client.touch; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import io.appium.java_client.touch.offset.AbstractOptionCombinedWithPosition; import java.time.Duration; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class LongPressOptions extends AbstractOptionCombinedWithPosition { protected Duration duration = null; diff --git a/src/main/java/io/appium/java_client/touch/TapOptions.java b/src/main/java/io/appium/java_client/touch/TapOptions.java index 7c4a1e1a0..620df8286 100644 --- a/src/main/java/io/appium/java_client/touch/TapOptions.java +++ b/src/main/java/io/appium/java_client/touch/TapOptions.java @@ -16,13 +16,13 @@ package io.appium.java_client.touch; -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Optional.ofNullable; - import io.appium.java_client.touch.offset.AbstractOptionCombinedWithPosition; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Optional.ofNullable; + public class TapOptions extends AbstractOptionCombinedWithPosition { private Integer tapsCount = null; diff --git a/src/main/java/io/appium/java_client/touch/WaitOptions.java b/src/main/java/io/appium/java_client/touch/WaitOptions.java index 422f0b052..81aedd674 100644 --- a/src/main/java/io/appium/java_client/touch/WaitOptions.java +++ b/src/main/java/io/appium/java_client/touch/WaitOptions.java @@ -16,13 +16,13 @@ package io.appium.java_client.touch; +import java.time.Duration; +import java.util.Map; + import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static java.time.Duration.ofMillis; -import java.time.Duration; -import java.util.Map; - public class WaitOptions extends ActionOptions { protected Duration duration = ofMillis(0); diff --git a/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java b/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java index a497ab4a8..d10a05682 100644 --- a/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java +++ b/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java @@ -1,11 +1,11 @@ package io.appium.java_client.touch.offset; -import static java.util.Optional.ofNullable; - import io.appium.java_client.touch.ActionOptions; import java.util.Map; +import static java.util.Optional.ofNullable; + public abstract class AbstractOptionCombinedWithPosition> extends ActionOptions> { private ActionOptions positionOption; diff --git a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java index 775b067d1..05b4684a3 100644 --- a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java +++ b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java @@ -1,9 +1,5 @@ package io.appium.java_client.touch.offset; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.Optional.ofNullable; - import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; @@ -11,6 +7,10 @@ import java.util.HashMap; import java.util.Map; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.ofNullable; + public class ElementOption extends PointOption { private String elementId; diff --git a/src/main/java/io/appium/java_client/touch/offset/PointOption.java b/src/main/java/io/appium/java_client/touch/offset/PointOption.java index 1cccd2486..9bad51609 100644 --- a/src/main/java/io/appium/java_client/touch/offset/PointOption.java +++ b/src/main/java/io/appium/java_client/touch/offset/PointOption.java @@ -1,12 +1,12 @@ package io.appium.java_client.touch.offset; -import static java.util.Optional.ofNullable; - import io.appium.java_client.touch.ActionOptions; import org.openqa.selenium.Point; import java.util.Map; +import static java.util.Optional.ofNullable; + public class PointOption> extends ActionOptions { protected Point coordinates; diff --git a/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java b/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java index e5a8f55c3..1b4465a88 100644 --- a/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java +++ b/src/main/java/io/appium/java_client/windows/options/SupportsAppArgumentsOption.java @@ -20,7 +20,6 @@ import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; -import java.net.URL; import java.util.Optional; public interface SupportsAppArgumentsOption> extends diff --git a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java index 6a3148aa2..99f16d8d3 100644 --- a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java +++ b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java @@ -16,20 +16,19 @@ package io.appium.java_client.ws; -import java.net.URI; -import java.time.Duration; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Consumer; - -import javax.annotation.Nullable; - import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.WebSocket; +import javax.annotation.Nullable; +import java.net.URI; +import java.time.Duration; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; + public class StringWebSocketClient implements WebSocket.Listener, CanHandleMessages, CanHandleErrors, CanHandleConnects, CanHandleDisconnects { private final List> messageHandlers = new CopyOnWriteArrayList<>(); diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index 38fa40b93..1a0cd129e 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -1,11 +1,5 @@ package io.appium.java_client.android; -import static io.appium.java_client.TestUtils.getCenter; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - import io.appium.java_client.AppiumBy; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; @@ -16,6 +10,12 @@ import java.util.List; +import static io.appium.java_client.TestUtils.getCenter; +import static io.appium.java_client.touch.WaitOptions.waitOptions; +import static io.appium.java_client.touch.offset.ElementOption.element; +import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { private final ActionSupplier horizontalSwipe = () -> { diff --git a/src/test/java/io/appium/java_client/android/AndroidActivityTest.java b/src/test/java/io/appium/java_client/android/AndroidActivityTest.java index 86377ac11..149a393c4 100644 --- a/src/test/java/io/appium/java_client/android/AndroidActivityTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidActivityTest.java @@ -16,13 +16,13 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertEquals; - import io.appium.java_client.android.nativekey.AndroidKey; import io.appium.java_client.android.nativekey.KeyEvent; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class AndroidActivityTest extends BaseAndroidTest { @BeforeEach public void setUp() { diff --git a/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java b/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java index 9aaeb88b3..e3fefd9b0 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java @@ -16,10 +16,10 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + public class AndroidAppStringsTest extends BaseAndroidTest { @Test public void getAppStrings() { diff --git a/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java b/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java index 88e1c1d6e..4c8f03cd4 100644 --- a/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java @@ -16,15 +16,15 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.android.connection.ConnectionState; import io.appium.java_client.android.connection.ConnectionStateBuilder; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + @TestMethodOrder(MethodOrderer.MethodName.class) public class AndroidConnectionTest extends BaseAndroidTest { diff --git a/src/test/java/io/appium/java_client/android/AndroidContextTest.java b/src/test/java/io/appium/java_client/android/AndroidContextTest.java index ed832f9e3..53a90f1dd 100644 --- a/src/test/java/io/appium/java_client/android/AndroidContextTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidContextTest.java @@ -16,13 +16,13 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - import io.appium.java_client.NoSuchContextException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class AndroidContextTest extends BaseAndroidTest { @BeforeAll public static void beforeClass2() throws Exception { diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index f2e502781..aa2434d50 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -16,16 +16,6 @@ package io.appium.java_client.android; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.lessThan; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - import io.appium.java_client.appmanagement.ApplicationState; import org.apache.commons.io.FileUtils; import org.hamcrest.Matchers; @@ -39,6 +29,16 @@ import java.util.Base64; import java.util.List; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + public class AndroidDriverTest extends BaseAndroidTest { @Test diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java index 8ce9fd2fc..acb4d4dd2 100644 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidElementTest.java @@ -16,10 +16,6 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,6 +23,10 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebElement; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class AndroidElementTest extends BaseAndroidTest { @BeforeEach public void setup() { diff --git a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java index 3b915eae1..79a0d8870 100644 --- a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java @@ -1,12 +1,5 @@ package io.appium.java_client.android; -import static java.time.Duration.ofMillis; -import static java.time.Duration.ofSeconds; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.StringContains.containsString; -import static org.junit.jupiter.api.Assertions.assertThrows; - import io.appium.java_client.functions.AppiumFunction; import io.appium.java_client.functions.ExpectedCondition; import org.junit.jupiter.api.BeforeAll; @@ -25,6 +18,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static java.time.Duration.ofMillis; +import static java.time.Duration.ofSeconds; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class AndroidFunctionTest extends BaseAndroidTest { private final AppiumFunction> searchingFunction = input -> { diff --git a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java b/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java index f1045c8cf..e7a40383c 100644 --- a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java @@ -1,7 +1,5 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertTrue; - import org.apache.commons.lang3.time.DurationFormatUtils; import org.junit.jupiter.api.Test; @@ -9,6 +7,8 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class AndroidLogcatListenerTest extends BaseAndroidTest { @Test diff --git a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java b/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java index 63510fc26..b0ec3a1e7 100644 --- a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java @@ -1,16 +1,16 @@ package io.appium.java_client.android; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.emptyString; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriverException; import java.time.Duration; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + public class AndroidScreenRecordTest extends BaseAndroidTest { @BeforeEach diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index 262b50c61..c9b06c49f 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -16,16 +16,16 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class AndroidSearchingTest extends BaseAndroidTest { @BeforeEach diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index 958da3140..f3c9c0394 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -1,19 +1,8 @@ package io.appium.java_client.android; -import static io.appium.java_client.TestUtils.getCenter; -import static io.appium.java_client.touch.LongPressOptions.longPressOptions; -import static io.appium.java_client.touch.TapOptions.tapOptions; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static io.appium.java_client.touch.offset.PointOption.point; -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - import io.appium.java_client.AppiumBy; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; @@ -22,6 +11,16 @@ import java.util.List; +import static io.appium.java_client.TestUtils.getCenter; +import static io.appium.java_client.touch.LongPressOptions.longPressOptions; +import static io.appium.java_client.touch.TapOptions.tapOptions; +import static io.appium.java_client.touch.WaitOptions.waitOptions; +import static io.appium.java_client.touch.offset.ElementOption.element; +import static io.appium.java_client.touch.offset.PointOption.point; +import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + public class AndroidTouchTest extends BaseAndroidTest { @BeforeEach diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 3e75fe6f1..d5eb6840f 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -18,7 +18,6 @@ import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; - import io.appium.java_client.service.local.AppiumServiceBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; diff --git a/src/test/java/io/appium/java_client/android/BatteryTest.java b/src/test/java/io/appium/java_client/android/BatteryTest.java index 619fafac1..ae9fc9e26 100644 --- a/src/test/java/io/appium/java_client/android/BatteryTest.java +++ b/src/test/java/io/appium/java_client/android/BatteryTest.java @@ -16,13 +16,13 @@ package io.appium.java_client.android; +import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import org.junit.jupiter.api.Test; - public class BatteryTest extends BaseAndroidTest { @Test public void veryGettingBatteryInformation() { diff --git a/src/test/java/io/appium/java_client/android/ClipboardTest.java b/src/test/java/io/appium/java_client/android/ClipboardTest.java index cf9ee8581..353d9a579 100644 --- a/src/test/java/io/appium/java_client/android/ClipboardTest.java +++ b/src/test/java/io/appium/java_client/android/ClipboardTest.java @@ -16,11 +16,11 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ClipboardTest extends BaseAndroidTest { @BeforeEach public void setUp() { 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 fc1a138c6..259dd0d4d 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -26,7 +26,6 @@ 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; diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java index a32c482fe..4f1e17551 100644 --- a/src/test/java/io/appium/java_client/android/FingerPrintTest.java +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -16,8 +16,6 @@ package io.appium.java_client.android; -import static io.appium.java_client.AppiumBy.androidUIAutomator; - import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import org.junit.jupiter.api.AfterAll; @@ -32,6 +30,8 @@ import java.time.Duration; +import static io.appium.java_client.AppiumBy.androidUIAutomator; + public class FingerPrintTest { private static AppiumDriverLocalService service; private static AndroidDriver driver; diff --git a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java b/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java index e49463b87..3632bfbf8 100644 --- a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java +++ b/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java @@ -16,14 +16,6 @@ package io.appium.java_client.android; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.core.Is.is; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.util.Base64; - import io.appium.java_client.imagecomparison.FeatureDetector; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; import io.appium.java_client.imagecomparison.FeaturesMatchingResult; @@ -35,6 +27,14 @@ import org.junit.jupiter.api.Test; import org.openqa.selenium.OutputType; +import java.util.Base64; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class ImagesComparisonTest extends BaseAndroidTest { @Test diff --git a/src/test/java/io/appium/java_client/android/IntentTest.java b/src/test/java/io/appium/java_client/android/IntentTest.java index a25e6a0bf..ba4888821 100644 --- a/src/test/java/io/appium/java_client/android/IntentTest.java +++ b/src/test/java/io/appium/java_client/android/IntentTest.java @@ -1,9 +1,5 @@ package io.appium.java_client.android; -import static io.appium.java_client.TestResources.intentExampleApk; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import org.junit.jupiter.api.AfterAll; @@ -13,6 +9,10 @@ import java.util.function.Predicate; +import static io.appium.java_client.TestResources.intentExampleApk; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class IntentTest { private static AppiumDriverLocalService service; protected static AndroidDriver driver; diff --git a/src/test/java/io/appium/java_client/android/KeyCodeTest.java b/src/test/java/io/appium/java_client/android/KeyCodeTest.java index 7a3ae47e3..7c50f4ceb 100644 --- a/src/test/java/io/appium/java_client/android/KeyCodeTest.java +++ b/src/test/java/io/appium/java_client/android/KeyCodeTest.java @@ -16,10 +16,6 @@ package io.appium.java_client.android; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.android.nativekey.AndroidKey; import io.appium.java_client.android.nativekey.KeyEvent; import io.appium.java_client.android.nativekey.KeyEventFlag; @@ -28,6 +24,10 @@ import org.junit.jupiter.api.Test; import org.openqa.selenium.By; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class KeyCodeTest extends BaseAndroidTest { private static final By PRESS_RESULT_VIEW = By.id("io.appium.android.apis:id/text"); diff --git a/src/test/java/io/appium/java_client/android/LogEventTest.java b/src/test/java/io/appium/java_client/android/LogEventTest.java index a473fbe32..ea820fa94 100644 --- a/src/test/java/io/appium/java_client/android/LogEventTest.java +++ b/src/test/java/io/appium/java_client/android/LogEventTest.java @@ -16,16 +16,16 @@ package io.appium.java_client.android; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.serverevents.CommandEvent; import io.appium.java_client.serverevents.CustomEvent; -import io.appium.java_client.serverevents.TimedEvent; import io.appium.java_client.serverevents.ServerEvents; +import io.appium.java_client.serverevents.TimedEvent; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class LogEventTest extends BaseAndroidTest { @Test diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index e29e92c45..bfb4e576a 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -1,8 +1,5 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.openqa.selenium.By.xpath; - import org.junit.jupiter.api.Test; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; @@ -10,6 +7,9 @@ import java.time.Duration; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.openqa.selenium.By.xpath; + public class OpenNotificationsTest extends BaseAndroidTest { @Test public void openNotification() { diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java index 6c2bf0857..0d9da052d 100644 --- a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java +++ b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java @@ -1,8 +1,5 @@ package io.appium.java_client.android; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Disabled; @@ -15,6 +12,9 @@ import java.time.Duration; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class UIAutomator2Test extends BaseAndroidTest { @AfterEach diff --git a/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java b/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java index 4be313211..5a50dc58a 100644 --- a/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java +++ b/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java @@ -17,8 +17,6 @@ package io.appium.java_client.events.stubs; import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.OutputType; @@ -27,6 +25,9 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; +import java.util.ArrayList; +import java.util.List; + public class StubWebElement implements WebElement { public StubWebElement() { } diff --git a/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java b/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java index 10e33a1ee..7b1eec03a 100644 --- a/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java +++ b/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java @@ -8,7 +8,8 @@ import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class AppiumUserAgentFilterTest { @Test diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index 67518eca7..46651eac6 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -1,19 +1,15 @@ package io.appium.java_client.internal; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.AppiumUserAgentFilter; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import java.util.stream.Stream; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; class ConfigTest { private static final String SELENIUM_EXISTING_KEY = "selenium.version"; diff --git a/src/test/java/io/appium/java_client/internal/DirectConnectTest.java b/src/test/java/io/appium/java_client/internal/DirectConnectTest.java index 93b345474..8255c3c5d 100644 --- a/src/test/java/io/appium/java_client/internal/DirectConnectTest.java +++ b/src/test/java/io/appium/java_client/internal/DirectConnectTest.java @@ -7,7 +7,10 @@ import java.util.HashMap; import java.util.Map; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; class DirectConnectTest { diff --git a/src/test/java/io/appium/java_client/ios/ClipboardTest.java b/src/test/java/io/appium/java_client/ios/ClipboardTest.java index af6b8a51d..b8ed26a44 100644 --- a/src/test/java/io/appium/java_client/ios/ClipboardTest.java +++ b/src/test/java/io/appium/java_client/ios/ClipboardTest.java @@ -16,10 +16,10 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ClipboardTest extends AppIOSTest { @Test public void verifySetAndGetClipboardText() { diff --git a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java index 3c731e007..7e1fb6528 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java @@ -16,10 +16,6 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; - import io.appium.java_client.AppiumBy; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterEach; @@ -33,6 +29,10 @@ import java.time.Duration; import java.util.function.Supplier; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; + @TestMethodOrder(MethodOrderer.MethodName.class) public class IOSAlertTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java b/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java index 6080737f8..dc552dc91 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java @@ -16,10 +16,10 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + public class IOSAppStringsTest extends AppIOSTest { @Test public void getAppStrings() { diff --git a/src/test/java/io/appium/java_client/ios/IOSContextTest.java b/src/test/java/io/appium/java_client/ios/IOSContextTest.java index 5c51aa677..f2ac548b1 100644 --- a/src/test/java/io/appium/java_client/ios/IOSContextTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSContextTest.java @@ -16,14 +16,14 @@ package io.appium.java_client.ios; +import io.appium.java_client.NoSuchContextException; +import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import io.appium.java_client.NoSuchContextException; -import org.junit.jupiter.api.Test; - public class IOSContextTest extends BaseIOSWebViewTest { @Test public void testGetContext() { diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index bcfd41d7d..ba62dcf34 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -16,15 +16,6 @@ package io.appium.java_client.ios; -import static io.appium.java_client.TestUtils.waitUntilTrue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.remote.HideKeyboardStrategy; @@ -43,6 +34,15 @@ import java.time.Duration; +import static io.appium.java_client.TestUtils.waitUntilTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + public class IOSDriverTest extends AppIOSTest { @BeforeEach public void setupEach() { diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/test/java/io/appium/java_client/ios/IOSElementTest.java index 18db02e2b..5d3d943a5 100644 --- a/src/test/java/io/appium/java_client/ios/IOSElementTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSElementTest.java @@ -1,10 +1,6 @@ package io.appium.java_client.ios; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsNot.not; -import static org.junit.jupiter.api.Assertions.assertEquals; - +import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; @@ -12,10 +8,13 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; -import io.appium.java_client.AppiumBy; - import java.time.Duration; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; +import static org.junit.jupiter.api.Assertions.assertEquals; + @TestMethodOrder(MethodOrderer.MethodName.class) public class IOSElementTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java b/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java index e4d27f327..922dbb7cd 100644 --- a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java @@ -1,9 +1,5 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.time.Duration; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; @@ -11,6 +7,10 @@ import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertTrue; + public class IOSNativeWebTapSettingTest extends BaseSafariTest { @Test diff --git a/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java b/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java index cf88b7b4a..170ea9b6a 100644 --- a/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java @@ -1,14 +1,14 @@ package io.appium.java_client.ios; +import org.junit.jupiter.api.Test; + +import java.time.Duration; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import org.junit.jupiter.api.Test; - -import java.time.Duration; - public class IOSScreenRecordTest extends AppIOSTest { @Test diff --git a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java b/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java index 30213f480..5af445b0b 100644 --- a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java @@ -16,11 +16,10 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - +import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.Test; -import io.appium.java_client.AppiumBy; +import static org.junit.jupiter.api.Assertions.assertNotEquals; public class IOSSearchingTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java b/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java index d5e2b377f..34429e5df 100644 --- a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java @@ -1,7 +1,5 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertTrue; - import org.apache.commons.lang3.time.DurationFormatUtils; import org.junit.jupiter.api.Test; @@ -9,6 +7,8 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class IOSSyslogListenerTest extends AppIOSTest { @Test diff --git a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java index 46a4d0474..38e66359f 100644 --- a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java @@ -1,14 +1,5 @@ package io.appium.java_client.ios; -import static io.appium.java_client.ios.touch.IOSPressOptions.iosPressOptions; -import static io.appium.java_client.touch.TapOptions.tapOptions; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static java.time.Duration.ofMillis; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; - import io.appium.java_client.AppiumBy; import io.appium.java_client.MultiTouchAction; import org.junit.jupiter.api.MethodOrderer; @@ -20,6 +11,15 @@ import java.time.Duration; +import static io.appium.java_client.ios.touch.IOSPressOptions.iosPressOptions; +import static io.appium.java_client.touch.TapOptions.tapOptions; +import static io.appium.java_client.touch.WaitOptions.waitOptions; +import static io.appium.java_client.touch.offset.ElementOption.element; +import static java.time.Duration.ofMillis; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; + @TestMethodOrder(MethodOrderer.MethodName.class) public class IOSTouchTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java index d03f1acdc..60943342e 100644 --- a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java @@ -1,15 +1,15 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.time.Duration; - import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertTrue; + public class IOSWebViewTest extends BaseIOSWebViewTest { private static final Duration LOOKUP_TIMEOUT = Duration.ofSeconds(30); diff --git a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java b/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java index d724b4ecb..8534f8f35 100644 --- a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java +++ b/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java @@ -16,14 +16,6 @@ package io.appium.java_client.ios; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.core.Is.is; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.util.Base64; - import io.appium.java_client.imagecomparison.FeatureDetector; import io.appium.java_client.imagecomparison.FeaturesMatchingOptions; import io.appium.java_client.imagecomparison.FeaturesMatchingResult; @@ -35,6 +27,14 @@ import org.junit.jupiter.api.Test; import org.openqa.selenium.OutputType; +import java.util.Base64; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class ImagesComparisonTest extends AppIOSTest { @Test diff --git a/src/test/java/io/appium/java_client/ios/RotationTest.java b/src/test/java/io/appium/java_client/ios/RotationTest.java index 21d177fff..1d741845f 100644 --- a/src/test/java/io/appium/java_client/ios/RotationTest.java +++ b/src/test/java/io/appium/java_client/ios/RotationTest.java @@ -16,12 +16,12 @@ package io.appium.java_client.ios; -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.DeviceRotation; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class RotationTest extends AppIOSTest { @AfterEach public void afterMethod() { diff --git a/src/test/java/io/appium/java_client/ios/SettingTest.java b/src/test/java/io/appium/java_client/ios/SettingTest.java index 9fc2bfa4b..647b93e2d 100644 --- a/src/test/java/io/appium/java_client/ios/SettingTest.java +++ b/src/test/java/io/appium/java_client/ios/SettingTest.java @@ -20,12 +20,12 @@ import io.appium.java_client.Setting; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; - import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class SettingTest extends AppIOSTest { @Test public void testSetShouldUseCompactResponses() { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index 433aa2a1a..a135c30e3 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -16,16 +16,7 @@ package io.appium.java_client.pagefactory_tests; -import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.android.BaseAndroidTest; - import io.appium.java_client.pagefactory.AndroidBy; import io.appium.java_client.pagefactory.AndroidFindAll; import io.appium.java_client.pagefactory.AndroidFindBy; @@ -45,6 +36,14 @@ import java.util.ArrayList; import java.util.List; +import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; +import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class AndroidPageObjectTest extends BaseAndroidTest { private boolean populated = false; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index c2cb1b6f4..aeefba86e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -16,13 +16,6 @@ package io.appium.java_client.pagefactory_tests; -import static io.appium.java_client.TestResources.helloAppiumHtml; -import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; -import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; @@ -39,6 +32,13 @@ import java.util.List; +import static io.appium.java_client.TestResources.helloAppiumHtml; +import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; +import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; +import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + public class DesktopBrowserCompatibilityTest { @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java index dad9d7a18..824261c52 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java @@ -16,8 +16,6 @@ package io.appium.java_client.pagefactory_tests; -import static java.time.Duration.ofSeconds; - import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.pagefactory.AndroidFindBy; @@ -37,6 +35,8 @@ import java.util.List; +import static java.time.Duration.ofSeconds; + public class MobileBrowserCompatibilityTest { private WebDriver driver; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java index cfba2ba36..2fbe87f41 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java @@ -16,18 +16,6 @@ package io.appium.java_client.pagefactory_tests; -import static io.appium.java_client.pagefactory.AppiumFieldDecorator.DEFAULT_WAITING_TIMEOUT; -import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; -import static java.lang.Math.abs; -import static java.lang.String.format; -import static java.lang.System.currentTimeMillis; -import static java.time.Duration.ofSeconds; -import static java.time.temporal.ChronoUnit.SECONDS; -import static org.apache.commons.lang3.time.DurationFormatUtils.formatDuration; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.lessThanOrEqualTo; -import static org.openqa.selenium.support.PageFactory.initElements; - import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.WithTimeout; import org.junit.jupiter.api.AfterEach; @@ -43,6 +31,18 @@ import java.time.Duration; import java.util.List; +import static io.appium.java_client.pagefactory.AppiumFieldDecorator.DEFAULT_WAITING_TIMEOUT; +import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; +import static java.lang.Math.abs; +import static java.lang.String.format; +import static java.lang.System.currentTimeMillis; +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.apache.commons.lang3.time.DurationFormatUtils.formatDuration; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.openqa.selenium.support.PageFactory.initElements; + public class TimeoutTest { private static final long ACCEPTABLE_TIME_DIFF_MS = 1500; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java index 418f35e71..9660da6a4 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java @@ -16,17 +16,6 @@ package io.appium.java_client.pagefactory_tests; -import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; -import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.ios.AppIOSTest; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; @@ -40,6 +29,17 @@ import java.util.List; +import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; +import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + @TestMethodOrder(MethodOrderer.MethodName.class) public class XCUITModeTest extends AppIOSTest { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index f71d1d8c4..6f7dbb1c9 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -1,13 +1,5 @@ package io.appium.java_client.pagefactory_tests.widget.tests; -import static com.google.common.collect.ImmutableList.of; -import static io.appium.java_client.remote.AutomationName.ANDROID_UIAUTOMATOR2; -import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; -import static io.appium.java_client.remote.MobilePlatform.ANDROID; -import static io.appium.java_client.remote.MobilePlatform.IOS; -import static io.appium.java_client.remote.MobilePlatform.WINDOWS; -import static org.apache.commons.lang3.StringUtils.EMPTY; - import io.appium.java_client.HasBrowserCheck; import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; @@ -25,6 +17,14 @@ import java.util.Set; import java.util.concurrent.TimeUnit; +import static com.google.common.collect.ImmutableList.of; +import static io.appium.java_client.remote.AutomationName.ANDROID_UIAUTOMATOR2; +import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; +import static io.appium.java_client.remote.MobilePlatform.ANDROID; +import static io.appium.java_client.remote.MobilePlatform.IOS; +import static io.appium.java_client.remote.MobilePlatform.WINDOWS; +import static org.apache.commons.lang3.StringUtils.EMPTY; + public abstract class AbstractStubWebDriver implements WebDriver, HasBrowserCheck, diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java index e81022a57..0e6bc08b7 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java @@ -1,7 +1,6 @@ package io.appium.java_client.pagefactory_tests.widget.tests; import com.google.common.collect.ImmutableList; - import io.appium.java_client.pagefactory.Widget; import org.openqa.selenium.WebElement; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java index cffb170fd..43f0864ac 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java @@ -1,8 +1,5 @@ package io.appium.java_client.pagefactory_tests.widget.tests; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.ImmutableList.of; - import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.OutputType; @@ -15,6 +12,9 @@ import java.util.List; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.ImmutableList.of; + public class StubWebElement implements WebElement, WrapsDriver { private final WebDriver driver; private final By by; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java index 0420d44f6..6e1f4ab2b 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java @@ -1,11 +1,5 @@ package io.appium.java_client.pagefactory_tests.widget.tests; -import static java.util.stream.Collectors.toList; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.openqa.selenium.support.PageFactory.initElements; - import io.appium.java_client.pagefactory.AppiumFieldDecorator; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; @@ -13,6 +7,12 @@ import java.util.List; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.openqa.selenium.support.PageFactory.initElements; + public abstract class WidgetTest { protected final AbstractApp app; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java index a3eee515a..2e0f1e0ae 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/android/AndroidWidgetTest.java @@ -1,16 +1,16 @@ package io.appium.java_client.pagefactory_tests.widget.tests.android; +import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; +import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; +import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; +import org.junit.jupiter.api.Test; + import static io.appium.java_client.AppiumBy.androidUIAutomator; import static io.appium.java_client.pagefactory_tests.widget.tests.android.AndroidApp.ANDROID_DEFAULT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.android.AndroidApp.ANDROID_EXTERNALLY_DEFINED_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.android.AnnotatedAndroidWidget.ANDROID_ROOT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget.ANDROID_SUB_WIDGET_LOCATOR; -import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; -import org.junit.jupiter.api.Test; - public class AndroidWidgetTest extends WidgetTest { public AndroidWidgetTest() { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index 80e6eb1b3..100f0322c 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -1,11 +1,5 @@ package io.appium.java_client.pagefactory_tests.widget.tests.combined; -import static java.util.stream.Collectors.toList; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.equalTo; -import static org.openqa.selenium.support.PageFactory.initElements; - import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.OverrideWidget; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractApp; @@ -13,13 +7,20 @@ import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget; -import java.util.List; -import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.openqa.selenium.WebDriver; +import java.util.List; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.openqa.selenium.support.PageFactory.initElements; + @SuppressWarnings({"unused", "unchecked"}) public class CombinedAppTest { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java index 342e37335..d54e3618c 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java @@ -1,11 +1,5 @@ package io.appium.java_client.pagefactory_tests.widget.tests.combined; -import static java.util.stream.Collectors.toList; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.equalTo; -import static org.openqa.selenium.support.PageFactory.initElements; - import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.OverrideWidget; import io.appium.java_client.pagefactory_tests.widget.tests.AbstractApp; @@ -23,6 +17,12 @@ import java.util.List; import java.util.stream.Stream; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.openqa.selenium.support.PageFactory.initElements; + @SuppressWarnings({"unchecked", "unused"}) public class CombinedWidgetTest { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java index 6a9bb0d53..edaa699f7 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/ios/XCUITWidgetTest.java @@ -1,16 +1,16 @@ package io.appium.java_client.pagefactory_tests.widget.tests.ios; +import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; +import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; +import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; +import org.junit.jupiter.api.Test; + import static io.appium.java_client.AppiumBy.iOSNsPredicateString; import static io.appium.java_client.pagefactory_tests.widget.tests.combined.DefaultIosXCUITWidget.XCUIT_SUB_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.ios.AnnotatedIosWidget.XCUIT_ROOT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.ios.IosApp.IOS_XCUIT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.ios.IosApp.XCUIT_EXTERNALLY_DEFINED_WIDGET_LOCATOR; -import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; -import org.junit.jupiter.api.Test; - public class XCUITWidgetTest extends WidgetTest { public XCUITWidgetTest() { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java index d5990b7e5..023b24819 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java @@ -1,16 +1,16 @@ package io.appium.java_client.pagefactory_tests.widget.tests.windows; +import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; +import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; +import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; +import org.junit.jupiter.api.Test; + import static io.appium.java_client.MobileBy.windowsAutomation; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.AnnotatedWindowsWidget.WINDOWS_ROOT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget.WINDOWS_SUB_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_DEFAULT_WIDGET_LOCATOR; import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR; -import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; -import org.junit.jupiter.api.Test; - public class WindowsWidgetTest extends WidgetTest { public WindowsWidgetTest() { diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index ccdd117d2..923fa57b8 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -1,5 +1,20 @@ package io.appium.java_client.service.local; +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.android.options.UiAutomator2Options; +import io.github.bonigarcia.wdm.WebDriverManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + import static io.appium.java_client.TestResources.apiDemosApk; import static io.appium.java_client.TestUtils.getLocalIp4Address; import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; @@ -24,20 +39,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.common.collect.ImmutableMap; -import io.appium.java_client.android.options.UiAutomator2Options; -import io.github.bonigarcia.wdm.WebDriverManager; -import java.io.File; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - @SuppressWarnings("ResultOfMethodCallIgnored") class ServerBuilderTest { diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index 55906d13f..36518f4ed 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -16,12 +16,6 @@ package io.appium.java_client.service.local; -import static io.appium.java_client.TestResources.apiDemosApk; -import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.remote.AutomationName; @@ -29,10 +23,17 @@ import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.github.bonigarcia.wdm.WebDriverManager; -import java.time.Duration; import org.junit.jupiter.api.Test; import org.openqa.selenium.Capabilities; +import java.time.Duration; + +import static io.appium.java_client.TestResources.apiDemosApk; +import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + class StartingAppLocallyAndroidTest { @Test diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index 07bf8008a..6baf77701 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -16,12 +16,6 @@ package io.appium.java_client.service.local; -import static io.appium.java_client.TestResources.uiCatalogAppZip; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.options.XCUITestOptions; @@ -33,6 +27,12 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; +import static io.appium.java_client.TestResources.uiCatalogAppZip; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + class StartingAppLocallyIosTest { @Test void startingIOSAppWithCapabilitiesOnlyTest() { diff --git a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java b/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java index f4fb55b42..8087da057 100644 --- a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java +++ b/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java @@ -1,11 +1,11 @@ package io.appium.java_client.service.local; +import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - class ThreadSafetyTest { private final AppiumDriverLocalService service = AppiumDriverLocalService.buildDefaultService(); diff --git a/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java b/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java index f4ac4bec8..2d79fcfec 100644 --- a/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java +++ b/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java @@ -1,12 +1,12 @@ package io.appium.java_client.touch; -import static org.hamcrest.core.AllOf.allOf; -import static org.hamcrest.core.IsInstanceOf.instanceOf; - import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; +import static org.hamcrest.core.AllOf.allOf; +import static org.hamcrest.core.IsInstanceOf.instanceOf; + public final class FailsWithMatcher extends TypeSafeMatcher { private final Matcher matcher; diff --git a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java index b08249962..a68bc3fa6 100644 --- a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java +++ b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java @@ -1,5 +1,16 @@ package io.appium.java_client.touch; +import io.appium.java_client.touch.offset.ElementOption; +import io.appium.java_client.touch.offset.PointOption; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.Point; +import org.openqa.selenium.remote.RemoteWebElement; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static io.appium.java_client.touch.FailsWithMatcher.failsWith; import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.TapOptions.tapOptions; @@ -14,17 +25,6 @@ import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertThrows; -import io.appium.java_client.touch.offset.ElementOption; -import io.appium.java_client.touch.offset.PointOption; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.Point; -import org.openqa.selenium.remote.RemoteWebElement; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class TouchOptionsTests { private static final RemoteWebElement DUMMY_ELEMENT = new DummyElement(); From 2afe309a0834212e8a9c9b1525a9459036015eeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 16:50:27 +0300 Subject: [PATCH 143/501] build(deps): bump webdrivermanager from 5.3.0 to 5.3.1 (#1794) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.3.0 to 5.3.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.3.0...webdrivermanager-5.3.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b64f8cebb..6db5a016d 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.0') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.1') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From a3bf0f4a35475b1bbc8fdd9cba803e7c756bc8b5 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Sat, 19 Nov 2022 19:51:41 +0530 Subject: [PATCH 144/501] ci: automated artefact publish to maven central (#1803) * ci: automated artefact publish to maven central * ci: address review comments --- .github/workflows/publish.yml | 20 ++++++++++++++++++++ build.gradle | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..8f82b851b --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,20 @@ +name: Publish package to the Maven Central Repository +on: + release: + types: [created] +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'zulu' + cache: 'gradle' + - name: Publish package + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} + run: ./gradlew publish \ No newline at end of file diff --git a/build.gradle b/build.gradle index 6db5a016d..a932f5b51 100644 --- a/build.gradle +++ b/build.gradle @@ -166,8 +166,8 @@ publishing { repositories { maven { credentials { - username "$ossrhUsername" - password "$ossrhPassword" + username = System.getenv("MAVEN_USERNAME") + password = System.getenv("MAVEN_PASSWORD") } def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/'" From 6a1429437a193aacbc19a63b4c588605bc8f9c23 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 21 Nov 2022 11:32:08 +0530 Subject: [PATCH 145/501] Release 8.2.1 and update release notes --- README.md | 24 ++++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e2da9ca63..74ec4bfb0 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,30 @@ You could find much more code examples by checking client's [unit and integration tests](src/test/java/io/appium/java_client). ## Changelog +*8.2.1* +- **[ENHANCEMENTS]** + - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) + - Connect directly to Appium Hosts in Distributed Environments. [#1747](https://github.com/appium/java-client/pull/1747) + - use own User Agent. [#1779](https://github.com/appium/java-client/pull/1779) + - Add alternative proxy implementation. [#1790](https://github.com/appium/java-client/pull/1790) +- **[BUG FIX]** + - Enforce usage of Base64 compliant with RFC 4648 for all operations. [#1785](https://github.com/appium/java-client/pull/1785) + - Override getScreenshotAs to support the legacy base64 encoding. [#1787](https://github.com/appium/java-client/pull/1787) +- **[REFRACTOR]** + - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) + - JUnit5 test classes and methods are updated to have default package visibility. [#1755](https://github.com/appium/java-client/pull/1755) + - Verify if the PR title complies with conventional commits spec. [#1757](https://github.com/appium/java-client/pull/1757) + - Use Lombok in direct connect class. [#1789](https://github.com/appium/java-client/pull/1789) + - Update readme and remove obsolete documents. [#1792](https://github.com/appium/java-client/pull/1792) + - Remove unnecessary annotation. [#1791](https://github.com/appium/java-client/pull/1791) + - Force unified imports order. [#1793](https://github.com/appium/java-client/pull/1793) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.5.0. + - `org.owasp.dependencycheck` was updated to 7.3.0. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.1. + - `org.junit.jupiter:junit-jupiter` was updated to 5.9.1. + - `org.slf4j:slf4j-api` was updated to 2.0.3. + - `com.google.code.gson:gson` was updated to 2.10.0. *8.2.0* - **[ENHANCEMENTS]** - AppiumDriverLocalService can handle outputStreams. [#1709](https://github.com/appium/java-client/pull/1709) diff --git a/gradle.properties b/gradle.properties index 239efd600..250d8d3b8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,4 +9,4 @@ ossrhPassword=your-jira-password selenium.version=4.5.0 # Please increment the value in a release -appiumClient.version=8.2.0 +appiumClient.version=8.2.1 From 3d16a95a6bcd197730cb521ffbb9a2952ad5ee3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Nov 2022 15:37:39 +0300 Subject: [PATCH 146/501] build(deps): bump slf4j-api from 2.0.3 to 2.0.4 (#1804) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.3...v_2.0.4) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a932f5b51..9ccdbfa40 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:2.0.3' + implementation 'org.slf4j:slf4j-api:2.0.4' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' From 26a6cdb62335e4842d03fa223c689c83596c3e25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Nov 2022 15:38:02 +0300 Subject: [PATCH 147/501] build(deps): bump org.owasp.dependencycheck from 7.3.0 to 7.3.2 (#1805) Bumps org.owasp.dependencycheck from 7.3.0 to 7.3.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9ccdbfa40..9aa5a4b21 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.3.0' + id 'org.owasp.dependencycheck' version '7.3.2' id 'com.github.johnrengelman.shadow' version '7.1.2' } From bb12c03f812da6f1b39dbf399e84cba97f3b821a Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Thu, 24 Nov 2022 17:31:14 +0530 Subject: [PATCH 148/501] ci: fix automated maven repository publishing (#1807) --- .github/workflows/publish.yml | 2 ++ build.gradle | 3 +++ gradle.properties | 7 ------- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8f82b851b..8196bf5ff 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,4 +17,6 @@ jobs: env: MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} + PGP_SECRET: ${{ secrets.SIGNING_KEY }} + PGP_PASSPHRASE: ${{ secrets.SIGNING_PASSWORD }} run: ./gradlew publish \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9aa5a4b21..aac5e7189 100644 --- a/build.gradle +++ b/build.gradle @@ -177,6 +177,9 @@ publishing { } signing { + def signingKey = System.getenv("PGP_SECRET") + def signingPassword = System.getenv("PGP_PASSPHRASE") + useInMemoryPgpKeys(signingKey, signingPassword) sign publishing.publications.mavenJava } diff --git a/gradle.properties b/gradle.properties index 250d8d3b8..e23c7abf2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,5 @@ org.gradle.daemon=true -signing.keyId=YourKeyId -signing.password=YourPublicKeyPassword -signing.secretKeyRingFile=PathToYourKeyRingFile - -ossrhUsername=your-jira-id -ossrhPassword=your-jira-password - selenium.version=4.5.0 # Please increment the value in a release appiumClient.version=8.2.1 From 2250ea506304a02d139620d96002d674776900dc Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Thu, 24 Nov 2022 17:42:41 +0530 Subject: [PATCH 149/501] docs: update release notes --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 74ec4bfb0..ae034f7eb 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ You could find much more code examples by checking client's - Connect directly to Appium Hosts in Distributed Environments. [#1747](https://github.com/appium/java-client/pull/1747) - use own User Agent. [#1779](https://github.com/appium/java-client/pull/1779) - Add alternative proxy implementation. [#1790](https://github.com/appium/java-client/pull/1790) + - Automated artefact publish to maven central. [#1803](https://github.com/appium/java-client/pull/1803) & [#1807](https://github.com/appium/java-client/pull/1807) - **[BUG FIX]** - Enforce usage of Base64 compliant with RFC 4648 for all operations. [#1785](https://github.com/appium/java-client/pull/1785) - Override getScreenshotAs to support the legacy base64 encoding. [#1787](https://github.com/appium/java-client/pull/1787) @@ -220,10 +221,10 @@ You could find much more code examples by checking client's - Force unified imports order. [#1793](https://github.com/appium/java-client/pull/1793) - **[DEPENDENCY UPDATES]** - `org.seleniumhq.selenium:selenium-java` was updated to 4.5.0. - - `org.owasp.dependencycheck` was updated to 7.3.0. + - `org.owasp.dependencycheck` was updated to 7.3.2. - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.1. - `org.junit.jupiter:junit-jupiter` was updated to 5.9.1. - - `org.slf4j:slf4j-api` was updated to 2.0.3. + - `org.slf4j:slf4j-api` was updated to 2.0.4. - `com.google.code.gson:gson` was updated to 2.10.0. *8.2.0* - **[ENHANCEMENTS]** From 7ee25a2cb250d7e5acf89da760d0e9c49a0b9bd9 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 28 Nov 2022 12:54:46 +0100 Subject: [PATCH 150/501] docs: Add troubleshooting section (#1808) --- README.md | 27 ++++++++++ docs/Installing-the-project.md | 91 ---------------------------------- 2 files changed, 27 insertions(+), 91 deletions(-) delete mode 100644 docs/Installing-the-project.md diff --git a/README.md b/README.md index ae034f7eb..f09334c06 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,33 @@ Check the corresponding driver's READMEs to know the list of capabilities and fe You could find much more code examples by checking client's [unit and integration tests](src/test/java/io/appium/java_client). +## Troubleshooting + +### InaccessibleObjectException is thrown in runtime if Java 16+ is used + +Appium Java client uses reflective access to private members of other modules +to ensure proper functionality of several features, like Page Object model. +If you get a runtime exception and `InaccessibleObjectException` is present in +the stacktrace, and your Java runtime is at version 16 or higher, then consider following +[Oracle's tutorial](https://docs.oracle.com/en/java/javase/16/migrate/migrating-jdk-8-later-jdk-releases.html#GUID-7BB28E4D-99B3-4078-BDC4-FC24180CE82B) +and/or checking [existing issues](https://github.com/appium/java-client/search?q=InaccessibleObjectException&type=issues) +for possible solutions. Basically, the idea there would be to explicitly allow +access for particular modules using `--add-exports/--add-opens` command line arguments. + +Another possible, but weakly advised solution, would be to downgrade Java to +version 15 or lower. + +### Issues related to environment variables presence or to their values + +Such issues are usually the case when Appium server is started directly from your +framework code rather than run separately by a script or manually. Depending +on the way the server process is started it may or may not inherit the currently +active shell environment. That is why you may still receive errors about variables +presence even though these variables ar actually defined for your command line interpreter. +Again, there is no universal solution to that, as there are many ways to spin up a new +server process. Consider checking the [Appium Environment Troubleshooting](docs/environment.md) +document for more information on how to debug and fix process environment issues. + ## Changelog *8.2.1* - **[ENHANCEMENTS]** diff --git a/docs/Installing-the-project.md b/docs/Installing-the-project.md deleted file mode 100644 index 8417f9f79..000000000 --- a/docs/Installing-the-project.md +++ /dev/null @@ -1,91 +0,0 @@ -# Requirements - -Firstly you should install appium server. [Appium getting started](https://appium.io/docs/en/about-appium/getting-started/). The latest server version is recommended. - -Since version 5.x there many features based on Java 8. So we recommend to install JDK SE 8 and provide that source compatibility. - -# Maven - -Add the following to pom.xml: - -``` - - io.appium - java-client - ${version.you.require} - test - -``` - -If you haven't already, change the Java version: -``` - - 1.8 - 1.8 - -``` - -If it is necessary to change the version of Selenium then you can configure pom.xml like following: - -``` - - io.appium - java-client - ${version.you.require} - test - - - org.seleniumhq.selenium - selenium-java - - - - - - org.seleniumhq.selenium - selenium-java - ${selenium.version.you.require} - -``` - -# Gradle - -Add the following to build.gradle: - -``` -repositories { - jcenter() - maven { - url "http://repo.maven.apache.org/maven2" - } -} - -dependencies { - ... - testCompile group: 'io.appium', name: 'java-client', version: requiredVersion - ... -} -``` - -If it is necessary to change the version of Selenium then you can configure build.gradle like the sample below: - -``` -repositories { - jcenter() - maven { - url "http://repo.maven.apache.org/maven2" - } -} - -dependencies { - ... - testCompile group: 'io.appium', name: 'java-client', version: requiredVersion { - exclude module: 'selenium-java' - } - - testCompile group: 'org.seleniumhq.selenium', name: 'selenium-java', - version: requiredSeleniumVersion - ... -} -``` - From 80c6c1b8d968cb8aac33023f40af930f7ae77f1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 15:30:09 +0300 Subject: [PATCH 151/501] build(deps): bump slf4j-api from 2.0.4 to 2.0.5 (#1809) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.4 to 2.0.5. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.4...v_2.0.5) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index aac5e7189..3b89ad341 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:2.0.4' + implementation 'org.slf4j:slf4j-api:2.0.5' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' From d81e91a3b7ad2e24b24117d763c679240948877f Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 30 Nov 2022 15:52:09 +0100 Subject: [PATCH 152/501] chore: Add CHANGELOG.md (#1810) --- CHANGELOG.md | 866 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 858 +------------------------------------------------- 2 files changed, 867 insertions(+), 857 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..0d8a55cd9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,866 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +*8.2.1* +- **[ENHANCEMENTS]** + - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) + - Connect directly to Appium Hosts in Distributed Environments. [#1747](https://github.com/appium/java-client/pull/1747) + - use own User Agent. [#1779](https://github.com/appium/java-client/pull/1779) + - Add alternative proxy implementation. [#1790](https://github.com/appium/java-client/pull/1790) + - Automated artefact publish to maven central. [#1803](https://github.com/appium/java-client/pull/1803) & [#1807](https://github.com/appium/java-client/pull/1807) +- **[BUG FIX]** + - Enforce usage of Base64 compliant with RFC 4648 for all operations. [#1785](https://github.com/appium/java-client/pull/1785) + - Override getScreenshotAs to support the legacy base64 encoding. [#1787](https://github.com/appium/java-client/pull/1787) +- **[REFACTOR]** + - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) + - JUnit5 test classes and methods are updated to have default package visibility. [#1755](https://github.com/appium/java-client/pull/1755) + - Verify if the PR title complies with conventional commits spec. [#1757](https://github.com/appium/java-client/pull/1757) + - Use Lombok in direct connect class. [#1789](https://github.com/appium/java-client/pull/1789) + - Update readme and remove obsolete documents. [#1792](https://github.com/appium/java-client/pull/1792) + - Remove unnecessary annotation. [#1791](https://github.com/appium/java-client/pull/1791) + - Force unified imports order. [#1793](https://github.com/appium/java-client/pull/1793) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.5.0. + - `org.owasp.dependencycheck` was updated to 7.3.2. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.1. + - `org.junit.jupiter:junit-jupiter` was updated to 5.9.1. + - `org.slf4j:slf4j-api` was updated to 2.0.4. + - `com.google.code.gson:gson` was updated to 2.10.0. + +*8.2.0* +- **[ENHANCEMENTS]** + - AppiumDriverLocalService can handle outputStreams. [#1709](https://github.com/appium/java-client/pull/1709) + - Add creating a driver with ClientConfig. [#1735](https://github.com/appium/java-client/pull/1735) +- **[BUG FIX]** + - Update the environment argument type for mac SupportsEnvironmentOption. [#1712](https://github.com/appium/java-client/pull/1712) +- **[REFACTOR]** + - Deprecate Appium ByAll in favour of Selenium ByAll. [#1740](https://github.com/appium/java-client/pull/1740) + - Bump Node.js version in pipeline. [#1713](https://github.com/appium/java-client/pull/1713) + - Switch unit tests to run on Junit 5 Jupiter Platform. [#1721](https://github.com/appium/java-client/pull/1721) + - Clean up unit tests asserting thrown exceptions. [#1741](https://github.com/appium/java-client/pull/1741) + - Fix open notification test. [#1749](https://github.com/appium/java-client/pull/1749) + - update Azure pipeline to use macos-11 VM image. [#1728](https://github.com/appium/java-client/pull/1728) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.4.0. + - `org.owasp.dependencycheck` was updated to 7.1.2. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.0. + - `gradle` was updated to 7.5.1. + - `com.google.code.gson:gson` was updated to 2.9.1. + +*8.1.1* +- **[BUG FIX]** + - Perform safe typecast while getting the platform name. [#1702](https://github.com/appium/java-client/pull/1702) + - Add prefix to platformVersion capability name. [#1704](https://github.com/appium/java-client/pull/1704) +- **[REFACTOR]** + - Update e2e tests to make it green. [#1706](https://github.com/appium/java-client/pull/1706) + - Ignore the test which has a connected server issue. [#1699](https://github.com/appium/java-client/pull/1699) + +*8.1.0* +- **[ENHANCEMENTS]** + - Add new EspressoBuildConfig options. [#1687](https://github.com/appium/java-client/pull/1687) +- **[DOCUMENTATION]** + - delete all references to removed MobileElement class. [#1677](https://github.com/appium/java-client/pull/1677) +- **[BUG FIX]** + - Pass orientation name capability in uppercase. [#1686](https://github.com/appium/java-client/pull/1686) + - correction for ping method to get proper status URL. [#1661](https://github.com/appium/java-client/pull/1661) + - Remove deprecated option classes. [#1679](https://github.com/appium/java-client/pull/1679) + - Remove obsolete event firing decorators. [#1676](https://github.com/appium/java-client/pull/1676) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.2.0. + - `org.owasp.dependencycheck` was updated to 7.1.0.1. + - `org.springframework:spring-context` was removed. [#1676](https://github.com/appium/java-client/pull/1676) + - `org.aspectj:aspectjweaver` was updated to 1.9.9. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.2.0. + - `org.projectlombok:lombok` was updated to 1.18.24. + +*8.0.0* +- **[DOCUMENTATION]** + - Set minimum Java version to 1.8.0. [#1631](https://github.com/appium/java-client/pull/1631) +- **[BUG FIX]** + - Make interfaces public to fix decorator creation. [#1644](https://github.com/appium/java-client/pull/1644) + - Do not convert argument names to lowercase. [#1627](https://github.com/appium/java-client/pull/1627) + - Avoid fallback to css for id and name locator annotations. [#1622](https://github.com/appium/java-client/pull/1622) + - Fix handling of chinese characters in `AppiumDriverLocalService`. [#1618](https://github.com/appium/java-client/pull/1618) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 7.0.0. + - `org.springframework:spring-context` was updated to 5.3.16. + - `actions/setup-java` was updated to 3. + - `actions/checkout` was updated to 3. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.1.0. + - `org.aspectj:aspectjweaver` was updated to 1.9.8. + - `org.slf4j:slf4j-api` was updated to 1.7.36. + - `com.github.johnrengelman.shadow` was updated to 7.1.2. + +*8.0.0-beta2* +- **[DOCUMENTATION]** + - Add a link to options builder examples to the migration guide. [#1595](https://github.com/appium/java-client/pull/1595) +- **[BUG FIX]** + - Filter out proxyClassLookup method from Proxy class (for Java 16+) in AppiumByBuilder. [#1575](https://github.com/appium/java-client/pull/1575) +- **[REFACTOR]** + - Add more nice functional stuff into page factory helpers. [#1584](https://github.com/appium/java-client/pull/1584) + - Switch e2e tests to use Appium2. [#1603](https://github.com/appium/java-client/pull/1603) + - relax constraints of Selenium dependencies versions. [#1606](https://github.com/appium/java-client/pull/1606) +- **[DEPENDENCY UPDATES]** + - Upgrade to Selenium 4.1.1. [#1613](https://github.com/appium/java-client/pull/1613) + - `org.owasp.dependencycheck` was updated to 6.5.1. + - `org.springframework:spring-context` was updated to 5.3.14. + - `actions/setup-java` was updated to 2.4.0. + - `gradle` was updated to 7.3. + +*8.0.0-beta* +- **[ENHANCEMENTS]** + - Start adding UiAutomator2 options. [#1543](https://github.com/appium/java-client/pull/1543) + - Add more UiAutomator2 options. [#1545](https://github.com/appium/java-client/pull/1545) + - Finish creating options for UiAutomator2 driver. [#1548](https://github.com/appium/java-client/pull/1548) + - Add WDA-related XCUITestOptions. [#1552](https://github.com/appium/java-client/pull/1552) + - Add web view options for XCUITest driver. [#1557](https://github.com/appium/java-client/pull/1557) + - Add the rest of XCUITest driver options. [#1561](https://github.com/appium/java-client/pull/1561) + - Add Espresso options. [#1563](https://github.com/appium/java-client/pull/1563) + - Add Windows driver options. [#1564](https://github.com/appium/java-client/pull/1564) + - Add Mac2 driver options. [#1565](https://github.com/appium/java-client/pull/1565) + - Add Gecko driver options. [#1573](https://github.com/appium/java-client/pull/1573) + - Add Safari driver options. [#1576](https://github.com/appium/java-client/pull/1576) + - Start adding XCUITest driver options. [#1551](https://github.com/appium/java-client/pull/1551) + - Implement driver-specific W3C option classes. [#1540](https://github.com/appium/java-client/pull/1540) + - Update Service to properly work with options. [#1550](https://github.com/appium/java-client/pull/1550) +- **[BREAKING CHANGE]** + - Migrate to Selenium 4. [#1531](https://github.com/appium/java-client/pull/1531) + - Make sure we only write W3C payload into create session command. [#1537](https://github.com/appium/java-client/pull/1537) + - Use the new session payload creator inherited from Selenium. [#1535](https://github.com/appium/java-client/pull/1535) + - unify locator factories naming and toString implementations. [#1538](https://github.com/appium/java-client/pull/1538) + - drop support of deprecated Selendroid driver. [#1553](https://github.com/appium/java-client/pull/1553) + - switch to javac compiler. [#1556](https://github.com/appium/java-client/pull/1556) + - revise used Selenium dependencies. [#1560](https://github.com/appium/java-client/pull/1560) + - change prefix to AppiumBy in locator toString implementation. [#1559](https://github.com/appium/java-client/pull/1559) + - enable dependencies caching. [#1567](https://github.com/appium/java-client/pull/1567) + - Include more tests into the pipeline. [#1566](https://github.com/appium/java-client/pull/1566) + - Tune setting of default platform names. [#1570](https://github.com/appium/java-client/pull/1570) + - Deprecate custom event listener implementation and default to the one provided by Selenium4. [#1541](https://github.com/appium/java-client/pull/1541) + - Deprecate touch actions. [#1569](https://github.com/appium/java-client/pull/1569) + - Deprecate legacy app management helpers. [#1571](https://github.com/appium/java-client/pull/1571) + - deprecate Windows UIAutomation selector. [#1562](https://github.com/appium/java-client/pull/1562) + - Remove unused entities. [#1572](https://github.com/appium/java-client/pull/1572) + - Remove setElementValue helper. [#1577](https://github.com/appium/java-client/pull/1577) + - Remove selenium package override. [#1555](https://github.com/appium/java-client/pull/1555) + - remove redundant exclusion of Gradle task signMavenJavaPublication. [#1568](https://github.com/appium/java-client/pull/1568) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 6.4.1. + - `com.google.code.gson:gson` was updated to 2.8.9. + +*7.6.0* +- **[ENHANCEMENTS]** + - Add custom commands dynamically [Appium 2.0]. [#1506](https://github.com/appium/java-client/pull/1506) + - New General Server flags are added [Appium 2.0]. [#1511](https://github.com/appium/java-client/pull/1511) + - Add support of extended Android geolocation. [#1492](https://github.com/appium/java-client/pull/1492) +- **[BUG FIX]** + - AndroidGeoLocation: update the constructor signature to mimic order of parameters in `org.openqa.selenium.html5.Location`. [#1526](https://github.com/appium/java-client/pull/1526) + - Prevent duplicate builds for PRs from base repo branches. [#1496](https://github.com/appium/java-client/pull/1496) + - Enable Dependabot for GitHub actions. [#1500](https://github.com/appium/java-client/pull/1500) + - bind mac2element in element map for mac platform. [#1474](https://github.com/appium/java-client/pull/1474) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 6.3.2. + - `org.projectlombok:lombok` was updated to 1.18.22. + - `com.github.johnrengelman.shadow` was updated to 7.1.0. + - `actions/setup-java` was updated to 2.3.1. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.0.3. + - `org.springframework:spring-context` was updated to 5.3.10. + - `org.slf4j:slf4j-api` was updated to 1.7.32. + - `com.google.code.gson:gson` was updated to 2.8.8. + - `gradle` was updated to 7.1.1. + - `commons-io:commons-io` was updated to 2.11.0. + - `org.aspectj:aspectjweaver` was updated to 1.9.7. + - `org.eclipse.jdt:ecj` was updated to 3.26.0. + - `'junit:junit` was updated to 4.13.2. + +*7.5.1* +- **[ENHANCEMENTS]** + - Add iOS related annotations to tvOS. [#1456](https://github.com/appium/java-client/pull/1456) +- **[BUG FIX]** + - Bring back automatic quote escaping for desired capabilities command line arguments on windows. [#1454](https://github.com/appium/java-client/pull/1454) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 6.1.2. + - `org.eclipse.jdt:ecj` was updated to 3.25.0. + +*7.5.0* +- **[ENHANCEMENTS]** + - Add support for Appium Mac2Driver. [#1439](https://github.com/appium/java-client/pull/1439) + - Add support for multiple image occurrences. [#1445](https://github.com/appium/java-client/pull/1445) + - `BOUND_ELEMENTS_BY_INDEX` Setting was added. [#1418](https://github.com/appium/java-client/pull/1418) +- **[BUG FIX]** + - Use lower case for Windows platform key in ElementMap. [#1421](https://github.com/appium/java-client/pull/1421) +- **[DEPENDENCY UPDATES]** + - `org.apache.commons:commons-lang3` was updated to 3.12.0. + - `org.springframework:spring-context` was updated to 5.3.4. + - `org.owasp.dependencycheck` was updated to 6.1.0. + - `io.github.bonigarcia:webdrivermanager` was updated to 4.3.1. + - `org.eclipse.jdt:ecj` was updated to 3.24.0. + - `org.projectlombok:lombok` was updated to 1.18.16. + - `jcenter` repository was removed. + +*7.4.1* +- **[BUG FIX]** + - Fix the configuration of `selenium-java` dependency. [#1417](https://github.com/appium/java-client/pull/1417) +- **[DEPENDENCY UPDATES]** + - `gradle` was updated to 6.7.1. + + +*7.4.0* +- **[ENHANCEMENTS]** + - Add ability to set multiple settings. [#1409](https://github.com/appium/java-client/pull/1409) + - Support to execute Chrome DevTools Protocol commands against Android Chrome browser session. [#1375](https://github.com/appium/java-client/pull/1375) + - Add new upload options i.e withHeaders, withFormFields and withFileFieldName. [#1342](https://github.com/appium/java-client/pull/1342) + - Add AndroidOptions and iOSOptions. [#1331](https://github.com/appium/java-client/pull/1331) + - Add idempotency key to session creation requests. [#1327](https://github.com/appium/java-client/pull/1327) + - Add support for Android capability types: `buildToolsVersion`, `enforceAppInstall`, `ensureWebviewsHavePages`, `webviewDevtoolsPort`, and `remoteAppsCacheLimit`. [#1326](https://github.com/appium/java-client/pull/1326) + - Added OTHER_APPS and PRINT_PAGE_SOURCE_ON_FIND_FAILURE Mobile Capability Types. [#1323](https://github.com/appium/java-client/pull/1323) + - Make settings available for all AppiumDriver instances. [#1318](https://github.com/appium/java-client/pull/1318) + - Add wrappers for the Windows screen recorder. [#1313](https://github.com/appium/java-client/pull/1313) + - Add GitHub Action validating Gradle wrapper. [#1296](https://github.com/appium/java-client/pull/1296) + - Add support for Android viewmatcher. [#1293](https://github.com/appium/java-client/pull/1293) + - Update web view detection algorithm for iOS tests. [#1294](https://github.com/appium/java-client/pull/1294) + - Add allow-insecure and deny-insecure server flags. [#1282](https://github.com/appium/java-client/pull/1282) +- **[BUG FIX]** + - Fix jitpack build failures. [#1389](https://github.com/appium/java-client/pull/1389) + - Fix parse platformName if it is passed as enum item. [#1369](https://github.com/appium/java-client/pull/1369) + - Increase the timeout for graceful AppiumDriverLocalService termination. [#1354](https://github.com/appium/java-client/pull/1354) + - Avoid casting to RemoteWebElement in ElementOptions. [#1345](https://github.com/appium/java-client/pull/1345) + - Properly translate desiredCapabilities into a command line argument. [#1337](https://github.com/appium/java-client/pull/1337) + - Change getDeviceTime to call the `mobile` implementation. [#1332](https://github.com/appium/java-client/pull/1332) + - Remove appiumVersion from MobileCapabilityType. [#1325](https://github.com/appium/java-client/pull/1325) + - Set appropriate fluent wait timeouts. [#1316](https://github.com/appium/java-client/pull/1316) +- **[DOCUMENTATION UPDATES]** + - Update Appium Environment Troubleshooting. [#1358](https://github.com/appium/java-client/pull/1358) + - Address warnings printed by docs linter. [#1355](https://github.com/appium/java-client/pull/1355) + - Add java docs for various Mobile Options. [#1331](https://github.com/appium/java-client/pull/1331) + - Add AndroidFindBy, iOSXCUITFindBy and WindowsFindBy docs. [#1311](https://github.com/appium/java-client/pull/1311) + - Renamed maim.js to main.js. [#1277](https://github.com/appium/java-client/pull/1277) + - Improve Readability of Issue Template. [#1260](https://github.com/appium/java-client/pull/1260) + +*7.3.0* +- **[ENHANCEMENTS]** + - Add support for logging custom events on the Appium Server. [#1262](https://github.com/appium/java-client/pull/1262) + - Update Appium executable detection implementation. [#1256](https://github.com/appium/java-client/pull/1256) + - Avoid through NPE if any setting value is null. [#1241](https://github.com/appium/java-client/pull/1241) + - Settings API was improved to accept string names. [#1240](https://github.com/appium/java-client/pull/1240) + - Switch `runAppInBackground` iOS implementation in sync with other platforms. [#1229](https://github.com/appium/java-client/pull/1229) + - JavaDocs for AndroidMobileCapabilityType was updated. [#1238](https://github.com/appium/java-client/pull/1238) + - Github Actions were introduced instead of TravisCI. [#1219](https://github.com/appium/java-client/pull/1219) +- **[BUG FIX]** + - Fix return type of `getSystemBars` API. [#1216](https://github.com/appium/java-client/pull/1216) + - Avoid using `getSession` call for capabilities values retrieval [W3C Support]. [#1204](https://github.com/appium/java-client/pull/1204) + - Fix pagefactory list element initialisation when parameterised by generic type. [#1237](https://github.com/appium/java-client/pull/1237) + - Fix AndroidKey commands. [#1250](https://github.com/appium/java-client/pull/1250) + +*7.2.0* +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was reverted to stable version 3.141.59. [#1209](https://github.com/appium/java-client/pull/1209) + - `org.projectlombok:lombok:1.18.8` was introduced. [#1193](https://github.com/appium/java-client/pull/1193) +- **[ENHANCEMENTS]** + - `videoFilters` property was added to IOSStartScreenRecordingOptions. [#1180](https://github.com/appium/java-client/pull/1180) +- **[IMPROVEMENTS]** + - `Selendroid` automationName was deprecated. [#1198](https://github.com/appium/java-client/pull/1198) + - JavaDocs for AndroidMobileCapabilityType and IOSMobileCapabilityType were updated. [#1204](https://github.com/appium/java-client/pull/1204) + - JitPack builds were fixed. [#1203](https://github.com/appium/java-client/pull/1203) + +*7.1.0* +- **[ENHANCEMENTS]** + - Added an ability to get all the session details. [#1167 ](https://github.com/appium/java-client/pull/1167) + - `TRACK_SCROLL_EVENTS`, `ALLOW_INVISIBLE_ELEMENTS`, `ENABLE_NOTIFICATION_LISTENER`, + `NORMALIZE_TAG_NAMES` and `SHUTDOWN_ON_POWER_DISCONNECT` Android Settings were added. + - `KEYBOARD_AUTOCORRECTION`, `MJPEG_SCALING_FACTOR`, + `MJPEG_SERVER_SCREENSHOT_QUALITY`, `MJPEG_SERVER_FRAMERATE`, `SCREENSHOT_QUALITY` + and `KEYBOARD_PREDICTION` iOS Settings were added. + - `GET_MATCHED_IMAGE_RESULT`, `FIX_IMAGE_TEMPLATE_SCALE`, + `SHOULD_USE_COMPACT_RESPONSES`, `ELEMENT_RESPONSE_ATTRIBUTES` and + `DEFAULT_IMAGE_TEMPLATE_SCALE` settings were added for both Android and iOS [#1166](https://github.com/appium/java-client/pull/1166), [#1156 ](https://github.com/appium/java-client/pull/1156) and [#1120](https://github.com/appium/java-client/pull/1120) + - The new interface `io.appium.java_client.ExecutesDriverScript ` was added. [#1165](https://github.com/appium/java-client/pull/1165) + - Added an ability to get status of appium server. [#1153 ](https://github.com/appium/java-client/pull/1153) + - `tvOS` platform support was added. [#1142 ](https://github.com/appium/java-client/pull/1142) + - The new interface `io.appium.java_client. FindsByAndroidDataMatcher` was added. [#1106](https://github.com/appium/java-client/pull/1106) + - The selector strategy `io.appium.java_client.MobileBy.ByAndroidDataMatcher` was added. [#1106](https://github.com/appium/java-client/pull/1106) + - Selendroid for android and UIAutomation for iOS are removed. [#1077 ](https://github.com/appium/java-client/pull/1077) + - **[BUG FIX]** Platform Name enforced on driver creation is avoided now. [#1164 ](https://github.com/appium/java-client/pull/1164) + - **[BUG FIX]** Send both signalStrengh and signalStrength for `GSM_SIGNAL`. [#1115 ](https://github.com/appium/java-client/pull/1115) + - **[BUG FIX]** Null pointer exceptions when calling getCapabilities is handled better. [#1094 ](https://github.com/appium/java-client/pull/1094) + +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.0.0-alpha-1. + - `org.aspectj:aspectjweaver` was updated to 1.9.4. + - `org.apache.httpcomponents:httpclient` was updated to 4.5.9. + - `cglib:cglib` was updated to 3.2.12. + - `org.springframework:spring-context` was updated to 5.1.8.RELEASE. + - `io.github.bonigarcia:webdrivermanager` was updated to 3.6.1. + - `org.eclipse.jdt:ecj` was updated to 3.18.0. + - `com.github.jengelman.gradle.plugins:shadow` was updated to 5.1.0. + - `checkstyle` was updated to 8.22. + - `gradle` was updated to 5.4. + - `dependency-check-gradle` was updated to 5.1.0. + - `org.slf4j:slf4j-api` was updated to 1.7.26. + - `org.apache.commons:commons-lang3` was updated to 3.9. + +*7.0.0* +- **[ENHANCEMENTS]** + - The new interface `io.appium.java_client.FindsByAndroidViewTag` was added. [#996](https://github.com/appium/java-client/pull/996) + - The selector strategy `io.appium.java_client.MobileBy.ByAndroidViewTag` was added. [#996](https://github.com/appium/java-client/pull/996) + - The new interface `io.appium.java_client.FindsByImage` was added. [#990](https://github.com/appium/java-client/pull/990) + - The selector strategy `io.appium.java_client.MobileBy.ByImage` was added. [#990](https://github.com/appium/java-client/pull/990) + - The new interface `io.appium.java_client.FindsByCustom` was added. [#1041](https://github.com/appium/java-client/pull/1041) + - The selector strategy `io.appium.java_client.MobileBy.ByCustom` was added. [#1041](https://github.com/appium/java-client/pull/1041) + - DatatypeConverter is replaced with Base64 for JDK 9 compatibility. [#999](https://github.com/appium/java-client/pull/999) + - Expand touch options API to accept coordinates as Point. [#997](https://github.com/appium/java-client/pull/997) + - W3C capabilities written into firstMatch entity instead of alwaysMatch. [#1010](https://github.com/appium/java-client/pull/1010) + - `Selendroid` for android and `UIAutomation` for iOS is deprecated. [#1034](https://github.com/appium/java-client/pull/1034) and [#1074](https://github.com/appium/java-client/pull/1074) + - `videoScale` and `fps` screen recording options are introduced for iOS. [#1067](https://github.com/appium/java-client/pull/1067) + - `NORMALIZE_TAG_NAMES` setting was introduced for android. [#1073](https://github.com/appium/java-client/pull/1073) + - `threshold` argument was added to OccurrenceMatchingOptions. [#1060](https://github.com/appium/java-client/pull/1060) + - `org.openqa.selenium.internal.WrapsElement` replaced by `org.openqa.selenium.WrapsElement`. [#1053](https://github.com/appium/java-client/pull/1053) + - SLF4J logging support added into Appium Driver local service. [#1014](https://github.com/appium/java-client/pull/1014) + - `IMAGE_MATCH_THRESHOLD`, `FIX_IMAGE_FIND_SCREENSHOT_DIMENSIONS`, `FIX_IMAGE_TEMPLATE_SIZE`, `CHECK_IMAGE_ELEMENT_STALENESS`, `UPDATE_IMAGE_ELEMENT_POSITION` and `IMAGE_ELEMENT_TAP_STRATEGY` setting was introduced for image elements. [#1011](https://github.com/appium/java-client/pull/1011) +- **[BUG FIX]** Better handling of InvocationTargetException [#968](https://github.com/appium/java-client/pull/968) +- **[BUG FIX]** Map sending keys to active element for W3C compatibility. [#966](https://github.com/appium/java-client/pull/966) +- **[BUG FIX]** Error message on session creation is improved. [#994](https://github.com/appium/java-client/pull/994) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 3.141.59. + - `com.google.code.gson:gson` was updated to 2.8.5. + - `org.apache.httpcomponents:httpclient` was updated to 4.5.6. + - `cglib:cglib` was updated to 3.2.8. + - `org.apache.commons:commons-lang3` was updated to 3.8. + - `org.springframework:spring-context` was updated to 5.1.0.RELEASE. + - `io.github.bonigarcia:webdrivermanager` was updated to 3.0.0. + - `org.eclipse.jdt:ecj` was updated to 3.14.0. + - `org.slf4j:slf4j-api` was updated to 1.7.25. + - `jacoco` was updated to 0.8.2. + - `checkstyle` was updated to 8.12. + - `gradle` was updated to 4.10.1. + - `org.openpnp:opencv` was removed. + +*6.1.0* +- **[BUG FIX]** Initing web socket clients lazily. Report [#911](https://github.com/appium/java-client/issues/911). FIX: [#912](https://github.com/appium/java-client/pull/912). +- **[BUG FIX]** Fix session payload for W3C. [#913](https://github.com/appium/java-client/pull/913) +- **[ENHANCEMENT]** Added TouchAction constructor argument verification [#923](https://github.com/appium/java-client/pull/923) +- **[BUG FIX]** Set retry flag to true by default for OkHttpFactory. [#928](https://github.com/appium/java-client/pull/928) +- **[BUG FIX]** Fix class cast exception on getting battery info. [#935](https://github.com/appium/java-client/pull/935) +- **[ENHANCEMENT]** Added an optional format argument to getDeviceTime and update the documentation. [#939](https://github.com/appium/java-client/pull/939) +- **[ENHANCEMENT]** The switching web socket client implementation to okhttp library. [#941](https://github.com/appium/java-client/pull/941) +- **[BUG FIX]** Fix of the bug [#924](https://github.com/appium/java-client/issues/924). [#951](https://github.com/appium/java-client/pull/951) + +*6.0.0* +- **[ENHANCEMENT]** Added an ability to set pressure value for iOS. [#879](https://github.com/appium/java-client/pull/879) +- **[ENHANCEMENT]** Added new server arguments `RELAXED_SECURITY` and `ENABLE_HEAP_DUMP`. [#880](https://github.com/appium/java-client/pull/880) +- **[BUG FIX]** Use default Selenium HTTP client factory [#877](https://github.com/appium/java-client/pull/877) +- **[ENHANCEMENT]** Supporting syslog broadcast with iOS [#871](https://github.com/appium/java-client/pull/871) +- **[ENHANCEMENT]** Added isKeyboardShown command for iOS [#887](https://github.com/appium/java-client/pull/887) +- **[ENHANCEMENT]** Added battery information accessors [#882](https://github.com/appium/java-client/pull/882) +- **[BREAKING CHANGE]** Removal of deprecated code. [#881](https://github.com/appium/java-client/pull/881) +- **[BUG FIX]** Added `NewAppiumSessionPayload`. Bug report: [#875](https://github.com/appium/java-client/issues/875). FIX: [#894](https://github.com/appium/java-client/pull/894) +- **[ENHANCEMENT]** Added ESPRESSO automation name [#908](https://github.com/appium/java-client/pull/908) +- **[ENHANCEMENT]** Added a method for output streams cleanup [#909](https://github.com/appium/java-client/pull/909) +- **[DEPENDENCY UPDATES]** + - `com.google.code.gson:gson` was updated to 2.8.4 + - `org.springframework:spring-context` was updated to 5.0.5.RELEASE + - `org.aspectj:aspectjweaver` was updated to 1.9.1 + - `org.glassfish.tyrus:tyrus-clien` was updated to 1.13.1 + - `org.glassfish.tyrus:tyrus-container-grizzly` was updated to 1.2.1 + - `org.seleniumhq.selenium:selenium-java` was updated to 3.12.0 + + +*6.0.0-BETA5* +- **[ENHANCEMENT]** Added clipboard handlers. [#855](https://github.com/appium/java-client/pull/855) [#869](https://github.com/appium/java-client/pull/869) +- **[ENHANCEMENT]** Added wrappers for Android logcat broadcaster. [#858](https://github.com/appium/java-client/pull/858) +- **[ENHANCEMENT]** Add bugreport option to Android screen recorder. [#852](https://github.com/appium/java-client/pull/852) +- **[BUG FIX]** Avoid amending parameters for SET_ALERT_VALUE endpoint. [#867](https://github.com/appium/java-client/pull/867) +- **[BREAKING CHANGE]** Refactor network connection setting on Android. [#865](https://github.com/appium/java-client/pull/865) +- **[BUG FIX]** **[BREAKING CHANGE]** Refactor of the `io.appium.java_client.AppiumFluentWait`. It uses `java.time.Duration` for time settings instead of `org.openqa.selenium.support.ui.Duration` and `java.util.concurrent.TimeUnit` [#863](https://github.com/appium/java-client/pull/863) +- **[BREAKING CHANGE]** `io.appium.java_client.pagefactory.TimeOutDuration` became deprecated. It is going to be removed. Use `java.time.Duration` instead. FIX [#742](https://github.com/appium/java-client/issues/742) [#863](https://github.com/appium/java-client/pull/863). +- **[BREAKING CHANGE]** `io.appium.java_client.pagefactory.WithTimeOut#unit` became deprecated. It is going to be removed. Use `io.appium.java_client.pagefactory.WithTimeOut#chronoUnit` instead. FIX [#742](https://github.com/appium/java-client/issues/742) [#863](https://github.com/appium/java-client/pull/863). +- **[BREAKING CHANGE]** constructors of `io.appium.java_client.pagefactory.AppiumElementLocatorFactory`, `io.appium.java_client.pagefactory.AppiumFieldDecorator` and `io.appium.java_client.pagefactory.AppiumElementLocator` which use `io.appium.java_client.pagefactory.TimeOutDuration` as a parameter became deprecated. Use new constructors which use `java.time.Duration`. +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 3.11.0 + +*6.0.0-BETA4* +- **[ENHANCEMENT]** Added handler for isDispalyed in W3C mode. [#833](https://github.com/appium/java-client/pull/833) +- **[ENHANCEMENT]** Added handlers for sending SMS, making GSM Call, setting GSM signal, voice, power capacity and power AC. [#834](https://github.com/appium/java-client/pull/834) +- **[ENHANCEMENT]** Added handlers for toggling wifi, airplane mode and data in android. [#835](https://github.com/appium/java-client/pull/835) +- **[DEPENDENCY UPDATES]** + - `org.apache.httpcomponents:httpclient` was updated to 4.5.5 + - `cglib:cglib` was updated to 3.2.6 + - `org.springframework:spring-context` was updated to 5.0.3.RELEASE + +*6.0.0-BETA3* +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 3.9.1 +- **[BREAKING CHANGE]** Removal of deprecated listener-methods from the AlertEventListener. [#797](https://github.com/appium/java-client/pull/797) +- **[BUG FIX]**. Fix the `pushFile` command. [#812](https://github.com/appium/java-client/pull/812) [#816](https://github.com/appium/java-client/pull/816) +- **[ENHANCEMENT]**. Implemented custom command codec. [#817](https://github.com/appium/java-client/pull/817), [#825](https://github.com/appium/java-client/pull/825) +- **[ENHANCEMENT]** Added handlers for lock/unlock in iOS. [#799](https://github.com/appium/java-client/pull/799) +- **[ENHANCEMENT]** AddEd endpoints for screen recording API for iOS and Android. [#814](https://github.com/appium/java-client/pull/814) +- **[MAJOR ENHANCEMENT]** W3C compliance was provided. [#829](https://github.com/appium/java-client/pull/829) +- **[ENHANCEMENT]** New capability `MobileCapabilityType.FORCE_MJSONWP` [#829](https://github.com/appium/java-client/pull/829) +- **[ENHANCEMENT]** Updated applications management endpoints. [#824](https://github.com/appium/java-client/pull/824) + +*6.0.0-BETA2* +- **[ENHANCEMENT]** The `fingerPrint` ability was added. It is supported by Android for now. [#473](https://github.com/appium/java-client/pull/473) [#786](https://github.com/appium/java-client/pull/786) +- **[BUG FIX]**. Less strict verification of the `PointOption`. [#795](https://github.com/appium/java-client/pull/795) + +*6.0.0-BETA1* +- **[ENHANCEMENT]** **[REFACTOR]** **[BREAKING CHANGE]** **[MAJOR CHANGE]** Improvements of the TouchActions API [#756](https://github.com/appium/java-client/pull/756), [#760](https://github.com/appium/java-client/pull/760): + - `io.appium.java_client.touch.ActionOptions` and sublasses were added + - old methods of the `TouchActions` were marked `@Deprecated` + - new methods which take new options. +- **[ENHANCEMENT]**. Appium drivr local service uses default process environment by default. [#753](https://github.com/appium/java-client/pull/753) +- **[BUG FIX]**. Removed 'set' prefix from waitForIdleTimeout setting. [#754](https://github.com/appium/java-client/pull/754) +- **[BUG FIX]**. The asking for session details was optimized. Issue report [764](https://github.com/appium/java-client/issues/764). + FIX [#769](https://github.com/appium/java-client/pull/769) +- **[BUG FIX]** **[REFACTOR]**. Inconcistent MissingParameterException was removed. Improvements of MultiTouchAction. Report: [#102](https://github.com/appium/java-client/issues/102). FIX [#772](https://github.com/appium/java-client/pull/772) +- **[DEPENDENCY UPDATES]** + - `org.apache.commons:commons-lang3` was updated to 3.7 + - `commons-io:commons-io` was updated to 2.6 + - `org.springframework:spring-context` was updated to 5.0.2.RELEASE + - `org.aspectj:aspectjweaver` was updated to 1.8.13 + - `org.seleniumhq.selenium:selenium-java` was updated to 3.7.1 + +*5.0.4* +- **[BUG FIX]**. Client was crashing when user was testing iOS with server 1.7.0. Report: [#732](https://github.com/appium/java-client/issues/732). Fix: [#733](https://github.com/appium/java-client/pull/733). +- **[REFACTOR]** **[BREAKING CHANGE]** Excessive invocation of the implicit waiting timeout was removed. This is the breaking change because API of `AppiumElementLocator` and `AppiumElementLocatorFactory` was changed. Request: [#735](https://github.com/appium/java-client/issues/735), FIXES: [#738](https://github.com/appium/java-client/pull/738), [#741](https://github.com/appium/java-client/pull/741) +- **[DEPENDENCY UPDATES]** + - org.seleniumhq.selenium:selenium-java to 3.6.0 + - com.google.code.gson:gson to 2.8.2 + - org.springframework:spring-context to 5.0.0.RELEASE + - org.aspectj:aspectjweaver to 1.8.11 + +*5.0.3* +- **[BUG FIX]** Selenuim version was reverted from boundaries to the single number. Issue report: [#718](https://github.com/appium/java-client/issues/718). FIX: [#722](https://github.com/appium/java-client/pull/722) +- **[ENHANCEMENT]** The `pushFile` was added to IOSDriver. Feature request: [#720](https://github.com/appium/java-client/issues/720). Implementation: [#721](https://github.com/appium/java-client/pull/721). This feature requires appium node server v>=1.7.0 + +*5.0.2* **[BUG FIX RELEASE]** +- **[BUG FIX]** Dependency conflict resolving. The report: [#714](https://github.com/appium/java-client/issues/714). The fix: [#717](https://github.com/appium/java-client/pull/717). This change may affect users who use htmlunit-driver and/or phantomjsdriver. At this case it is necessary to add it to dependency list and to exclude old selenium versions. + +*5.0.1* **[BUG FIX RELEASE]** +- **[BUG FIX]** The fix of the element genering on iOS was fixed. Issue report: [#704](https://github.com/appium/java-client/issues/704). Fix: [#705](https://github.com/appium/java-client/pull/705) + +*5.0.0* +- **[REFACTOR]** **[BREAKING CHANGE]** 5.0.0 finalization. Removal of obsolete code. [#660](https://github.com/appium/java-client/pull/660) +- **[ENHANCEMENT]** Enable nativeWebTap setting for iOS. [#658](https://github.com/appium/java-client/pull/658) +- **[ENHANCEMENT]** The `getCurrentPackage` was added. [#657](https://github.com/appium/java-client/pull/657) +- **[ENHANCEMENT]** The `toggleTouchIDEnrollment` was added. [#659](https://github.com/appium/java-client/pull/659) +- **[BUG FIX]** The clearing of existing actions/parameters after perform is invoked. [#663](https://github.com/appium/java-client/pull/663) +- **[BUG FIX]** [#669](https://github.com/appium/java-client/pull/669) missed parameters of the `OverrideWidget` were added: + - `iOSXCUITAutomation` + - `windowsAutomation` +- **[BUG FIX]** ByAll was re-implemented. [#680](https://github.com/appium/java-client/pull/680) +- **[BUG FIX]** **[BREAKING CHANGE]** The issue of compliance with Selenium grid 3.x was fixed. This change is breaking because now java_client is compatible with appiun server v>=1.6.5. Issue report [#655](https://github.com/appium/java-client/issues/655). FIX [#682](https://github.com/appium/java-client/pull/682) +- **[BUG FIX]** issues related to latest Selenium changes were fixed. Issue report [#696](https://github.com/appium/java-client/issues/696). Fix: [#699](https://github.com/appium/java-client/pull/699). +- **[UPDATE]** Dependency update + - `selenium-java` was updated to 3.5.x + - `org.apache.commons-lang3` was updated to 3.6 + - `org.springframework.spring-context` was updated to 4.3.10.RELEASE +- **[ENHANCEMENT]** Update of the touch ID enroll method. The older `PerformsTouchID#toggleTouchIDEnrollment` was marked `Deprecated`. + It is recoomended to use `PerformsTouchID#toggleTouchIDEnrollment(boolean)` instead. [#695](https://github.com/appium/java-client/pull/695) + + +*5.0.0-BETA9* +- **[ENHANCEMENT]** Page factory: Mixed locator strategies were implemented. Feature request:[#565](https://github.com/appium/java-client/issues/565) Implementation: [#646](https://github.com/appium/java-client/pull/646) +- **[DEPRECATED]** All the content of the `io.appium.java_client.youiengine` package was marked `Deprecated`. It is going to be removed. [#652](https://github.com/appium/java-client/pull/652) +- **[UPDATE]** Update of the `com.google.code.gson:gson` to v2.8.1. + +*5.0.0-BETA8* +- **[ENHANCEMENT]** Page factory classes became which had package visibility are `public` now. [#630](https://github.com/appium/java-client/pull/630) + - `io.appium.java_client.pagefactory.AppiumElementLocatorFactory` + - `io.appium.java_client.pagefactory.DefaultElementByBuilder` + - `io.appium.java_client.pagefactory.WidgetByBuilder` + +- **[ENHANCEMENT]** New capabilities were added [#626](https://github.com/appium/java-client/pull/626): + - `AndroidMobileCapabilityType#AUTO_GRANT_PERMISSIONS` + - `AndroidMobileCapabilityType#ANDROID_NATURAL_ORIENTATION` + - `IOSMobileCapabilityType#XCODE_ORG_ID` + - `IOSMobileCapabilityType#XCODE_SIGNING_ID` + - `IOSMobileCapabilityType#UPDATE_WDA_BUNDLEID` + - `IOSMobileCapabilityType#RESET_ON_SESSION_START_ONLY` + - `IOSMobileCapabilityType#COMMAND_TIMEOUTS` + - `IOSMobileCapabilityType#WDA_STARTUP_RETRIES` + - `IOSMobileCapabilityType#WDA_STARTUP_RETRY_INTERVAL` + - `IOSMobileCapabilityType#CONNECT_HARDWARE_KEYBOARD` + - `IOSMobileCapabilityType#MAX_TYPING_FREQUENCY` + - `IOSMobileCapabilityType#SIMPLE_ISVISIBLE_CHECK` + - `IOSMobileCapabilityType#USE_CARTHAGE_SSL` + - `IOSMobileCapabilityType#SHOULD_USE_SINGLETON_TESTMANAGER` + - `IOSMobileCapabilityType#START_IWDP` + - `IOSMobileCapabilityType#ALLOW_TOUCHID_ENROLL` + - `MobileCapabilityType#EVENT_TIMINGS` + +- **[UPDATE]** Dependencies were updated: + - `org.seleniumhq.selenium:selenium-java` was updated to 3.4.0 + - `cglib:cglib` was updated to 3.2.5 + - `org.apache.httpcomponents:httpclient` was updated to 4.5.3 + - `commons-validator:commons-validator` was updated to 1.6 + - `org.springframework:spring-context` was updated to 4.3.8.RELEASE + + +*5.0.0-BETA7* +- **[ENHANCEMENT]** The ability to customize the polling strategy of the waiting was provided. [#612](https://github.com/appium/java-client/pull/612) +- **[ENHANCEMENT]** **[REFACTOR]** Methods which were representing time deltas instead of elementary types became `Deprecated`. Methods which use `java.time.Duration` are suugested to be used. [#611](https://github.com/appium/java-client/pull/611) +- **[ENHANCEMENT]** The ability to calculate screenshots overlap was included. [#595](https://github.com/appium/java-client/pull/595). + + +*5.0.0-BETA6* +- **[UPDATE]** Update to Selenium 3.3.1 +- **[ENHANCEMENT]** iOS XCUIT mode automation: API to run application in background was added. [#593](https://github.com/appium/java-client/pull/593) +- **[BUG FIX]** Issue report: [#594](https://github.com/appium/java-client/issues/594). FIX: [#597](https://github.com/appium/java-client/pull/597) +- **[ENHANCEMENT]** The class chain locator was added. [#599](https://github.com/appium/java-client/pull/599) + + +*5.0.0-BETA5* +- **[UPDATE]** Update to Selenium 3.2.0 +- **[BUG FIX]** Excessive dependency on `guava` was removed. It causes errors. Issue report: [#588](https://github.com/appium/java-client/issues/588). FIX: [#589](https://github.com/appium/java-client/pull/589). +- **[ENHANCEMENT]**. The capability `io.appium.java_client.remote.AndroidMobileCapabilityType#SYSTEM_PORT` was added. [#591](https://github.com/appium/java-client/pull/591) + +*5.0.0-BETA4* +- **[ENHANCEMENT]** Android. API to read the performance data was added. [#562](https://github.com/appium/java-client/pull/562) +- **[REFACTOR]** Android. Simplified the activity starting by reducing the number of parameters through POJO clas. Old methods which start activities were marked `@Deprecated`. [#579](https://github.com/appium/java-client/pull/579) [#585](https://github.com/appium/java-client/pull/585) +- **[BUG FIX]** Issue report:[#574](https://github.com/appium/java-client/issues/574). Fix:[#582](https://github.com/appium/java-client/pull/582) + +*5.0.0-BETA3* +[BUG FIX] +- **[BUG FIX]**:Issue report: [#567](https://github.com/appium/java-client/issues/567). Fix: [#568](https://github.com/appium/java-client/pull/568) + +*5.0.0-BETA2* +- **[BUG FIX]**:Issue report: [#549](https://github.com/appium/java-client/issues/549). Fix: [#551](https://github.com/appium/java-client/pull/551) +- New capabilities were added [#533](https://github.com/appium/java-client/pull/553): + - `IOSMobileCapabilityType#USE_NEW_WDA` + - `IOSMobileCapabilityType#WDA_LAUNCH_TIMEOUT` + - `IOSMobileCapabilityType#WDA_CONNECTION_TIMEOUT` + +The capability `IOSMobileCapabilityType#REAL_DEVICE_LOGGER` was removed. [#533](https://github.com/appium/java-client/pull/553) + +- **[BUG FIX]/[ENHANCEMENT]**. Issue report: [#552](https://github.com/appium/java-client/issues/552). FIX [#556](https://github.com/appium/java-client/pull/556) + - Additional methods were added to the `io.appium.java_client.HasSessionDetails` + - `String getPlatformName()` + - `String getAutomationName()` + - `boolean isBrowser()` + - `io.appium.java_client.HasSessionDetails` is used by the ` io.appium.java_client.internal.JsonToMobileElementConverter ` to define which instance of the `org.openqa.selenium.WebElement` subclass should be created. + +- **[ENHANCEMENT]**: The additional event firing feature. PR: [#559](https://github.com/appium/java-client/pull/559). The [WIKI chapter about the event firing](https://github.com/appium/java-client/blob/master/docs/The-event_firing.md) was updated. + +*5.0.0-BETA1* +- **[MAJOR ENHANCEMENT]**: Migration to Java 8. Epic: [#399](https://github.com/appium/java-client/issues/399) + - API with default implementation. PR [#470](https://github.com/appium/java-client/pull/470) + - Tools that provide _Page Object_ engines were redesigned. The migration to [repeatable annotations](http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html). Details you can read there: [#497](https://github.com/appium/java-client/pull/497). [Documentation was synced as well](https://github.com/appium/java-client/blob/master/docs/Page-objects.md#also-it-is-possible-to-define-chained-or-any-possible-locators). + - The new functional interface `io.appium.java_client.functions.AppiumFunctio`n was designed. It extends `java.util.function.Function` and `com.google.common.base.Function`. It was designed in order to provide compatibility with the `org.openqa.selenium.support.ui.Wait` [#543](https://github.com/appium/java-client/pull/543) + - The new functional interface `io.appium.java_client.functions.ExpectedCondition` was designed. It extends `io.appium.java_client.functions.AppiumFunction` and ```org.openqa.selenium.support.ui.ExpectedCondition```. [#543](https://github.com/appium/java-client/pull/543) + - The new functional interface `io.appium.java_client.functions.ActionSupplier` was designed. It extends ```java.util.function.Supplier```. [#543](https://github.com/appium/java-client/pull/543) + +- **[MAJOR ENHANCEMENT]**: Migration from Maven to Gradle. Feature request is [#214](https://github.com/appium/java-client/issues/214). Fixes: [#442](https://github.com/appium/java-client/pull/442), [#465](https://github.com/appium/java-client/pull/465). + +- **[MAJOR ENHANCEMENT]** **[MAJOR REFACTORING]**. Non-abstract **AppiumDriver**: + - Now the `io.appium.java_client.AppiumDriver` can use an instance of any `io.appium.java_client.MobileBy` subclass for the searching. It should work as expected when current session supports the given selector. It will throw `org.openqa.selenium.WebDriverException` otherwise. [#462](https://github.com/appium/java-client/pull/462) + - The new interface `io.appium.java_client.FindsByFluentSelector` was added. [#462](https://github.com/appium/java-client/pull/462) + - API was redesigned: + + these interfaces were marked deprecated and they are going to be removed [#513](https://github.com/appium/java-client/pull/513)[#514](https://github.com/appium/java-client/pull/514): + - `io.appium.java_client.DeviceActionShortcuts` + - `io.appium.java_client.android.AndroidDeviceActionShortcuts` + - `io.appium.java_client.ios.IOSDeviceActionShortcuts` + + instead following inerfaces were designed: + - `io.appium.java_client.HasDeviceTime` + - `io.appium.java_client.HidesKeyboard` + - `io.appium.java_client.HidesKeyboardWithKeyName` + - `io.appium.java_client.PressesKeyCode` + - `io.appium.java_client.ios.ShakesDevice` + - `io.appium.java_client.HasSessionDetails` + _That was done because Windows automation tools have some features that were considered as Android-specific and iOS-specific._ + + The list of classes and methods which were marked _deprecated_ and they are going to be removed + - `AppiumDriver#swipe(int, int, int, int, int)` + - `AppiumDriver#pinch(WebElement)` + - `AppiumDriver#pinch(int, int)` + - `AppiumDriver#zoom(WebElement)` + - `AppiumDriver#zoom(int, int)` + - `AppiumDriver#tap(int, WebElement, int)` + - `AppiumDriver#tap(int, int, int, int)` + - `AppiumDriver#swipe(int, int, int, int, int)` + - `MobileElement#swipe(SwipeElementDirection, int)` + - `MobileElement#swipe(SwipeElementDirection, int, int, int)` + - `MobileElement#zoom()` + - `MobileElement#pinch()` + - `MobileElement#tap(int, int)` + - `io.appium.java_client.SwipeElementDirection` and `io.appium.java_client.TouchebleElement` also were marked deprecated. + + redesign of `TouchAction` and `MultiTouchAction` + - constructors were redesigned. There is no strict binding of `AppiumDriver` and `TouchAction` /`MultiTouchAction`. They can consume any instance of a class that implements `PerformsTouchActions`. + - `io.appium.java_client.ios.IOSTouchAction` was added. It extends `io.appium.java_client.TouchAction`. + - the new interface `io.appium.java_client.PerformsActions` was added. It unifies `TouchAction` and `MultiTouchAction` now. [#543](https://github.com/appium/java-client/pull/543) + + `JsonToMobileElementConverter` re-design [#532](https://github.com/appium/java-client/pull/532): + - unused `MobileElementToJsonConverter` was removed + - `JsonToMobileElementConverter` is not rhe abstract class now. It generates instances of MobileElement subclasses according to current session parameters + - `JsonToAndroidElementConverter` is deprecated now + - `JsonToIOSElementConverter` is depreacated now + - `JsonToYouiEngineElementConverter` is deprecated now. + - constructors of 'AppiumDriver' were re-designed. + - constructors of 'AndroidDriver' were re-designed. + - constructors of 'IOSDriver' were re-designed. + +- **[MAJOR ENHANCEMENT]** Windows automation. Epic [#471](https://github.com/appium/java-client/issues/471) + - The new interface `io.appium.java_client.FindsByWindowsAutomation` was added. [#462](https://github.com/appium/java-client/pull/462). With [@jonstoneman](https://github.com/jonstoneman) 's authorship. + - The new selector strategy `io.appium.java_client.MobileBy.ByWindowsAutomation` was added. [#462](https://github.com/appium/java-client/pull/462). With [@jonstoneman](https://github.com/jonstoneman) 's authorship. + - `io.appium.java_client.windows.WindowsDriver` was designed. [#538](https://github.com/appium/java-client/pull/538) + - `io.appium.java_client.windows.WindowsElement` was designed. [#538](https://github.com/appium/java-client/pull/538) + - `io.appium.java_client.windows.WindowsKeyCode ` was added. [#538](https://github.com/appium/java-client/pull/538) + - Page object tools were updated [#538](https://github.com/appium/java-client/pull/538) + - the `io.appium.java_client.pagefactory.WindowsFindBy` annotation was added. + - `io.appium.java_client.pagefactory.AppiumFieldDecorator` and supporting tools were actualized. + +- **[MAJOR ENHANCEMENT]** iOS XCUIT mode automation: + - `io.appium.java_client.remote.AutomationName#IOS_XCUI_TEST` was added + - The new interface `io.appium.java_client.FindsByIosNSPredicate` was added. [#462](https://github.com/appium/java-client/pull/462). With [@rafael-chavez](https://github.com/rafael-chavez) 's authorship. It is implemented by `io.appium.java_client.ios.IOSDriver` and `io.appium.java_client.ios.IOSElement`. + - The new selector strategy `io.appium.java_client.MobileBy.ByIosNsPredicate` was added. [#462](https://github.com/appium/java-client/pull/462). With [@rafael-chavez](https://github.com/rafael-chavez) 's authorship. + - Page object tools were updated [#545](https://github.com/appium/java-client/pull/545), [#546](https://github.com/appium/java-client/pull/546) + - the `io.appium.java_client.pagefactory.iOSXCUITFindBy` annotation was added. + - `io.appium.java_client.pagefactory.AppiumFieldDecorator` and supporting tools were actualized. + +- [ENHANCEMENT] Added the ability to set UiAutomator Congfigurator values. [#410](https://github.com/appium/java-client/pull/410). + [#477](https://github.com/appium/java-client/pull/477). +- [ENHANCEMENT]. Additional methods which perform device rotation were implemented. [#489](https://github.com/appium/java-client/pull/489). [#439](https://github.com/appium/java-client/pull/439). But it works for iOS in XCUIT mode and for Android in UIAutomator2 mode only. The feature request: [#7131](https://github.com/appium/appium/issues/7131) +- [ENHANCEMENT]. TouchID Implementation (iOS Sim Only). Details: [#509](https://github.com/appium/java-client/pull/509) +- [ENHANCEMENT]. The ability to use port, ip and log file as server arguments was provided. Feature request: [#521](https://github.com/appium/java-client/issues/521). Fixes: [#522](https://github.com/appium/java-client/issues/522), [#524](https://github.com/appium/java-client/issues/524). +- [ENHANCEMENT]. The new interface ```io.appium.java_client.android.HasDeviceDetails``` was added. It is implemented by ```io.appium.java_client.android.AndroidDriver``` by default. [#518](https://github.com/appium/java-client/pull/518) +- [ENHANCEMENT]. New touch actions were added. ```io.appium.java_client.ios.IOSTouchAction#doubleTap(WebElement, int, int)``` and ```io.appium.java_client.ios.IOSTouchAction#doubleTap(WebElement)```. [#523](https://github.com/appium/java-client/pull/523), [#444](https://github.com/appium/java-client/pull/444) +- [ENHANCEMENT]. All constructors declared by `io.appium.java_client.AppiumDriver` are public now. +- [BUG FIX]: There was the issue when "@WithTimeout" was changing general timeout of the waiting for elements. Bug report: [#467](https://github.com/appium/java-client/issues/467). Fixes: [#468](https://github.com/appium/java-client/issues/468), [#469](https://github.com/appium/java-client/issues/469), [#480](https://github.com/appium/java-client/issues/480). Read: [supported-settings](https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/settings.md#supported-settings) +- Added the server flag `io.appium.java_client.service.local.flags.AndroidServerFlag#REBOOT`. [#476](https://github.com/appium/java-client/pull/476) +- Added `io.appium.java_client.remote.AndroidMobileCapabilityType.APP_WAIT_DURATION ` capability. [#461](https://github.com/appium/java-client/pull/461) +- the new automation type `io.appium.java_client.remote.MobilePlatform#ANDROID_UIAUTOMATOR2` was add. +- the new automation type `io.appium.java_client.remote.MobilePlatform#YOUI_ENGINE` was add. +- Additional capabilities were addede: + - `IOSMobileCapabilityType#CUSTOM_SSL_CERT` + - `IOSMobileCapabilityType#TAP_WITH_SHORT_PRESS_DURATION` + - `IOSMobileCapabilityType#SCALE_FACTOR` + - `IOSMobileCapabilityType#WDA_LOCAL_PORT` + - `IOSMobileCapabilityType#SHOW_XCODE_LOG` + - `IOSMobileCapabilityType#REAL_DEVICE_LOGGER` + - `IOSMobileCapabilityType#IOS_INSTALL_PAUSE` + - `IOSMobileCapabilityType#XCODE_CONFIG_FILE` + - `IOSMobileCapabilityType#KEYCHAIN_PASSWORD` + - `IOSMobileCapabilityType#USE_PREBUILT_WDA` + - `IOSMobileCapabilityType#PREVENT_WDAATTACHMENTS` + - `IOSMobileCapabilityType#WEB_DRIVER_AGENT_URL` + - `IOSMobileCapabilityType#KEYCHAIN_PATH` + - `MobileCapabilityType#CLEAR_SYSTEM_FILES` +- **[UPDATE]** to Selenium 3.0.1. +- **[UPDATE]** to Spring Framework 4.3.5.RELEASE. +- **[UPDATE]** to AspectJ weaver 1.8.10. + + + +*4.1.2* + +- Following capabilities were added: + - `io.appium.java_client.remote.AndroidMobileCapabilityType.ANDROID_INSTALL_TIMEOUT` + - `io.appium.java_client.remote.AndroidMobileCapabilityType.NATIVE_WEB_SCREENSHOT` + - `io.appium.java_client.remote.AndroidMobileCapabilityType.ANDROID_SCREENSHOT_PATH`. The pull request: [#452](https://github.com/appium/java-client/pull/452) +- `org.openqa.selenium.Alert` was reimplemented for iOS. Details: [#459](https://github.com/appium/java-client/pull/459) +- The deprecated `io.appium.java_client.generic.searchcontext` was removed. +- The dependency on `com.google.code.gson` was updated to 2.7. Also it was adde to exclusions + for `org.seleniumhq.selenium` `selenium-java`. +- The new AutomationName was added. IOS_XCUI_TEST. It is needed for the further development. +- The new MobilePlatform was added. WINDOWS. It is needed for the further development. + +*4.1.1* + +BUG FIX: Issue [#450](https://github.com/appium/java-client/issues/450). Fix: [#451](https://github.com/appium/java-client/issues/451). Thanks to [@tutunang](https://github.com/appium/java-client/pull/451) for the report. + +*4.1.0* +- all code marked `@Deprecated` was removed. +- `getSessionDetails()` was added. Thanks to [@saikrishna321](https://github.com/saikrishna321) for the contribution. +- FIX [#362](https://github.com/appium/java-client/issues/362), [#220](https://github.com/appium/java-client/issues/220), [#323](https://github.com/appium/java-client/issues/323). Details read there: [#413](https://github.com/appium/java-client/pull/413) +- FIX [#392](https://github.com/appium/java-client/issues/392). Thanks to [@truebit](https://github.com/truebit) for the bug report. +- The dependency on `cglib` was replaced by the dependency on `cglib-nodep`. FIX [#418](https://github.com/appium/java-client/issues/418) +- The casting to the weaker interface `HasIdentity` instead of class `RemoteWebElement` was added. It is the internal refactoring of the `TouchAction`. [#432](https://github.com/appium/java-client/pull/432). Thanks to [@asolntsev](https://github.com/asolntsev) for the contribution. +- The `setValue` method was moved to `MobileElement`. It works against text input elements on Android. +- The dependency on `org.springframework` `spring-context` v`4.3.2.RELEASE` was added +- The dependency on `org.aspectj` `aspectjweaver` v`1.8.9` was added +- ENHANCEMENT: The alternative event firing engine. The feature request: [#242](https://github.com/appium/java-client/issues/242). + Implementation: [#437](https://github.com/appium/java-client/pull/437). Also [new WIKI chapter](https://github.com/appium/java-client/blob/master/docs/The-event_firing.md) was added. +- ENHANCEMENT: Convenient access to specific commands for each supported mobile OS. Details: [#445](https://github.com/appium/java-client/pull/445) +- dependencies and plugins were updated +- ENHANCEMENT: `YouiEngineDriver` was added. Details: [appium server #6215](https://github.com/appium/appium/pull/6215), [#429](https://github.com/appium/java-client/pull/429), [#448](https://github.com/appium/java-client/pull/448). It is just the draft of the new solution that is going to be extended further. Please stay tuned. There are many interesting things are coming up. Thanks to `You I Engine` team for the contribution. + +*4.0.0* +- all code marked `@Deprecated` was removed. Java client won't support old servers (v<1.5.0) + anymore. +- the ability to start an activity using Android intent actions, intent categories, flags and arguments + was added to `AndroidDriver`. Thanks to [@saikrishna321](https://github.com/saikrishna321) for the contribution. +- `scrollTo()` and `scrollToExact()` became deprecated. They are going to be removed in the next release. +- The interface `io.appium.java_client.ios.GetsNamedTextField` and the declared method `T getNamedTextField(String name)` are + deprecated as well. They are going to be removed in the next release. +- Methods `findElements(String by, String using)` and `findElement(String by, String using)` of `org.openga.selenium.remote.RemoteWebdriver` are public now. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget). +- the `io.appium.java_client.NetworkConnectionSetting` class was marked deprecated +- the enum `io.appium.java_client.android.Connection` was added. All supported network bitmasks are defined there. +- Android. Old methods which get/set connection were marked `@Deprecated` +- Android. New methods which consume/return `io.appium.java_client.android.Connection` were added. +- the `commandRepository` field is public now. The modification of the `MobileCommand` +- Constructors like `AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities)` were added to + `io.appium.java_client.android.AndroidDriver` and `io.appium.java_client.ios.IOSDriver` +- The refactoring of `io.appium.java_client.internal.JsonToMobileElementConverter`. Now it accepts + `org.openqa.selenium.remote.RemoteWebDriver` as the constructor parameter. It is possible to re-use + `io.appium.java_client.android.internal.JsonToAndroidElementConverter` or + `io.appium.java_client.ios.internal.JsonToIOSElementConverter` by RemoteWebDriver when it is needed. +- Constructors of the abstract `io.appium.java_client.AppiumDriver` were redesigned. Now they require + a subclass of `io.appium.java_client.internal.JsonToMobileElementConverter`. Constructors of + `io.appium.java_client.android.AndroidDriver` and `io.appium.java_client.ios.IOSDriver` are same still. +- The `pushFile(String remotePath, File file)` was added to AndroidDriver +- FIX of TouchAction. Instances of the TouchAction class are reusable now +- FIX of the swiping issue (iOS, server version >= 1.5.0). Now the swiping is implemented differently by + AndroidDriver and IOSDriver. Thanks to [@truebit](https://github.com/truebit) and [@nuggit32](https://github.com/nuggit32) for the catching. +- the project was integrated with [maven-checkstyle-plugin](https://maven.apache.org/plugins/maven-checkstyle-plugin/). Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the work +- source code was improved according to code style checking rules. +- the integration with `org.owasp dependency-check-maven` was added. Thanks to [@saikrishna321](https://github.com/saikrishna321) + for the work. +- the integration with `org.jacoco jacoco-maven-plugin` was added. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the contribution. + +*3.4.1* +- Update to Selenium v2.53.0 +- all dependencies were updated to latest versions +- the dependency on org.apache.commons commons-lang3 v3.4 was added +- the fix of Widget method invocation.[#340](https://github.com/appium/java-client/issues/340). A class visibility was taken into account. Thanks to [aznime](https://github.com/aznime) for the catching. + Server flags were added: + - GeneralServerFlag.ASYNC_TRACE + - IOSServerFlag.WEBKIT_DEBUG_PROXY_PORT +- Source code was formatted using [eclipse-java-google-style.xml](https://google-styleguide.googlecode.com/svn/trunk/eclipse-java-google-style.xml). This is not the complete solution. The code style checking is going to be added further. Thanks to [SrinivasanTarget](https://github.com/SrinivasanTarget) for the work! + +*3.4.0* +- Update to Selenium v2.52.0 +- `getAppStrings()` methods are deprecated now. They are going to be removed. `getAppStringMap()` methods were added and now return a map with app strings (keys and values) + instead of a string. Thanks to [@rgonalo](https://github.com/rgonalo) for the contribution. +- Add `getAppStringMap(String language, String stringFile)` method to allow searching app strings in the specified file +- FIXED of the bug which causes deadlocks of AppiumDriver LocalService in multithreading. Thanks to [saikrishna321](https://github.com/saikrishna321) for the [bug report](https://github.com/appium/java-client/issues/283). +- FIXED Zoom methods, thanks to [@kkhaidukov](https://github.com/kkhaidukov) +- FIXED The issue of compatibility of AppiumServiceBuilder with Appium node server v >= 1.5.x. Take a look at [#305](https://github.com/appium/java-client/issues/305) +- `getDeviceTime()` was added. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the contribution. +- FIXED `longPressKeyCode()` methods. Now they use the convenient JSONWP command.Thanks to [@kirillbilchenko](https://github.com/kirillbilchenko) for the proposed fix. +- FIXED javadoc. +- Page object tools were updated. Details read here: [#311](https://github.com/appium/java-client/issues/311), [#313](https://github.com/appium/java-client/pull/313), [#317](https://github.com/appium/java-client/pull/317). By.name locator strategy is deprecated for Android and iOS. It is still valid for the Selendroid mode. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the helping. +- The method `lockScreen(seconds)` is deprecated and it is going to be removed in the next release. Since Appium node server v1.5.x it is recommended to use + `AndroidDriver.lockDevice()...AndroidDriver.unlockDevice()` or `IOSDriver.lockDevice(int seconds)` instead. Thanks to [@namannigam](https://github.com/namannigam) for + the catching. Read [#315](https://github.com/appium/java-client/issues/315) +- `maven-release-plugin` was added to POM.XML configuration +- [#320](https://github.com/appium/java-client/issues/320) fix. The `Widget.getSelfReference()` was added. This method allows to extract a real widget-object from inside a proxy at some extraordinary situations. Read: [PR](https://github.com/appium/java-client/pull/327). Thanks to [SergeyErmakovMercDev](https://github.com/SergeyErmakovMercDev) for the reporting. +- all capabilities were added according to [this description](https://github.com/appium/appium/blob/1.5/docs/en/writing-running-appium/caps.md). There are three classes: `io.appium.java_client.remote.MobileCapabilityType` (just modified), `io.appium.java_client.remote.AndroidMobileCapabilityType` (android-specific capabilities), `io.appium.java_client.remote.IOSMobileCapabilityType` (iOS-specific capabilities). Details are here: [#326](https://github.com/appium/java-client/pull/326) +- some server flags were marked `deprecated` because they are deprecated since server node v1.5.x. These flags are going to be removed at the java client release. Details are here: [#326](https://github.com/appium/java-client/pull/326) +- The ability to start Appium node programmatically using desired capabilities. This feature is compatible with Appium node server v >= 1.5.x. Details are here: [#326](https://github.com/appium/java-client/pull/326) + +*3.3.0* +- updated the dependency on Selenium to version 2.48.2 +- bug fix and enhancements of io.appium.java_client.service.local.AppiumDriverLocalService + - FIXED bug which was found and reproduced with Eclipse for Mac OS X. Please read about details here: [#252](https://github.com/appium/java-client/issues/252) + Thanks to [saikrishna321](https://github.com/saikrishna321) for the bug report + - FIXED bug which was found out by [Jonahss](https://github.com/Jonahss). Thanks for the reporting. Details: [#272](https://github.com/appium/java-client/issues/272) + and [#273](https://github.com/appium/java-client/issues/273) + - For starting an appium server using localService, added additional environment variable to specify the location of Node.js binary: NODE_BINARY_PATH + - The ability to set additional output streams was provided +- The additional __startActivity()__ method was added to AndroidDriver. It allows to start activities without the stopping of a target app + Thanks to [deadmoto](https://github.com/deadmoto) for the contribution +- The additional extension of the Page Object design pattern was designed. Please read about details here: [#267](https://github.com/appium/java-client/pull/267) +- New public constructors to AndroidDriver/IOSDriver that allow passing a custom HttpClient.Factory Details: [#276](https://github.com/appium/java-client/pull/278) thanks to [baechul](https://github.com/baechul) + +*3.2.0* +- updated the dependency on Selenium to version 2.47.1 +- the new dependency on commons-validator v1.4.1 +- the ability to start programmatically/silently an Appium node server is provided now. Details please read at [#240](https://github.com/appium/java-client/pull/240). + Historical reference: [The similar solution](https://github.com/Genium-Framework/Appium-Support) has been designed by [@Hassan-Radi](https://github.com/Hassan-Radi). + The mentioned framework and the current solution use different approaches. +- Throwing declarations were added to some searching methods. The __"getMouse"__ method of RemoteWebDriver was marked __Deprecated__ +- Add `replaceValue` method for elements. +- Replace `sendKeyEvent()` method in android with pressKeyCode(int key) and added: pressKeyCode(int key, Integer metastate), longPressKeyCode(int key), longPressKeyCode(int key, Integer metastate) + +*3.1.1* +- Page-object findBy strategies are now aware of which driver (iOS or Android) you are using. For more details see the Pull Request: https://github.com/appium/java-client/pull/213 +- If somebody desires to use their own Webdriver implementation then it has to implement HasCapabilities. +- Added a new annotation: `WithTimeout`. This annotation allows one to specify a specific timeout for finding an element which overrides the drivers default timeout. For more info see: https://github.com/appium/java-client/pull/210 +- Corrected an uninformative Exception message. + +*3.0.0* +- AppiumDriver class is now a Generic. This allows us to return elements of class MobileElement (and its subclasses) instead of always returning WebElements and requiring users to cast to MobileElement. See https://github.com/appium/java-client/pull/182 +- Full set of Android KeyEvents added. +- Selenium client version updated to 2.46 +- PageObject enhancements +- Junit dependency removed + +*2.2.0* +- Added new TouchAction methods for LongPress, on an element, at x,y coordinates, or at an offset from within an element +- SwipeElementDirection changed. Read the documentation, it's now smarter about how/where to swipe +- Added APPIUM_VERSION MobileCapabilityType +- `sendKeyEvent()` moved from AppiumDriver to AndroidDriver +- `linkText` and `partialLinkText` locators added +- setValue() moved from MobileElement to iOSElement +- Fixed Selendroid PageAnnotations + +*2.1.0* +- Moved hasAppString() from AndroidDriver to AppiumDriver +- Fixes to PageFactory +- Added @AndroidFindAll and @iOSFindAll +- Added toggleLocationServices() to AndroidDriver +- Added touchAction methods to MobileElement, so now you can do `element.pinch()`, `element.zoom()`, etc. +- Added the ability to choose a direction to swipe over an element. Use the `SwipeElementDirection` enums: `UP, DOWN, LEFT, RIGHT` + +*2.0.0* +- AppiumDriver is now an abstract class, use IOSDriver and AndroidDriver which both extend it. You no longer need to include the `PLATFORM_NAME` desired capability since it's automatic for each class. Thanks to @TikhomirovSergey for all their work +- ScrollTo() and ScrollToExact() methods reimplemented +- Zoom() and Pinch() are now a little smarter and less likely to fail if you element is near the edge of the screen. Congratulate @BJap on their first PR! + +*1.7.0* +- Removed `scrollTo()` and `scrollToExact()` methods because they relied on `complexFind()`. They will be added back in the next version! +- Removed `complexFind()` +- Added `startActivity()` method +- Added `isLocked()` method +- Added `getSettings()` and `ignoreUnimportantViews()` methods + +*1.6.2* +- Added MobilePlatform interface (Android, IOS, FirefoxOS) +- Added MobileBrowserType interface (Safari, Browser, Chromium, Chrome) +- Added MobileCapabilityType.APP_WAIT_ACTIVITY +- Fixed small Integer cast issue (in Eclipse it won't compile) +- Set -source and -target of the Java Compiler to 1.7 (for maven compiler plugin) +- Fixed bug in Page Factory + +*1.6.1* +- Fixed the logic for checking connection status on NetworkConnectionSetting objects + +*1.6.0* +- Added @findBy annotations. Explanation here: https://github.com/appium/java-client/pull/68 Thanks to TikhomirovSergey +- Appium Driver now implements LocationContext interface, so setLocation() works for setting GPS coordinates + +*1.5.0* +- Added MobileCapabilityType enums for desired capabilities +- `findElement` and `findElements` return MobileElement objects (still need to be casted, but no longer instantiated) +- new appium v1.2 `hideKeyboard()` strategies added +- `getNetworkConnection()` and `setNetworkConnection()` commands added + +*1.4.0* +- Added openNotifications() method, to open the notifications shade on Android +- Added pullFolder() method, to pull an entire folder as a zip archive from a device/simulator +- Upgraded Selenium dependency to 2.42.2 + +*1.3.0* +- MultiGesture with a single TouchAction fixed for Android +- Now depends upon Selenium java client 2.42.1 +- Cleanup of Errorcode handling, due to merging a change into Selenium + +*1.2.1* +- fix dependency issue + +*1.2.0* +- complexFind() now returns MobileElement objects +- added scrollTo() and scrollToExact() methods for use with complexFind() + +*1.1.0* +- AppiumDriver now implements Rotatable. rotate() and getOrientation() methods added +- when no appium server is running, the proper error is thrown, instead of a NullPointerException + +*1.0.2* +- recompiled to include some missing methods such as shake() and complexFind() diff --git a/README.md b/README.md index f09334c06..596d6e564 100644 --- a/README.md +++ b/README.md @@ -228,864 +228,8 @@ server process. Consider checking the [Appium Environment Troubleshooting](docs/ document for more information on how to debug and fix process environment issues. ## Changelog -*8.2.1* -- **[ENHANCEMENTS]** - - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) - - Connect directly to Appium Hosts in Distributed Environments. [#1747](https://github.com/appium/java-client/pull/1747) - - use own User Agent. [#1779](https://github.com/appium/java-client/pull/1779) - - Add alternative proxy implementation. [#1790](https://github.com/appium/java-client/pull/1790) - - Automated artefact publish to maven central. [#1803](https://github.com/appium/java-client/pull/1803) & [#1807](https://github.com/appium/java-client/pull/1807) -- **[BUG FIX]** - - Enforce usage of Base64 compliant with RFC 4648 for all operations. [#1785](https://github.com/appium/java-client/pull/1785) - - Override getScreenshotAs to support the legacy base64 encoding. [#1787](https://github.com/appium/java-client/pull/1787) -- **[REFRACTOR]** - - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) - - JUnit5 test classes and methods are updated to have default package visibility. [#1755](https://github.com/appium/java-client/pull/1755) - - Verify if the PR title complies with conventional commits spec. [#1757](https://github.com/appium/java-client/pull/1757) - - Use Lombok in direct connect class. [#1789](https://github.com/appium/java-client/pull/1789) - - Update readme and remove obsolete documents. [#1792](https://github.com/appium/java-client/pull/1792) - - Remove unnecessary annotation. [#1791](https://github.com/appium/java-client/pull/1791) - - Force unified imports order. [#1793](https://github.com/appium/java-client/pull/1793) -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 4.5.0. - - `org.owasp.dependencycheck` was updated to 7.3.2. - - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.1. - - `org.junit.jupiter:junit-jupiter` was updated to 5.9.1. - - `org.slf4j:slf4j-api` was updated to 2.0.4. - - `com.google.code.gson:gson` was updated to 2.10.0. -*8.2.0* -- **[ENHANCEMENTS]** - - AppiumDriverLocalService can handle outputStreams. [#1709](https://github.com/appium/java-client/pull/1709) - - Add creating a driver with ClientConfig. [#1735](https://github.com/appium/java-client/pull/1735) -- **[BUG FIX]** - - Update the environment argument type for mac SupportsEnvironmentOption. [#1712](https://github.com/appium/java-client/pull/1712) -- **[REFRACTOR]** - - Deprecate Appium ByAll in favour of Selenium ByAll. [#1740](https://github.com/appium/java-client/pull/1740) - - Bump Node.js version in pipeline. [#1713](https://github.com/appium/java-client/pull/1713) - - Switch unit tests to run on Junit 5 Jupiter Platform. [#1721](https://github.com/appium/java-client/pull/1721) - - Clean up unit tests asserting thrown exceptions. [#1741](https://github.com/appium/java-client/pull/1741) - - Fix open notification test. [#1749](https://github.com/appium/java-client/pull/1749) - - update Azure pipeline to use macos-11 VM image. [#1728](https://github.com/appium/java-client/pull/1728) -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 4.4.0. - - `org.owasp.dependencycheck` was updated to 7.1.2. - - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.0. - - `gradle` was updated to 7.5.1. - - `com.google.code.gson:gson` was updated to 2.9.1. -*8.1.1* -- **[BUG FIX]** - - Perform safe typecast while getting the platform name. [#1702](https://github.com/appium/java-client/pull/1702) - - Add prefix to platformVersion capability name. [#1704](https://github.com/appium/java-client/pull/1704) -- **[REFRACTOR]** - - Update e2e tests to make it green. [#1706](https://github.com/appium/java-client/pull/1706) - - Ignore the test which has a connected server issue. [#1699](https://github.com/appium/java-client/pull/1699) - -*8.1.0* -- **[ENHANCEMENTS]** - - Add new EspressoBuildConfig options. [#1687](https://github.com/appium/java-client/pull/1687) -- **[DOCUMENTATION]** - - delete all references to removed MobileElement class. [#1677](https://github.com/appium/java-client/pull/1677) -- **[BUG FIX]** - - Pass orientation name capability in uppercase. [#1686](https://github.com/appium/java-client/pull/1686) - - correction for ping method to get proper status URL. [#1661](https://github.com/appium/java-client/pull/1661) - - Remove deprecated option classes. [#1679](https://github.com/appium/java-client/pull/1679) - - Remove obsolete event firing decorators. [#1676](https://github.com/appium/java-client/pull/1676) -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 4.2.0. - - `org.owasp.dependencycheck` was updated to 7.1.0.1. - - `org.springframework:spring-context` was removed. [#1676](https://github.com/appium/java-client/pull/1676) - - `org.aspectj:aspectjweaver` was updated to 1.9.9. - - `io.github.bonigarcia:webdrivermanager` was updated to 5.2.0. - - `org.projectlombok:lombok` was updated to 1.18.24. - -*8.0.0* -- **[DOCUMENTATION]** - - Set minimum Java version to 1.8.0. [#1631](https://github.com/appium/java-client/pull/1631) -- **[BUG FIX]** - - Make interfaces public to fix decorator creation. [#1644](https://github.com/appium/java-client/pull/1644) - - Do not convert argument names to lowercase. [#1627](https://github.com/appium/java-client/pull/1627) - - Avoid fallback to css for id and name locator annotations. [#1622](https://github.com/appium/java-client/pull/1622) - - Fix handling of chinese characters in `AppiumDriverLocalService`. [#1618](https://github.com/appium/java-client/pull/1618) -- **[DEPENDENCY UPDATES]** - - `org.owasp.dependencycheck` was updated to 7.0.0. - - `org.springframework:spring-context` was updated to 5.3.16. - - `actions/setup-java` was updated to 3. - - `actions/checkout` was updated to 3. - - `io.github.bonigarcia:webdrivermanager` was updated to 5.1.0. - - `org.aspectj:aspectjweaver` was updated to 1.9.8. - - `org.slf4j:slf4j-api` was updated to 1.7.36. - - `com.github.johnrengelman.shadow` was updated to 7.1.2. - -*8.0.0-beta2* -- **[DOCUMENTATION]** - - Add a link to options builder examples to the migration guide. [#1595](https://github.com/appium/java-client/pull/1595) -- **[BUG FIX]** - - Filter out proxyClassLookup method from Proxy class (for Java 16+) in AppiumByBuilder. [#1575](https://github.com/appium/java-client/pull/1575) -- **[REFRACTOR]** - - Add more nice functional stuff into page factory helpers. [#1584](https://github.com/appium/java-client/pull/1584) - - Switch e2e tests to use Appium2. [#1603](https://github.com/appium/java-client/pull/1603) - - relax constraints of Selenium dependencies versions. [#1606](https://github.com/appium/java-client/pull/1606) -- **[DEPENDENCY UPDATES]** - - Upgrade to Selenium 4.1.1. [#1613](https://github.com/appium/java-client/pull/1613) - - `org.owasp.dependencycheck` was updated to 6.5.1. - - `org.springframework:spring-context` was updated to 5.3.14. - - `actions/setup-java` was updated to 2.4.0. - - `gradle` was updated to 7.3. - -*8.0.0-beta* -- **[ENHANCEMENTS]** - - Start adding UiAutomator2 options. [#1543](https://github.com/appium/java-client/pull/1543) - - Add more UiAutomator2 options. [#1545](https://github.com/appium/java-client/pull/1545) - - Finish creating options for UiAutomator2 driver. [#1548](https://github.com/appium/java-client/pull/1548) - - Add WDA-related XCUITestOptions. [#1552](https://github.com/appium/java-client/pull/1552) - - Add web view options for XCUITest driver. [#1557](https://github.com/appium/java-client/pull/1557) - - Add the rest of XCUITest driver options. [#1561](https://github.com/appium/java-client/pull/1561) - - Add Espresso options. [#1563](https://github.com/appium/java-client/pull/1563) - - Add Windows driver options. [#1564](https://github.com/appium/java-client/pull/1564) - - Add Mac2 driver options. [#1565](https://github.com/appium/java-client/pull/1565) - - Add Gecko driver options. [#1573](https://github.com/appium/java-client/pull/1573) - - Add Safari driver options. [#1576](https://github.com/appium/java-client/pull/1576) - - Start adding XCUITest driver options. [#1551](https://github.com/appium/java-client/pull/1551) - - Implement driver-specific W3C option classes. [#1540](https://github.com/appium/java-client/pull/1540) - - Update Service to properly work with options. [#1550](https://github.com/appium/java-client/pull/1550) -- **[BREAKING CHANGE]** - - Migrate to Selenium 4. [#1531](https://github.com/appium/java-client/pull/1531) - - Make sure we only write W3C payload into create session command. [#1537](https://github.com/appium/java-client/pull/1537) - - Use the new session payload creator inherited from Selenium. [#1535](https://github.com/appium/java-client/pull/1535) - - unify locator factories naming and toString implementations. [#1538](https://github.com/appium/java-client/pull/1538) - - drop support of deprecated Selendroid driver. [#1553](https://github.com/appium/java-client/pull/1553) - - switch to javac compiler. [#1556](https://github.com/appium/java-client/pull/1556) - - revise used Selenium dependencies. [#1560](https://github.com/appium/java-client/pull/1560) - - change prefix to AppiumBy in locator toString implementation. [#1559](https://github.com/appium/java-client/pull/1559) - - enable dependencies caching. [#1567](https://github.com/appium/java-client/pull/1567) - - Include more tests into the pipeline. [#1566](https://github.com/appium/java-client/pull/1566) - - Tune setting of default platform names. [#1570](https://github.com/appium/java-client/pull/1570) - - Deprecate custom event listener implementation and default to the one provided by Selenium4. [#1541](https://github.com/appium/java-client/pull/1541) - - Deprecate touch actions. [#1569](https://github.com/appium/java-client/pull/1569) - - Deprecate legacy app management helpers. [#1571](https://github.com/appium/java-client/pull/1571) - - deprecate Windows UIAutomation selector. [#1562](https://github.com/appium/java-client/pull/1562) - - Remove unused entities. [#1572](https://github.com/appium/java-client/pull/1572) - - Remove setElementValue helper. [#1577](https://github.com/appium/java-client/pull/1577) - - Remove selenium package override. [#1555](https://github.com/appium/java-client/pull/1555) - - remove redundant exclusion of Gradle task signMavenJavaPublication. [#1568](https://github.com/appium/java-client/pull/1568) -- **[DEPENDENCY UPDATES]** - - `org.owasp.dependencycheck` was updated to 6.4.1. - - `com.google.code.gson:gson` was updated to 2.8.9. - -*7.6.0* -- **[ENHANCEMENTS]** - - Add custom commands dynamically [Appium 2.0]. [#1506](https://github.com/appium/java-client/pull/1506) - - New General Server flags are added [Appium 2.0]. [#1511](https://github.com/appium/java-client/pull/1511) - - Add support of extended Android geolocation. [#1492](https://github.com/appium/java-client/pull/1492) -- **[BUG FIX]** - - AndroidGeoLocation: update the constructor signature to mimic order of parameters in `org.openqa.selenium.html5.Location`. [#1526](https://github.com/appium/java-client/pull/1526) - - Prevent duplicate builds for PRs from base repo branches. [#1496](https://github.com/appium/java-client/pull/1496) - - Enable Dependabot for GitHub actions. [#1500](https://github.com/appium/java-client/pull/1500) - - bind mac2element in element map for mac platform. [#1474](https://github.com/appium/java-client/pull/1474) -- **[DEPENDENCY UPDATES]** - - `org.owasp.dependencycheck` was updated to 6.3.2. - - `org.projectlombok:lombok` was updated to 1.18.22. - - `com.github.johnrengelman.shadow` was updated to 7.1.0. - - `actions/setup-java` was updated to 2.3.1. - - `io.github.bonigarcia:webdrivermanager` was updated to 5.0.3. - - `org.springframework:spring-context` was updated to 5.3.10. - - `org.slf4j:slf4j-api` was updated to 1.7.32. - - `com.google.code.gson:gson` was updated to 2.8.8. - - `gradle` was updated to 7.1.1. - - `commons-io:commons-io` was updated to 2.11.0. - - `org.aspectj:aspectjweaver` was updated to 1.9.7. - - `org.eclipse.jdt:ecj` was updated to 3.26.0. - - `'junit:junit` was updated to 4.13.2. - -*7.5.1* -- **[ENHANCEMENTS]** - - Add iOS related annotations to tvOS. [#1456](https://github.com/appium/java-client/pull/1456) -- **[BUG FIX]** - - Bring back automatic quote escaping for desired capabilities command line arguments on windows. [#1454](https://github.com/appium/java-client/pull/1454) -- **[DEPENDENCY UPDATES]** - - `org.owasp.dependencycheck` was updated to 6.1.2. - - `org.eclipse.jdt:ecj` was updated to 3.25.0. - -*7.5.0* -- **[ENHANCEMENTS]** - - Add support for Appium Mac2Driver. [#1439](https://github.com/appium/java-client/pull/1439) - - Add support for multiple image occurrences. [#1445](https://github.com/appium/java-client/pull/1445) - - `BOUND_ELEMENTS_BY_INDEX` Setting was added. [#1418](https://github.com/appium/java-client/pull/1418) -- **[BUG FIX]** - - Use lower case for Windows platform key in ElementMap. [#1421](https://github.com/appium/java-client/pull/1421) -- **[DEPENDENCY UPDATES]** - - `org.apache.commons:commons-lang3` was updated to 3.12.0. - - `org.springframework:spring-context` was updated to 5.3.4. - - `org.owasp.dependencycheck` was updated to 6.1.0. - - `io.github.bonigarcia:webdrivermanager` was updated to 4.3.1. - - `org.eclipse.jdt:ecj` was updated to 3.24.0. - - `org.projectlombok:lombok` was updated to 1.18.16. - - `jcenter` repository was removed. - -*7.4.1* -- **[BUG FIX]** - - Fix the configuration of `selenium-java` dependency. [#1417](https://github.com/appium/java-client/pull/1417) -- **[DEPENDENCY UPDATES]** - - `gradle` was updated to 6.7.1. - - -*7.4.0* -- **[ENHANCEMENTS]** - - Add ability to set multiple settings. [#1409](https://github.com/appium/java-client/pull/1409) - - Support to execute Chrome DevTools Protocol commands against Android Chrome browser session. [#1375](https://github.com/appium/java-client/pull/1375) - - Add new upload options i.e withHeaders, withFormFields and withFileFieldName. [#1342](https://github.com/appium/java-client/pull/1342) - - Add AndroidOptions and iOSOptions. [#1331](https://github.com/appium/java-client/pull/1331) - - Add idempotency key to session creation requests. [#1327](https://github.com/appium/java-client/pull/1327) - - Add support for Android capability types: `buildToolsVersion`, `enforceAppInstall`, `ensureWebviewsHavePages`, `webviewDevtoolsPort`, and `remoteAppsCacheLimit`. [#1326](https://github.com/appium/java-client/pull/1326) - - Added OTHER_APPS and PRINT_PAGE_SOURCE_ON_FIND_FAILURE Mobile Capability Types. [#1323](https://github.com/appium/java-client/pull/1323) - - Make settings available for all AppiumDriver instances. [#1318](https://github.com/appium/java-client/pull/1318) - - Add wrappers for the Windows screen recorder. [#1313](https://github.com/appium/java-client/pull/1313) - - Add GitHub Action validating Gradle wrapper. [#1296](https://github.com/appium/java-client/pull/1296) - - Add support for Android viewmatcher. [#1293](https://github.com/appium/java-client/pull/1293) - - Update web view detection algorithm for iOS tests. [#1294](https://github.com/appium/java-client/pull/1294) - - Add allow-insecure and deny-insecure server flags. [#1282](https://github.com/appium/java-client/pull/1282) -- **[BUG FIX]** - - Fix jitpack build failures. [#1389](https://github.com/appium/java-client/pull/1389) - - Fix parse platformName if it is passed as enum item. [#1369](https://github.com/appium/java-client/pull/1369) - - Increase the timeout for graceful AppiumDriverLocalService termination. [#1354](https://github.com/appium/java-client/pull/1354) - - Avoid casting to RemoteWebElement in ElementOptions. [#1345](https://github.com/appium/java-client/pull/1345) - - Properly translate desiredCapabilities into a command line argument. [#1337](https://github.com/appium/java-client/pull/1337) - - Change getDeviceTime to call the `mobile` implementation. [#1332](https://github.com/appium/java-client/pull/1332) - - Remove appiumVersion from MobileCapabilityType. [#1325](https://github.com/appium/java-client/pull/1325) - - Set appropriate fluent wait timeouts. [#1316](https://github.com/appium/java-client/pull/1316) -- **[DOCUMENTATION UPDATES]** - - Update Appium Environment Troubleshooting. [#1358](https://github.com/appium/java-client/pull/1358) - - Address warnings printed by docs linter. [#1355](https://github.com/appium/java-client/pull/1355) - - Add java docs for various Mobile Options. [#1331](https://github.com/appium/java-client/pull/1331) - - Add AndroidFindBy, iOSXCUITFindBy and WindowsFindBy docs. [#1311](https://github.com/appium/java-client/pull/1311) - - Renamed maim.js to main.js. [#1277](https://github.com/appium/java-client/pull/1277) - - Improve Readability of Issue Template. [#1260](https://github.com/appium/java-client/pull/1260) - -*7.3.0* -- **[ENHANCEMENTS]** - - Add support for logging custom events on the Appium Server. [#1262](https://github.com/appium/java-client/pull/1262) - - Update Appium executable detection implementation. [#1256](https://github.com/appium/java-client/pull/1256) - - Avoid through NPE if any setting value is null. [#1241](https://github.com/appium/java-client/pull/1241) - - Settings API was improved to accept string names. [#1240](https://github.com/appium/java-client/pull/1240) - - Switch `runAppInBackground` iOS implementation in sync with other platforms. [#1229](https://github.com/appium/java-client/pull/1229) - - JavaDocs for AndroidMobileCapabilityType was updated. [#1238](https://github.com/appium/java-client/pull/1238) - - Github Actions were introduced instead of TravisCI. [#1219](https://github.com/appium/java-client/pull/1219) -- **[BUG FIX]** - - Fix return type of `getSystemBars` API. [#1216](https://github.com/appium/java-client/pull/1216) - - Avoid using `getSession` call for capabilities values retrieval [W3C Support]. [#1204](https://github.com/appium/java-client/pull/1204) - - Fix pagefactory list element initialisation when parameterised by generic type. [#1237](https://github.com/appium/java-client/pull/1237) - - Fix AndroidKey commands. [#1250](https://github.com/appium/java-client/pull/1250) - -*7.2.0* -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was reverted to stable version 3.141.59. [#1209](https://github.com/appium/java-client/pull/1209) - - `org.projectlombok:lombok:1.18.8` was introduced. [#1193](https://github.com/appium/java-client/pull/1193) -- **[ENHANCEMENTS]** - - `videoFilters` property was added to IOSStartScreenRecordingOptions. [#1180](https://github.com/appium/java-client/pull/1180) -- **[IMPROVEMENTS]** - - `Selendroid` automationName was deprecated. [#1198](https://github.com/appium/java-client/pull/1198) - - JavaDocs for AndroidMobileCapabilityType and IOSMobileCapabilityType were updated. [#1204](https://github.com/appium/java-client/pull/1204) - - JitPack builds were fixed. [#1203](https://github.com/appium/java-client/pull/1203) - -*7.1.0* -- **[ENHANCEMENTS]** - - Added an ability to get all the session details. [#1167 ](https://github.com/appium/java-client/pull/1167) - - `TRACK_SCROLL_EVENTS`, `ALLOW_INVISIBLE_ELEMENTS`, `ENABLE_NOTIFICATION_LISTENER`, - `NORMALIZE_TAG_NAMES` and `SHUTDOWN_ON_POWER_DISCONNECT` Android Settings were added. - - `KEYBOARD_AUTOCORRECTION`, `MJPEG_SCALING_FACTOR`, - `MJPEG_SERVER_SCREENSHOT_QUALITY`, `MJPEG_SERVER_FRAMERATE`, `SCREENSHOT_QUALITY` - and `KEYBOARD_PREDICTION` iOS Settings were added. - - `GET_MATCHED_IMAGE_RESULT`, `FIX_IMAGE_TEMPLATE_SCALE`, - `SHOULD_USE_COMPACT_RESPONSES`, `ELEMENT_RESPONSE_ATTRIBUTES` and - `DEFAULT_IMAGE_TEMPLATE_SCALE` settings were added for both Android and iOS [#1166](https://github.com/appium/java-client/pull/1166), [#1156 ](https://github.com/appium/java-client/pull/1156) and [#1120](https://github.com/appium/java-client/pull/1120) - - The new interface `io.appium.java_client.ExecutesDriverScript ` was added. [#1165](https://github.com/appium/java-client/pull/1165) - - Added an ability to get status of appium server. [#1153 ](https://github.com/appium/java-client/pull/1153) - - `tvOS` platform support was added. [#1142 ](https://github.com/appium/java-client/pull/1142) - - The new interface `io.appium.java_client. FindsByAndroidDataMatcher` was added. [#1106](https://github.com/appium/java-client/pull/1106) - - The selector strategy `io.appium.java_client.MobileBy.ByAndroidDataMatcher` was added. [#1106](https://github.com/appium/java-client/pull/1106) - - Selendroid for android and UIAutomation for iOS are removed. [#1077 ](https://github.com/appium/java-client/pull/1077) - - **[BUG FIX]** Platform Name enforced on driver creation is avoided now. [#1164 ](https://github.com/appium/java-client/pull/1164) - - **[BUG FIX]** Send both signalStrengh and signalStrength for `GSM_SIGNAL`. [#1115 ](https://github.com/appium/java-client/pull/1115) - - **[BUG FIX]** Null pointer exceptions when calling getCapabilities is handled better. [#1094 ](https://github.com/appium/java-client/pull/1094) - -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 4.0.0-alpha-1. - - `org.aspectj:aspectjweaver` was updated to 1.9.4. - - `org.apache.httpcomponents:httpclient` was updated to 4.5.9. - - `cglib:cglib` was updated to 3.2.12. - - `org.springframework:spring-context` was updated to 5.1.8.RELEASE. - - `io.github.bonigarcia:webdrivermanager` was updated to 3.6.1. - - `org.eclipse.jdt:ecj` was updated to 3.18.0. - - `com.github.jengelman.gradle.plugins:shadow` was updated to 5.1.0. - - `checkstyle` was updated to 8.22. - - `gradle` was updated to 5.4. - - `dependency-check-gradle` was updated to 5.1.0. - - `org.slf4j:slf4j-api` was updated to 1.7.26. - - `org.apache.commons:commons-lang3` was updated to 3.9. - -*7.0.0* -- **[ENHANCEMENTS]** - - The new interface `io.appium.java_client.FindsByAndroidViewTag` was added. [#996](https://github.com/appium/java-client/pull/996) - - The selector strategy `io.appium.java_client.MobileBy.ByAndroidViewTag` was added. [#996](https://github.com/appium/java-client/pull/996) - - The new interface `io.appium.java_client.FindsByImage` was added. [#990](https://github.com/appium/java-client/pull/990) - - The selector strategy `io.appium.java_client.MobileBy.ByImage` was added. [#990](https://github.com/appium/java-client/pull/990) - - The new interface `io.appium.java_client.FindsByCustom` was added. [#1041](https://github.com/appium/java-client/pull/1041) - - The selector strategy `io.appium.java_client.MobileBy.ByCustom` was added. [#1041](https://github.com/appium/java-client/pull/1041) - - DatatypeConverter is replaced with Base64 for JDK 9 compatibility. [#999](https://github.com/appium/java-client/pull/999) - - Expand touch options API to accept coordinates as Point. [#997](https://github.com/appium/java-client/pull/997) - - W3C capabilities written into firstMatch entity instead of alwaysMatch. [#1010](https://github.com/appium/java-client/pull/1010) - - `Selendroid` for android and `UIAutomation` for iOS is deprecated. [#1034](https://github.com/appium/java-client/pull/1034) and [#1074](https://github.com/appium/java-client/pull/1074) - - `videoScale` and `fps` screen recording options are introduced for iOS. [#1067](https://github.com/appium/java-client/pull/1067) - - `NORMALIZE_TAG_NAMES` setting was introduced for android. [#1073](https://github.com/appium/java-client/pull/1073) - - `threshold` argument was added to OccurrenceMatchingOptions. [#1060](https://github.com/appium/java-client/pull/1060) - - `org.openqa.selenium.internal.WrapsElement` replaced by `org.openqa.selenium.WrapsElement`. [#1053](https://github.com/appium/java-client/pull/1053) - - SLF4J logging support added into Appium Driver local service. [#1014](https://github.com/appium/java-client/pull/1014) - - `IMAGE_MATCH_THRESHOLD`, `FIX_IMAGE_FIND_SCREENSHOT_DIMENSIONS`, `FIX_IMAGE_TEMPLATE_SIZE`, `CHECK_IMAGE_ELEMENT_STALENESS`, `UPDATE_IMAGE_ELEMENT_POSITION` and `IMAGE_ELEMENT_TAP_STRATEGY` setting was introduced for image elements. [#1011](https://github.com/appium/java-client/pull/1011) -- **[BUG FIX]** Better handling of InvocationTargetException [#968](https://github.com/appium/java-client/pull/968) -- **[BUG FIX]** Map sending keys to active element for W3C compatibility. [#966](https://github.com/appium/java-client/pull/966) -- **[BUG FIX]** Error message on session creation is improved. [#994](https://github.com/appium/java-client/pull/994) -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 3.141.59. - - `com.google.code.gson:gson` was updated to 2.8.5. - - `org.apache.httpcomponents:httpclient` was updated to 4.5.6. - - `cglib:cglib` was updated to 3.2.8. - - `org.apache.commons:commons-lang3` was updated to 3.8. - - `org.springframework:spring-context` was updated to 5.1.0.RELEASE. - - `io.github.bonigarcia:webdrivermanager` was updated to 3.0.0. - - `org.eclipse.jdt:ecj` was updated to 3.14.0. - - `org.slf4j:slf4j-api` was updated to 1.7.25. - - `jacoco` was updated to 0.8.2. - - `checkstyle` was updated to 8.12. - - `gradle` was updated to 4.10.1. - - `org.openpnp:opencv` was removed. - -*6.1.0* -- **[BUG FIX]** Initing web socket clients lazily. Report [#911](https://github.com/appium/java-client/issues/911). FIX: [#912](https://github.com/appium/java-client/pull/912). -- **[BUG FIX]** Fix session payload for W3C. [#913](https://github.com/appium/java-client/pull/913) -- **[ENHANCEMENT]** Added TouchAction constructor argument verification [#923](https://github.com/appium/java-client/pull/923) -- **[BUG FIX]** Set retry flag to true by default for OkHttpFactory. [#928](https://github.com/appium/java-client/pull/928) -- **[BUG FIX]** Fix class cast exception on getting battery info. [#935](https://github.com/appium/java-client/pull/935) -- **[ENHANCEMENT]** Added an optional format argument to getDeviceTime and update the documentation. [#939](https://github.com/appium/java-client/pull/939) -- **[ENHANCEMENT]** The switching web socket client implementation to okhttp library. [#941](https://github.com/appium/java-client/pull/941) -- **[BUG FIX]** Fix of the bug [#924](https://github.com/appium/java-client/issues/924). [#951](https://github.com/appium/java-client/pull/951) - -*6.0.0* -- **[ENHANCEMENT]** Added an ability to set pressure value for iOS. [#879](https://github.com/appium/java-client/pull/879) -- **[ENHANCEMENT]** Added new server arguments `RELAXED_SECURITY` and `ENABLE_HEAP_DUMP`. [#880](https://github.com/appium/java-client/pull/880) -- **[BUG FIX]** Use default Selenium HTTP client factory [#877](https://github.com/appium/java-client/pull/877) -- **[ENHANCEMENT]** Supporting syslog broadcast with iOS [#871](https://github.com/appium/java-client/pull/871) -- **[ENHANCEMENT]** Added isKeyboardShown command for iOS [#887](https://github.com/appium/java-client/pull/887) -- **[ENHANCEMENT]** Added battery information accessors [#882](https://github.com/appium/java-client/pull/882) -- **[BREAKING CHANGE]** Removal of deprecated code. [#881](https://github.com/appium/java-client/pull/881) -- **[BUG FIX]** Added `NewAppiumSessionPayload`. Bug report: [#875](https://github.com/appium/java-client/issues/875). FIX: [#894](https://github.com/appium/java-client/pull/894) -- **[ENHANCEMENT]** Added ESPRESSO automation name [#908](https://github.com/appium/java-client/pull/908) -- **[ENHANCEMENT]** Added a method for output streams cleanup [#909](https://github.com/appium/java-client/pull/909) -- **[DEPENDENCY UPDATES]** - - `com.google.code.gson:gson` was updated to 2.8.4 - - `org.springframework:spring-context` was updated to 5.0.5.RELEASE - - `org.aspectj:aspectjweaver` was updated to 1.9.1 - - `org.glassfish.tyrus:tyrus-clien` was updated to 1.13.1 - - `org.glassfish.tyrus:tyrus-container-grizzly` was updated to 1.2.1 - - `org.seleniumhq.selenium:selenium-java` was updated to 3.12.0 - - -*6.0.0-BETA5* -- **[ENHANCEMENT]** Added clipboard handlers. [#855](https://github.com/appium/java-client/pull/855) [#869](https://github.com/appium/java-client/pull/869) -- **[ENHANCEMENT]** Added wrappers for Android logcat broadcaster. [#858](https://github.com/appium/java-client/pull/858) -- **[ENHANCEMENT]** Add bugreport option to Android screen recorder. [#852](https://github.com/appium/java-client/pull/852) -- **[BUG FIX]** Avoid amending parameters for SET_ALERT_VALUE endpoint. [#867](https://github.com/appium/java-client/pull/867) -- **[BREAKING CHANGE]** Refactor network connection setting on Android. [#865](https://github.com/appium/java-client/pull/865) -- **[BUG FIX]** **[BREAKING CHANGE]** Refactor of the `io.appium.java_client.AppiumFluentWait`. It uses `java.time.Duration` for time settings instead of `org.openqa.selenium.support.ui.Duration` and `java.util.concurrent.TimeUnit` [#863](https://github.com/appium/java-client/pull/863) -- **[BREAKING CHANGE]** `io.appium.java_client.pagefactory.TimeOutDuration` became deprecated. It is going to be removed. Use `java.time.Duration` instead. FIX [#742](https://github.com/appium/java-client/issues/742) [#863](https://github.com/appium/java-client/pull/863). -- **[BREAKING CHANGE]** `io.appium.java_client.pagefactory.WithTimeOut#unit` became deprecated. It is going to be removed. Use `io.appium.java_client.pagefactory.WithTimeOut#chronoUnit` instead. FIX [#742](https://github.com/appium/java-client/issues/742) [#863](https://github.com/appium/java-client/pull/863). -- **[BREAKING CHANGE]** constructors of `io.appium.java_client.pagefactory.AppiumElementLocatorFactory`, `io.appium.java_client.pagefactory.AppiumFieldDecorator` and `io.appium.java_client.pagefactory.AppiumElementLocator` which use `io.appium.java_client.pagefactory.TimeOutDuration` as a parameter became deprecated. Use new constructors which use `java.time.Duration`. -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 3.11.0 - -*6.0.0-BETA4* -- **[ENHANCEMENT]** Added handler for isDispalyed in W3C mode. [#833](https://github.com/appium/java-client/pull/833) -- **[ENHANCEMENT]** Added handlers for sending SMS, making GSM Call, setting GSM signal, voice, power capacity and power AC. [#834](https://github.com/appium/java-client/pull/834) -- **[ENHANCEMENT]** Added handlers for toggling wifi, airplane mode and data in android. [#835](https://github.com/appium/java-client/pull/835) -- **[DEPENDENCY UPDATES]** - - `org.apache.httpcomponents:httpclient` was updated to 4.5.5 - - `cglib:cglib` was updated to 3.2.6 - - `org.springframework:spring-context` was updated to 5.0.3.RELEASE - -*6.0.0-BETA3* -- **[DEPENDENCY UPDATES]** - - `org.seleniumhq.selenium:selenium-java` was updated to 3.9.1 -- **[BREAKING CHANGE]** Removal of deprecated listener-methods from the AlertEventListener. [#797](https://github.com/appium/java-client/pull/797) -- **[BUG FIX]**. Fix the `pushFile` command. [#812](https://github.com/appium/java-client/pull/812) [#816](https://github.com/appium/java-client/pull/816) -- **[ENHANCEMENT]**. Implemented custom command codec. [#817](https://github.com/appium/java-client/pull/817), [#825](https://github.com/appium/java-client/pull/825) -- **[ENHANCEMENT]** Added handlers for lock/unlock in iOS. [#799](https://github.com/appium/java-client/pull/799) -- **[ENHANCEMENT]** AddEd endpoints for screen recording API for iOS and Android. [#814](https://github.com/appium/java-client/pull/814) -- **[MAJOR ENHANCEMENT]** W3C compliance was provided. [#829](https://github.com/appium/java-client/pull/829) -- **[ENHANCEMENT]** New capability `MobileCapabilityType.FORCE_MJSONWP` [#829](https://github.com/appium/java-client/pull/829) -- **[ENHANCEMENT]** Updated applications management endpoints. [#824](https://github.com/appium/java-client/pull/824) - -*6.0.0-BETA2* -- **[ENHANCEMENT]** The `fingerPrint` ability was added. It is supported by Android for now. [#473](https://github.com/appium/java-client/pull/473) [#786](https://github.com/appium/java-client/pull/786) -- **[BUG FIX]**. Less strict verification of the `PointOption`. [#795](https://github.com/appium/java-client/pull/795) - -*6.0.0-BETA1* -- **[ENHANCEMENT]** **[REFACTOR]** **[BREAKING CHANGE]** **[MAJOR CHANGE]** Improvements of the TouchActions API [#756](https://github.com/appium/java-client/pull/756), [#760](https://github.com/appium/java-client/pull/760): - - `io.appium.java_client.touch.ActionOptions` and sublasses were added - - old methods of the `TouchActions` were marked `@Deprecated` - - new methods which take new options. -- **[ENHANCEMENT]**. Appium drivr local service uses default process environment by default. [#753](https://github.com/appium/java-client/pull/753) -- **[BUG FIX]**. Removed 'set' prefix from waitForIdleTimeout setting. [#754](https://github.com/appium/java-client/pull/754) -- **[BUG FIX]**. The asking for session details was optimized. Issue report [764](https://github.com/appium/java-client/issues/764). -FIX [#769](https://github.com/appium/java-client/pull/769) -- **[BUG FIX]** **[REFACTOR]**. Inconcistent MissingParameterException was removed. Improvements of MultiTouchAction. Report: [#102](https://github.com/appium/java-client/issues/102). FIX [#772](https://github.com/appium/java-client/pull/772) -- **[DEPENDENCY UPDATES]** - - `org.apache.commons:commons-lang3` was updated to 3.7 - - `commons-io:commons-io` was updated to 2.6 - - `org.springframework:spring-context` was updated to 5.0.2.RELEASE - - `org.aspectj:aspectjweaver` was updated to 1.8.13 - - `org.seleniumhq.selenium:selenium-java` was updated to 3.7.1 - -*5.0.4* -- **[BUG FIX]**. Client was crashing when user was testing iOS with server 1.7.0. Report: [#732](https://github.com/appium/java-client/issues/732). Fix: [#733](https://github.com/appium/java-client/pull/733). -- **[REFACTOR]** **[BREAKING CHANGE]** Excessive invocation of the implicit waiting timeout was removed. This is the breaking change because API of `AppiumElementLocator` and `AppiumElementLocatorFactory` was changed. Request: [#735](https://github.com/appium/java-client/issues/735), FIXES: [#738](https://github.com/appium/java-client/pull/738), [#741](https://github.com/appium/java-client/pull/741) -- **[DEPENDENCY UPDATES]** - - org.seleniumhq.selenium:selenium-java to 3.6.0 - - com.google.code.gson:gson to 2.8.2 - - org.springframework:spring-context to 5.0.0.RELEASE - - org.aspectj:aspectjweaver to 1.8.11 - -*5.0.3* -- **[BUG FIX]** Selenuim version was reverted from boundaries to the single number. Issue report: [#718](https://github.com/appium/java-client/issues/718). FIX: [#722](https://github.com/appium/java-client/pull/722) -- **[ENHANCEMENT]** The `pushFile` was added to IOSDriver. Feature request: [#720](https://github.com/appium/java-client/issues/720). Implementation: [#721](https://github.com/appium/java-client/pull/721). This feature requires appium node server v>=1.7.0 - -*5.0.2* **[BUG FIX RELEASE]** -- **[BUG FIX]** Dependency conflict resolving. The report: [#714](https://github.com/appium/java-client/issues/714). The fix: [#717](https://github.com/appium/java-client/pull/717). This change may affect users who use htmlunit-driver and/or phantomjsdriver. At this case it is necessary to add it to dependency list and to exclude old selenium versions. - -*5.0.1* **[BUG FIX RELEASE]** -- **[BUG FIX]** The fix of the element genering on iOS was fixed. Issue report: [#704](https://github.com/appium/java-client/issues/704). Fix: [#705](https://github.com/appium/java-client/pull/705) - -*5.0.0* -- **[REFACTOR]** **[BREAKING CHANGE]** 5.0.0 finalization. Removal of obsolete code. [#660](https://github.com/appium/java-client/pull/660) -- **[ENHANCEMENT]** Enable nativeWebTap setting for iOS. [#658](https://github.com/appium/java-client/pull/658) -- **[ENHANCEMENT]** The `getCurrentPackage` was added. [#657](https://github.com/appium/java-client/pull/657) -- **[ENHANCEMENT]** The `toggleTouchIDEnrollment` was added. [#659](https://github.com/appium/java-client/pull/659) -- **[BUG FIX]** The clearing of existing actions/parameters after perform is invoked. [#663](https://github.com/appium/java-client/pull/663) -- **[BUG FIX]** [#669](https://github.com/appium/java-client/pull/669) missed parameters of the `OverrideWidget` were added: - - `iOSXCUITAutomation` - - `windowsAutomation` -- **[BUG FIX]** ByAll was re-implemented. [#680](https://github.com/appium/java-client/pull/680) -- **[BUG FIX]** **[BREAKING CHANGE]** The issue of compliance with Selenium grid 3.x was fixed. This change is breaking because now java_client is compatible with appiun server v>=1.6.5. Issue report [#655](https://github.com/appium/java-client/issues/655). FIX [#682](https://github.com/appium/java-client/pull/682) -- **[BUG FIX]** issues related to latest Selenium changes were fixed. Issue report [#696](https://github.com/appium/java-client/issues/696). Fix: [#699](https://github.com/appium/java-client/pull/699). -- **[UPDATE]** Dependency update - - `selenium-java` was updated to 3.5.x - - `org.apache.commons-lang3` was updated to 3.6 - - `org.springframework.spring-context` was updated to 4.3.10.RELEASE -- **[ENHANCEMENT]** Update of the touch ID enroll method. The older `PerformsTouchID#toggleTouchIDEnrollment` was marked `Deprecated`. -It is recoomended to use `PerformsTouchID#toggleTouchIDEnrollment(boolean)` instead. [#695](https://github.com/appium/java-client/pull/695) - - -*5.0.0-BETA9* -- **[ENHANCEMENT]** Page factory: Mixed locator strategies were implemented. Feature request:[#565](https://github.com/appium/java-client/issues/565) Implementation: [#646](https://github.com/appium/java-client/pull/646) -- **[DEPRECATED]** All the content of the `io.appium.java_client.youiengine` package was marked `Deprecated`. It is going to be removed. [#652](https://github.com/appium/java-client/pull/652) -- **[UPDATE]** Update of the `com.google.code.gson:gson` to v2.8.1. - -*5.0.0-BETA8* -- **[ENHANCEMENT]** Page factory classes became which had package visibility are `public` now. [#630](https://github.com/appium/java-client/pull/630) - - `io.appium.java_client.pagefactory.AppiumElementLocatorFactory` - - `io.appium.java_client.pagefactory.DefaultElementByBuilder` - - `io.appium.java_client.pagefactory.WidgetByBuilder` - -- **[ENHANCEMENT]** New capabilities were added [#626](https://github.com/appium/java-client/pull/626): - - `AndroidMobileCapabilityType#AUTO_GRANT_PERMISSIONS` - - `AndroidMobileCapabilityType#ANDROID_NATURAL_ORIENTATION` - - `IOSMobileCapabilityType#XCODE_ORG_ID` - - `IOSMobileCapabilityType#XCODE_SIGNING_ID` - - `IOSMobileCapabilityType#UPDATE_WDA_BUNDLEID` - - `IOSMobileCapabilityType#RESET_ON_SESSION_START_ONLY` - - `IOSMobileCapabilityType#COMMAND_TIMEOUTS` - - `IOSMobileCapabilityType#WDA_STARTUP_RETRIES` - - `IOSMobileCapabilityType#WDA_STARTUP_RETRY_INTERVAL` - - `IOSMobileCapabilityType#CONNECT_HARDWARE_KEYBOARD` - - `IOSMobileCapabilityType#MAX_TYPING_FREQUENCY` - - `IOSMobileCapabilityType#SIMPLE_ISVISIBLE_CHECK` - - `IOSMobileCapabilityType#USE_CARTHAGE_SSL` - - `IOSMobileCapabilityType#SHOULD_USE_SINGLETON_TESTMANAGER` - - `IOSMobileCapabilityType#START_IWDP` - - `IOSMobileCapabilityType#ALLOW_TOUCHID_ENROLL` - - `MobileCapabilityType#EVENT_TIMINGS` - -- **[UPDATE]** Dependencies were updated: - - `org.seleniumhq.selenium:selenium-java` was updated to 3.4.0 - - `cglib:cglib` was updated to 3.2.5 - - `org.apache.httpcomponents:httpclient` was updated to 4.5.3 - - `commons-validator:commons-validator` was updated to 1.6 - - `org.springframework:spring-context` was updated to 4.3.8.RELEASE - - -*5.0.0-BETA7* -- **[ENHANCEMENT]** The ability to customize the polling strategy of the waiting was provided. [#612](https://github.com/appium/java-client/pull/612) -- **[ENHANCEMENT]** **[REFACTOR]** Methods which were representing time deltas instead of elementary types became `Deprecated`. Methods which use `java.time.Duration` are suugested to be used. [#611](https://github.com/appium/java-client/pull/611) -- **[ENHANCEMENT]** The ability to calculate screenshots overlap was included. [#595](https://github.com/appium/java-client/pull/595). - - -*5.0.0-BETA6* -- **[UPDATE]** Update to Selenium 3.3.1 -- **[ENHANCEMENT]** iOS XCUIT mode automation: API to run application in background was added. [#593](https://github.com/appium/java-client/pull/593) -- **[BUG FIX]** Issue report: [#594](https://github.com/appium/java-client/issues/594). FIX: [#597](https://github.com/appium/java-client/pull/597) -- **[ENHANCEMENT]** The class chain locator was added. [#599](https://github.com/appium/java-client/pull/599) - - -*5.0.0-BETA5* -- **[UPDATE]** Update to Selenium 3.2.0 -- **[BUG FIX]** Excessive dependency on `guava` was removed. It causes errors. Issue report: [#588](https://github.com/appium/java-client/issues/588). FIX: [#589](https://github.com/appium/java-client/pull/589). -- **[ENHANCEMENT]**. The capability `io.appium.java_client.remote.AndroidMobileCapabilityType#SYSTEM_PORT` was added. [#591](https://github.com/appium/java-client/pull/591) - -*5.0.0-BETA4* -- **[ENHANCEMENT]** Android. API to read the performance data was added. [#562](https://github.com/appium/java-client/pull/562) -- **[REFACTOR]** Android. Simplified the activity starting by reducing the number of parameters through POJO clas. Old methods which start activities were marked `@Deprecated`. [#579](https://github.com/appium/java-client/pull/579) [#585](https://github.com/appium/java-client/pull/585) -- **[BUG FIX]** Issue report:[#574](https://github.com/appium/java-client/issues/574). Fix:[#582](https://github.com/appium/java-client/pull/582) - -*5.0.0-BETA3* -[BUG FIX] -- **[BUG FIX]**:Issue report: [#567](https://github.com/appium/java-client/issues/567). Fix: [#568](https://github.com/appium/java-client/pull/568) - -*5.0.0-BETA2* -- **[BUG FIX]**:Issue report: [#549](https://github.com/appium/java-client/issues/549). Fix: [#551](https://github.com/appium/java-client/pull/551) -- New capabilities were added [#533](https://github.com/appium/java-client/pull/553): - - `IOSMobileCapabilityType#USE_NEW_WDA` - - `IOSMobileCapabilityType#WDA_LAUNCH_TIMEOUT` - - `IOSMobileCapabilityType#WDA_CONNECTION_TIMEOUT` - -The capability `IOSMobileCapabilityType#REAL_DEVICE_LOGGER` was removed. [#533](https://github.com/appium/java-client/pull/553) - -- **[BUG FIX]/[ENHANCEMENT]**. Issue report: [#552](https://github.com/appium/java-client/issues/552). FIX [#556](https://github.com/appium/java-client/pull/556) - - Additional methods were added to the `io.appium.java_client.HasSessionDetails` - - `String getPlatformName()` - - `String getAutomationName()` - - `boolean isBrowser()` - - `io.appium.java_client.HasSessionDetails` is used by the ` io.appium.java_client.internal.JsonToMobileElementConverter ` to define which instance of the `org.openqa.selenium.WebElement` subclass should be created. - -- **[ENHANCEMENT]**: The additional event firing feature. PR: [#559](https://github.com/appium/java-client/pull/559). The [WIKI chapter about the event firing](https://github.com/appium/java-client/blob/master/docs/The-event_firing.md) was updated. - -*5.0.0-BETA1* -- **[MAJOR ENHANCEMENT]**: Migration to Java 8. Epic: [#399](https://github.com/appium/java-client/issues/399) - - API with default implementation. PR [#470](https://github.com/appium/java-client/pull/470) - - Tools that provide _Page Object_ engines were redesigned. The migration to [repeatable annotations](http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html). Details you can read there: [#497](https://github.com/appium/java-client/pull/497). [Documentation was synced as well](https://github.com/appium/java-client/blob/master/docs/Page-objects.md#also-it-is-possible-to-define-chained-or-any-possible-locators). - - The new functional interface `io.appium.java_client.functions.AppiumFunctio`n was designed. It extends `java.util.function.Function` and `com.google.common.base.Function`. It was designed in order to provide compatibility with the `org.openqa.selenium.support.ui.Wait` [#543](https://github.com/appium/java-client/pull/543) - - The new functional interface `io.appium.java_client.functions.ExpectedCondition` was designed. It extends `io.appium.java_client.functions.AppiumFunction` and ```org.openqa.selenium.support.ui.ExpectedCondition```. [#543](https://github.com/appium/java-client/pull/543) - - The new functional interface `io.appium.java_client.functions.ActionSupplier` was designed. It extends ```java.util.function.Supplier```. [#543](https://github.com/appium/java-client/pull/543) - -- **[MAJOR ENHANCEMENT]**: Migration from Maven to Gradle. Feature request is [#214](https://github.com/appium/java-client/issues/214). Fixes: [#442](https://github.com/appium/java-client/pull/442), [#465](https://github.com/appium/java-client/pull/465). - -- **[MAJOR ENHANCEMENT]** **[MAJOR REFACTORING]**. Non-abstract **AppiumDriver**: - - Now the `io.appium.java_client.AppiumDriver` can use an instance of any `io.appium.java_client.MobileBy` subclass for the searching. It should work as expected when current session supports the given selector. It will throw `org.openqa.selenium.WebDriverException` otherwise. [#462](https://github.com/appium/java-client/pull/462) - - The new interface `io.appium.java_client.FindsByFluentSelector` was added. [#462](https://github.com/appium/java-client/pull/462) - - API was redesigned: - - these interfaces were marked deprecated and they are going to be removed [#513](https://github.com/appium/java-client/pull/513)[#514](https://github.com/appium/java-client/pull/514): - - `io.appium.java_client.DeviceActionShortcuts` - - `io.appium.java_client.android.AndroidDeviceActionShortcuts` - - `io.appium.java_client.ios.IOSDeviceActionShortcuts` - - instead following inerfaces were designed: - - `io.appium.java_client.HasDeviceTime` - - `io.appium.java_client.HidesKeyboard` - - `io.appium.java_client.HidesKeyboardWithKeyName` - - `io.appium.java_client.PressesKeyCode` - - `io.appium.java_client.ios.ShakesDevice` - - `io.appium.java_client.HasSessionDetails` - _That was done because Windows automation tools have some features that were considered as Android-specific and iOS-specific._ - - The list of classes and methods which were marked _deprecated_ and they are going to be removed - - `AppiumDriver#swipe(int, int, int, int, int)` - - `AppiumDriver#pinch(WebElement)` - - `AppiumDriver#pinch(int, int)` - - `AppiumDriver#zoom(WebElement)` - - `AppiumDriver#zoom(int, int)` - - `AppiumDriver#tap(int, WebElement, int)` - - `AppiumDriver#tap(int, int, int, int)` - - `AppiumDriver#swipe(int, int, int, int, int)` - - `MobileElement#swipe(SwipeElementDirection, int)` - - `MobileElement#swipe(SwipeElementDirection, int, int, int)` - - `MobileElement#zoom()` - - `MobileElement#pinch()` - - `MobileElement#tap(int, int)` - - `io.appium.java_client.SwipeElementDirection` and `io.appium.java_client.TouchebleElement` also were marked deprecated. - - redesign of `TouchAction` and `MultiTouchAction` - - constructors were redesigned. There is no strict binding of `AppiumDriver` and `TouchAction` /`MultiTouchAction`. They can consume any instance of a class that implements `PerformsTouchActions`. - - `io.appium.java_client.ios.IOSTouchAction` was added. It extends `io.appium.java_client.TouchAction`. - - the new interface `io.appium.java_client.PerformsActions` was added. It unifies `TouchAction` and `MultiTouchAction` now. [#543](https://github.com/appium/java-client/pull/543) - - `JsonToMobileElementConverter` re-design [#532](https://github.com/appium/java-client/pull/532): - - unused `MobileElementToJsonConverter` was removed - - `JsonToMobileElementConverter` is not rhe abstract class now. It generates instances of MobileElement subclasses according to current session parameters - - `JsonToAndroidElementConverter` is deprecated now - - `JsonToIOSElementConverter` is depreacated now - - `JsonToYouiEngineElementConverter` is deprecated now. - - constructors of 'AppiumDriver' were re-designed. - - constructors of 'AndroidDriver' were re-designed. - - constructors of 'IOSDriver' were re-designed. - -- **[MAJOR ENHANCEMENT]** Windows automation. Epic [#471](https://github.com/appium/java-client/issues/471) - - The new interface `io.appium.java_client.FindsByWindowsAutomation` was added. [#462](https://github.com/appium/java-client/pull/462). With [@jonstoneman](https://github.com/jonstoneman) 's authorship. - - The new selector strategy `io.appium.java_client.MobileBy.ByWindowsAutomation` was added. [#462](https://github.com/appium/java-client/pull/462). With [@jonstoneman](https://github.com/jonstoneman) 's authorship. - - `io.appium.java_client.windows.WindowsDriver` was designed. [#538](https://github.com/appium/java-client/pull/538) - - `io.appium.java_client.windows.WindowsElement` was designed. [#538](https://github.com/appium/java-client/pull/538) - - `io.appium.java_client.windows.WindowsKeyCode ` was added. [#538](https://github.com/appium/java-client/pull/538) - - Page object tools were updated [#538](https://github.com/appium/java-client/pull/538) - - the `io.appium.java_client.pagefactory.WindowsFindBy` annotation was added. - - `io.appium.java_client.pagefactory.AppiumFieldDecorator` and supporting tools were actualized. - -- **[MAJOR ENHANCEMENT]** iOS XCUIT mode automation: - - `io.appium.java_client.remote.AutomationName#IOS_XCUI_TEST` was added - - The new interface `io.appium.java_client.FindsByIosNSPredicate` was added. [#462](https://github.com/appium/java-client/pull/462). With [@rafael-chavez](https://github.com/rafael-chavez) 's authorship. It is implemented by `io.appium.java_client.ios.IOSDriver` and `io.appium.java_client.ios.IOSElement`. - - The new selector strategy `io.appium.java_client.MobileBy.ByIosNsPredicate` was added. [#462](https://github.com/appium/java-client/pull/462). With [@rafael-chavez](https://github.com/rafael-chavez) 's authorship. - - Page object tools were updated [#545](https://github.com/appium/java-client/pull/545), [#546](https://github.com/appium/java-client/pull/546) - - the `io.appium.java_client.pagefactory.iOSXCUITFindBy` annotation was added. - - `io.appium.java_client.pagefactory.AppiumFieldDecorator` and supporting tools were actualized. - -- [ENHANCEMENT] Added the ability to set UiAutomator Congfigurator values. [#410](https://github.com/appium/java-client/pull/410). -[#477](https://github.com/appium/java-client/pull/477). -- [ENHANCEMENT]. Additional methods which perform device rotation were implemented. [#489](https://github.com/appium/java-client/pull/489). [#439](https://github.com/appium/java-client/pull/439). But it works for iOS in XCUIT mode and for Android in UIAutomator2 mode only. The feature request: [#7131](https://github.com/appium/appium/issues/7131) -- [ENHANCEMENT]. TouchID Implementation (iOS Sim Only). Details: [#509](https://github.com/appium/java-client/pull/509) -- [ENHANCEMENT]. The ability to use port, ip and log file as server arguments was provided. Feature request: [#521](https://github.com/appium/java-client/issues/521). Fixes: [#522](https://github.com/appium/java-client/issues/522), [#524](https://github.com/appium/java-client/issues/524). -- [ENHANCEMENT]. The new interface ```io.appium.java_client.android.HasDeviceDetails``` was added. It is implemented by ```io.appium.java_client.android.AndroidDriver``` by default. [#518](https://github.com/appium/java-client/pull/518) -- [ENHANCEMENT]. New touch actions were added. ```io.appium.java_client.ios.IOSTouchAction#doubleTap(WebElement, int, int)``` and ```io.appium.java_client.ios.IOSTouchAction#doubleTap(WebElement)```. [#523](https://github.com/appium/java-client/pull/523), [#444](https://github.com/appium/java-client/pull/444) -- [ENHANCEMENT]. All constructors declared by `io.appium.java_client.AppiumDriver` are public now. -- [BUG FIX]: There was the issue when "@WithTimeout" was changing general timeout of the waiting for elements. Bug report: [#467](https://github.com/appium/java-client/issues/467). Fixes: [#468](https://github.com/appium/java-client/issues/468), [#469](https://github.com/appium/java-client/issues/469), [#480](https://github.com/appium/java-client/issues/480). Read: [supported-settings](https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/settings.md#supported-settings) -- Added the server flag `io.appium.java_client.service.local.flags.AndroidServerFlag#REBOOT`. [#476](https://github.com/appium/java-client/pull/476) -- Added `io.appium.java_client.remote.AndroidMobileCapabilityType.APP_WAIT_DURATION ` capability. [#461](https://github.com/appium/java-client/pull/461) -- the new automation type `io.appium.java_client.remote.MobilePlatform#ANDROID_UIAUTOMATOR2` was add. -- the new automation type `io.appium.java_client.remote.MobilePlatform#YOUI_ENGINE` was add. -- Additional capabilities were addede: - - `IOSMobileCapabilityType#CUSTOM_SSL_CERT` - - `IOSMobileCapabilityType#TAP_WITH_SHORT_PRESS_DURATION` - - `IOSMobileCapabilityType#SCALE_FACTOR` - - `IOSMobileCapabilityType#WDA_LOCAL_PORT` - - `IOSMobileCapabilityType#SHOW_XCODE_LOG` - - `IOSMobileCapabilityType#REAL_DEVICE_LOGGER` - - `IOSMobileCapabilityType#IOS_INSTALL_PAUSE` - - `IOSMobileCapabilityType#XCODE_CONFIG_FILE` - - `IOSMobileCapabilityType#KEYCHAIN_PASSWORD` - - `IOSMobileCapabilityType#USE_PREBUILT_WDA` - - `IOSMobileCapabilityType#PREVENT_WDAATTACHMENTS` - - `IOSMobileCapabilityType#WEB_DRIVER_AGENT_URL` - - `IOSMobileCapabilityType#KEYCHAIN_PATH` - - `MobileCapabilityType#CLEAR_SYSTEM_FILES` -- **[UPDATE]** to Selenium 3.0.1. -- **[UPDATE]** to Spring Framework 4.3.5.RELEASE. -- **[UPDATE]** to AspectJ weaver 1.8.10. - - - -*4.1.2* - -- Following capabilities were added: - - `io.appium.java_client.remote.AndroidMobileCapabilityType.ANDROID_INSTALL_TIMEOUT` - - `io.appium.java_client.remote.AndroidMobileCapabilityType.NATIVE_WEB_SCREENSHOT` - - `io.appium.java_client.remote.AndroidMobileCapabilityType.ANDROID_SCREENSHOT_PATH`. The pull request: [#452](https://github.com/appium/java-client/pull/452) -- `org.openqa.selenium.Alert` was reimplemented for iOS. Details: [#459](https://github.com/appium/java-client/pull/459) -- The deprecated `io.appium.java_client.generic.searchcontext` was removed. -- The dependency on `com.google.code.gson` was updated to 2.7. Also it was adde to exclusions -for `org.seleniumhq.selenium` `selenium-java`. -- The new AutomationName was added. IOS_XCUI_TEST. It is needed for the further development. -- The new MobilePlatform was added. WINDOWS. It is needed for the further development. - -*4.1.1* - -BUG FIX: Issue [#450](https://github.com/appium/java-client/issues/450). Fix: [#451](https://github.com/appium/java-client/issues/451). Thanks to [@tutunang](https://github.com/appium/java-client/pull/451) for the report. - -*4.1.0* -- all code marked `@Deprecated` was removed. -- `getSessionDetails()` was added. Thanks to [@saikrishna321](https://github.com/saikrishna321) for the contribution. -- FIX [#362](https://github.com/appium/java-client/issues/362), [#220](https://github.com/appium/java-client/issues/220), [#323](https://github.com/appium/java-client/issues/323). Details read there: [#413](https://github.com/appium/java-client/pull/413) -- FIX [#392](https://github.com/appium/java-client/issues/392). Thanks to [@truebit](https://github.com/truebit) for the bug report. -- The dependency on `cglib` was replaced by the dependency on `cglib-nodep`. FIX [#418](https://github.com/appium/java-client/issues/418) -- The casting to the weaker interface `HasIdentity` instead of class `RemoteWebElement` was added. It is the internal refactoring of the `TouchAction`. [#432](https://github.com/appium/java-client/pull/432). Thanks to [@asolntsev](https://github.com/asolntsev) for the contribution. -- The `setValue` method was moved to `MobileElement`. It works against text input elements on Android. -- The dependency on `org.springframework` `spring-context` v`4.3.2.RELEASE` was added -- The dependency on `org.aspectj` `aspectjweaver` v`1.8.9` was added -- ENHANCEMENT: The alternative event firing engine. The feature request: [#242](https://github.com/appium/java-client/issues/242). -Implementation: [#437](https://github.com/appium/java-client/pull/437). Also [new WIKI chapter](https://github.com/appium/java-client/blob/master/docs/The-event_firing.md) was added. -- ENHANCEMENT: Convenient access to specific commands for each supported mobile OS. Details: [#445](https://github.com/appium/java-client/pull/445) -- dependencies and plugins were updated -- ENHANCEMENT: `YouiEngineDriver` was added. Details: [appium server #6215](https://github.com/appium/appium/pull/6215), [#429](https://github.com/appium/java-client/pull/429), [#448](https://github.com/appium/java-client/pull/448). It is just the draft of the new solution that is going to be extended further. Please stay tuned. There are many interesting things are coming up. Thanks to `You I Engine` team for the contribution. - -*4.0.0* -- all code marked `@Deprecated` was removed. Java client won't support old servers (v<1.5.0) -anymore. -- the ability to start an activity using Android intent actions, intent categories, flags and arguments -was added to `AndroidDriver`. Thanks to [@saikrishna321](https://github.com/saikrishna321) for the contribution. -- `scrollTo()` and `scrollToExact()` became deprecated. They are going to be removed in the next release. -- The interface `io.appium.java_client.ios.GetsNamedTextField` and the declared method `T getNamedTextField(String name)` are -deprecated as well. They are going to be removed in the next release. -- Methods `findElements(String by, String using)` and `findElement(String by, String using)` of `org.openga.selenium.remote.RemoteWebdriver` are public now. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget). -- the `io.appium.java_client.NetworkConnectionSetting` class was marked deprecated -- the enum `io.appium.java_client.android.Connection` was added. All supported network bitmasks are defined there. -- Android. Old methods which get/set connection were marked `@Deprecated` -- Android. New methods which consume/return `io.appium.java_client.android.Connection` were added. -- the `commandRepository` field is public now. The modification of the `MobileCommand` -- Constructors like `AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities)` were added to -`io.appium.java_client.android.AndroidDriver` and `io.appium.java_client.ios.IOSDriver` -- The refactoring of `io.appium.java_client.internal.JsonToMobileElementConverter`. Now it accepts -`org.openqa.selenium.remote.RemoteWebDriver` as the constructor parameter. It is possible to re-use -`io.appium.java_client.android.internal.JsonToAndroidElementConverter` or -`io.appium.java_client.ios.internal.JsonToIOSElementConverter` by RemoteWebDriver when it is needed. -- Constructors of the abstract `io.appium.java_client.AppiumDriver` were redesigned. Now they require -a subclass of `io.appium.java_client.internal.JsonToMobileElementConverter`. Constructors of -`io.appium.java_client.android.AndroidDriver` and `io.appium.java_client.ios.IOSDriver` are same still. -- The `pushFile(String remotePath, File file)` was added to AndroidDriver -- FIX of TouchAction. Instances of the TouchAction class are reusable now -- FIX of the swiping issue (iOS, server version >= 1.5.0). Now the swiping is implemented differently by -AndroidDriver and IOSDriver. Thanks to [@truebit](https://github.com/truebit) and [@nuggit32](https://github.com/nuggit32) for the catching. -- the project was integrated with [maven-checkstyle-plugin](https://maven.apache.org/plugins/maven-checkstyle-plugin/). Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the work -- source code was improved according to code style checking rules. -- the integration with `org.owasp dependency-check-maven` was added. Thanks to [@saikrishna321](https://github.com/saikrishna321) -for the work. -- the integration with `org.jacoco jacoco-maven-plugin` was added. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the contribution. - -*3.4.1* -- Update to Selenium v2.53.0 -- all dependencies were updated to latest versions -- the dependency on org.apache.commons commons-lang3 v3.4 was added -- the fix of Widget method invocation.[#340](https://github.com/appium/java-client/issues/340). A class visibility was taken into account. Thanks to [aznime](https://github.com/aznime) for the catching. -Server flags were added: - - GeneralServerFlag.ASYNC_TRACE - - IOSServerFlag.WEBKIT_DEBUG_PROXY_PORT -- Source code was formatted using [eclipse-java-google-style.xml](https://google-styleguide.googlecode.com/svn/trunk/eclipse-java-google-style.xml). This is not the complete solution. The code style checking is going to be added further. Thanks to [SrinivasanTarget](https://github.com/SrinivasanTarget) for the work! - -*3.4.0* -- Update to Selenium v2.52.0 -- `getAppStrings()` methods are deprecated now. They are going to be removed. `getAppStringMap()` methods were added and now return a map with app strings (keys and values) -instead of a string. Thanks to [@rgonalo](https://github.com/rgonalo) for the contribution. -- Add `getAppStringMap(String language, String stringFile)` method to allow searching app strings in the specified file -- FIXED of the bug which causes deadlocks of AppiumDriver LocalService in multithreading. Thanks to [saikrishna321](https://github.com/saikrishna321) for the [bug report](https://github.com/appium/java-client/issues/283). -- FIXED Zoom methods, thanks to [@kkhaidukov](https://github.com/kkhaidukov) -- FIXED The issue of compatibility of AppiumServiceBuilder with Appium node server v >= 1.5.x. Take a look at [#305](https://github.com/appium/java-client/issues/305) -- `getDeviceTime()` was added. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the contribution. -- FIXED `longPressKeyCode()` methods. Now they use the convenient JSONWP command.Thanks to [@kirillbilchenko](https://github.com/kirillbilchenko) for the proposed fix. -- FIXED javadoc. -- Page object tools were updated. Details read here: [#311](https://github.com/appium/java-client/issues/311), [#313](https://github.com/appium/java-client/pull/313), [#317](https://github.com/appium/java-client/pull/317). By.name locator strategy is deprecated for Android and iOS. It is still valid for the Selendroid mode. Thanks to [@SrinivasanTarget](https://github.com/SrinivasanTarget) for the helping. -- The method `lockScreen(seconds)` is deprecated and it is going to be removed in the next release. Since Appium node server v1.5.x it is recommended to use -`AndroidDriver.lockDevice()...AndroidDriver.unlockDevice()` or `IOSDriver.lockDevice(int seconds)` instead. Thanks to [@namannigam](https://github.com/namannigam) for -the catching. Read [#315](https://github.com/appium/java-client/issues/315) -- `maven-release-plugin` was added to POM.XML configuration -- [#320](https://github.com/appium/java-client/issues/320) fix. The `Widget.getSelfReference()` was added. This method allows to extract a real widget-object from inside a proxy at some extraordinary situations. Read: [PR](https://github.com/appium/java-client/pull/327). Thanks to [SergeyErmakovMercDev](https://github.com/SergeyErmakovMercDev) for the reporting. -- all capabilities were added according to [this description](https://github.com/appium/appium/blob/1.5/docs/en/writing-running-appium/caps.md). There are three classes: `io.appium.java_client.remote.MobileCapabilityType` (just modified), `io.appium.java_client.remote.AndroidMobileCapabilityType` (android-specific capabilities), `io.appium.java_client.remote.IOSMobileCapabilityType` (iOS-specific capabilities). Details are here: [#326](https://github.com/appium/java-client/pull/326) -- some server flags were marked `deprecated` because they are deprecated since server node v1.5.x. These flags are going to be removed at the java client release. Details are here: [#326](https://github.com/appium/java-client/pull/326) -- The ability to start Appium node programmatically using desired capabilities. This feature is compatible with Appium node server v >= 1.5.x. Details are here: [#326](https://github.com/appium/java-client/pull/326) - -*3.3.0* -- updated the dependency on Selenium to version 2.48.2 -- bug fix and enhancements of io.appium.java_client.service.local.AppiumDriverLocalService - - FIXED bug which was found and reproduced with Eclipse for Mac OS X. Please read about details here: [#252](https://github.com/appium/java-client/issues/252) - Thanks to [saikrishna321](https://github.com/saikrishna321) for the bug report - - FIXED bug which was found out by [Jonahss](https://github.com/Jonahss). Thanks for the reporting. Details: [#272](https://github.com/appium/java-client/issues/272) - and [#273](https://github.com/appium/java-client/issues/273) - - For starting an appium server using localService, added additional environment variable to specify the location of Node.js binary: NODE_BINARY_PATH - - The ability to set additional output streams was provided -- The additional __startActivity()__ method was added to AndroidDriver. It allows to start activities without the stopping of a target app -Thanks to [deadmoto](https://github.com/deadmoto) for the contribution -- The additional extension of the Page Object design pattern was designed. Please read about details here: [#267](https://github.com/appium/java-client/pull/267) -- New public constructors to AndroidDriver/IOSDriver that allow passing a custom HttpClient.Factory Details: [#276](https://github.com/appium/java-client/pull/278) thanks to [baechul](https://github.com/baechul) - -*3.2.0* -- updated the dependency on Selenium to version 2.47.1 -- the new dependency on commons-validator v1.4.1 -- the ability to start programmatically/silently an Appium node server is provided now. Details please read at [#240](https://github.com/appium/java-client/pull/240). -Historical reference: [The similar solution](https://github.com/Genium-Framework/Appium-Support) has been designed by [@Hassan-Radi](https://github.com/Hassan-Radi). -The mentioned framework and the current solution use different approaches. -- Throwing declarations were added to some searching methods. The __"getMouse"__ method of RemoteWebDriver was marked __Deprecated__ -- Add `replaceValue` method for elements. -- Replace `sendKeyEvent()` method in android with pressKeyCode(int key) and added: pressKeyCode(int key, Integer metastate), longPressKeyCode(int key), longPressKeyCode(int key, Integer metastate) - -*3.1.1* -- Page-object findBy strategies are now aware of which driver (iOS or Android) you are using. For more details see the Pull Request: https://github.com/appium/java-client/pull/213 -- If somebody desires to use their own Webdriver implementation then it has to implement HasCapabilities. -- Added a new annotation: `WithTimeout`. This annotation allows one to specify a specific timeout for finding an element which overrides the drivers default timeout. For more info see: https://github.com/appium/java-client/pull/210 -- Corrected an uninformative Exception message. - -*3.0.0* -- AppiumDriver class is now a Generic. This allows us to return elements of class MobileElement (and its subclasses) instead of always returning WebElements and requiring users to cast to MobileElement. See https://github.com/appium/java-client/pull/182 -- Full set of Android KeyEvents added. -- Selenium client version updated to 2.46 -- PageObject enhancements -- Junit dependency removed - -*2.2.0* -- Added new TouchAction methods for LongPress, on an element, at x,y coordinates, or at an offset from within an element -- SwipeElementDirection changed. Read the documentation, it's now smarter about how/where to swipe -- Added APPIUM_VERSION MobileCapabilityType -- `sendKeyEvent()` moved from AppiumDriver to AndroidDriver -- `linkText` and `partialLinkText` locators added -- setValue() moved from MobileElement to iOSElement -- Fixed Selendroid PageAnnotations - -*2.1.0* -- Moved hasAppString() from AndroidDriver to AppiumDriver -- Fixes to PageFactory -- Added @AndroidFindAll and @iOSFindAll -- Added toggleLocationServices() to AndroidDriver -- Added touchAction methods to MobileElement, so now you can do `element.pinch()`, `element.zoom()`, etc. -- Added the ability to choose a direction to swipe over an element. Use the `SwipeElementDirection` enums: `UP, DOWN, LEFT, RIGHT` - -*2.0.0* -- AppiumDriver is now an abstract class, use IOSDriver and AndroidDriver which both extend it. You no longer need to include the `PLATFORM_NAME` desired capability since it's automatic for each class. Thanks to @TikhomirovSergey for all their work -- ScrollTo() and ScrollToExact() methods reimplemented -- Zoom() and Pinch() are now a little smarter and less likely to fail if you element is near the edge of the screen. Congratulate @BJap on their first PR! - -*1.7.0* -- Removed `scrollTo()` and `scrollToExact()` methods because they relied on `complexFind()`. They will be added back in the next version! -- Removed `complexFind()` -- Added `startActivity()` method -- Added `isLocked()` method -- Added `getSettings()` and `ignoreUnimportantViews()` methods - -*1.6.2* -- Added MobilePlatform interface (Android, IOS, FirefoxOS) -- Added MobileBrowserType interface (Safari, Browser, Chromium, Chrome) -- Added MobileCapabilityType.APP_WAIT_ACTIVITY -- Fixed small Integer cast issue (in Eclipse it won't compile) -- Set -source and -target of the Java Compiler to 1.7 (for maven compiler plugin) -- Fixed bug in Page Factory - -*1.6.1* -- Fixed the logic for checking connection status on NetworkConnectionSetting objects - -*1.6.0* -- Added @findBy annotations. Explanation here: https://github.com/appium/java-client/pull/68 Thanks to TikhomirovSergey -- Appium Driver now implements LocationContext interface, so setLocation() works for setting GPS coordinates - -*1.5.0* -- Added MobileCapabilityType enums for desired capabilities -- `findElement` and `findElements` return MobileElement objects (still need to be casted, but no longer instantiated) -- new appium v1.2 `hideKeyboard()` strategies added -- `getNetworkConnection()` and `setNetworkConnection()` commands added - -*1.4.0* -- Added openNotifications() method, to open the notifications shade on Android -- Added pullFolder() method, to pull an entire folder as a zip archive from a device/simulator -- Upgraded Selenium dependency to 2.42.2 - -*1.3.0* -- MultiGesture with a single TouchAction fixed for Android -- Now depends upon Selenium java client 2.42.1 -- Cleanup of Errorcode handling, due to merging a change into Selenium - -*1.2.1* -- fix dependency issue - -*1.2.0* -- complexFind() now returns MobileElement objects -- added scrollTo() and scrollToExact() methods for use with complexFind() - -*1.1.0* -- AppiumDriver now implements Rotatable. rotate() and getOrientation() methods added -- when no appium server is running, the proper error is thrown, instead of a NullPointerException - -*1.0.2* -- recompiled to include some missing methods such as shake() and complexFind() +Visit [CHANGELOG.md](CHANGELOG.md) to see the full list of changes between versions. ## Running tests From 843941aff92e89080dccd1f704b9201d3a945921 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 2 Dec 2022 10:28:35 +0100 Subject: [PATCH 153/501] chore: Bump Selenium version to 4.7.0 (#1811) --- gradle.properties | 2 +- .../remote/AppiumProtocolHandshake.java | 25 +++++++++++-------- .../java_client/remote/SupportsRotation.java | 3 +-- .../events/stubs/EmptyWebDriver.java | 19 +------------- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/gradle.properties b/gradle.properties index e23c7abf2..633c79fd6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.5.0 +selenium.version=4.7.0 # Please increment the value in a release appiumClient.version=8.2.1 diff --git a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java index 98b128554..0f42b9a51 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java +++ b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java @@ -30,7 +30,6 @@ import org.openqa.selenium.remote.ProtocolHandshake; import org.openqa.selenium.remote.http.HttpHandler; -import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; @@ -39,6 +38,7 @@ import java.lang.reflect.Method; import java.util.Map; import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; @@ -62,7 +62,7 @@ private static void writeJsonPayload(NewSessionPayload srcPayload, Appendable de try { Method getW3CMethod = NewSessionPayload.class.getDeclaredMethod("getW3C"); getW3CMethod.setAccessible(true); - //noinspection unchecked + //noinspection unchecked,resource ((Stream>) getW3CMethod.invoke(srcPayload)) .findFirst() .map(json::write) @@ -111,26 +111,31 @@ public Result createSession(HttpHandler client, Command command) throws IOExcept public Either createSession( HttpHandler client, NewSessionPayload payload) throws IOException { int threshold = (int) Math.min(Runtime.getRuntime().freeMemory() / 10, Integer.MAX_VALUE); - FileBackedOutputStream os = new FileBackedOutputStream(threshold); + FileBackedOutputStream os = new FileBackedOutputStream(threshold, true); try (CountingOutputStream counter = new CountingOutputStream(os); Writer writer = new OutputStreamWriter(counter, UTF_8)) { writeJsonPayload(payload, writer); - try (InputStream rawIn = os.asByteSource().openBufferedStream(); - BufferedInputStream contentStream = new BufferedInputStream(rawIn)) { - Method createSessionMethod = ProtocolHandshake.class.getDeclaredMethod("createSession", - HttpHandler.class, InputStream.class, long.class); + Supplier contentSupplier = () -> { + try { + return os.asByteSource().openBufferedStream(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; + try { + Method createSessionMethod = ProtocolHandshake.class.getDeclaredMethod( + "createSession", HttpHandler.class, Supplier.class, long.class + ); createSessionMethod.setAccessible(true); //noinspection unchecked return (Either) createSessionMethod.invoke( - this, client, contentStream, counter.getCount() + this, client, contentSupplier, counter.getCount() ); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { throw new WebDriverException(e); } - } finally { - os.reset(); } } } diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java index 8ac22a707..6e1af3a58 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsRotation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -19,7 +19,6 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.DeviceRotation; -import org.openqa.selenium.Rotatable; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.DriverCommand; @@ -27,7 +26,7 @@ import java.util.Map; -public interface SupportsRotation extends WebDriver, ExecutesMethod, Rotatable { +public interface SupportsRotation extends WebDriver, ExecutesMethod { /** * Get device rotation. * diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java index 01104b988..9b6af0820 100644 --- a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -22,13 +22,10 @@ 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; import org.openqa.selenium.OutputType; -import org.openqa.selenium.Rotatable; -import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; @@ -43,7 +40,7 @@ import java.util.Map; import java.util.Set; -public class EmptyWebDriver implements WebDriver, ContextAware, Rotatable, +public class EmptyWebDriver implements WebDriver, ContextAware, JavascriptExecutor, HasCapabilities, TakesScreenshot { public EmptyWebDriver() { } @@ -64,20 +61,6 @@ public String getContext() { return ""; } - public void rotate(ScreenOrientation orientation) { - } - - public void rotate(DeviceRotation rotation) { - } - - public ScreenOrientation getOrientation() { - return null; - } - - public DeviceRotation rotation() { - return null; - } - public void get(String url) { } From 7a98b69649a6d205eb8c55accf672265d52844b8 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Fri, 2 Dec 2022 16:21:00 +0530 Subject: [PATCH 154/501] Release 8.3.0 and update release notes --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d8a55cd9..bc957b07f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +*8.3.0* +- **[DOCUMENTATION]** + - Added troubleshooting section. [#1808](https://github.com/appium/java-client/pull/1808) + - Added CHANGELOG.md. [#1810](https://github.com/appium/java-client/pull/1810) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.7.0. + - `org.slf4j:slf4j-api` was updated to 2.0.5. + *8.2.1* - **[ENHANCEMENTS]** - BYACCESSABILITY is deprecated in favor of BYACCESSIBILITY. [#1752](https://github.com/appium/java-client/pull/1752) diff --git a/gradle.properties b/gradle.properties index 633c79fd6..716bc2a39 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.7.0 # Please increment the value in a release -appiumClient.version=8.2.1 +appiumClient.version=8.3.0 From f575ee49e24ce5ef352c962c77376765928bf4a3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 5 Dec 2022 08:06:41 +0100 Subject: [PATCH 155/501] feat: Add a possibility to connect to a running session (#1813) --- .../io/appium/java_client/AppiumDriver.java | 52 ++++++++++++--- .../appium/java_client/AppiumFluentWait.java | 18 +----- .../java_client/android/AndroidDriver.java | 14 +++++ .../appium/java_client/gecko/GeckoDriver.java | 14 +++++ .../internal/ReflectionHelpers.java | 63 +++++++++++++++++++ .../java_client/internal/SessionHelpers.java | 59 +++++++++++++++++ .../io/appium/java_client/ios/IOSDriver.java | 13 ++++ .../io/appium/java_client/mac/Mac2Driver.java | 13 ++++ .../remote/AppiumCommandExecutor.java | 22 ++----- .../java_client/safari/SafariDriver.java | 13 ++++ .../local/AppiumDriverLocalService.java | 20 +++--- .../java_client/windows/WindowsDriver.java | 5 +- .../internal/SessionConnectTest.java | 37 +++++++++++ 13 files changed, 292 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/appium/java_client/internal/ReflectionHelpers.java create mode 100644 src/main/java/io/appium/java_client/internal/SessionHelpers.java create mode 100644 src/test/java/io/appium/java_client/internal/SessionConnectTest.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 0c72f9c86..debd404d3 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -16,9 +16,13 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.internal.ReflectionHelpers; +import io.appium.java_client.internal.SessionHelpers; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; +import io.appium.java_client.remote.AppiumW3CHttpCommandCodec; import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -36,11 +40,11 @@ import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.Response; +import org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec; import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; -import java.lang.reflect.Field; import java.net.URL; import java.util.Arrays; import java.util.Collections; @@ -128,6 +132,42 @@ public AppiumDriver(Capabilities capabilities) { this(AppiumDriverLocalService.buildDefaultService(), capabilities); } + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + * @param platformName The name of the target platform. + * @param automationName The name of the target automation. + */ + public AppiumDriver(URL remoteSessionAddress, String platformName, String automationName) { + super(); + ReflectionHelpers.setPrivateFieldValue( + RemoteWebDriver.class, this, "capabilities", new ImmutableCapabilities( + ImmutableMap.of( + PLATFORM_NAME, platformName, + APPIUM_PREFIX + AUTOMATION_NAME, automationName + ) + ) + ); + SessionHelpers.SessionAddress sessionAddress = SessionHelpers.parseSessionAddress(remoteSessionAddress); + AppiumCommandExecutor executor = new AppiumCommandExecutor( + MobileCommand.commandRepository, sessionAddress.getServerUrl() + ); + executor.setCommandCodec(new AppiumW3CHttpCommandCodec()); + executor.setResponseCodec(new W3CHttpResponseCodec()); + setCommandExecutor(executor); + this.executeMethod = new AppiumExecutionMethod(this); + locationContext = new RemoteLocationContext(executeMethod); + super.setErrorHandler(errorHandler); + this.remoteAddress = executor.getAddressOfRemoteServer(); + + setSessionId(sessionAddress.getId()); + } + /** * Changes platform name if it is not set and returns merged capabilities. * @@ -252,13 +292,9 @@ && isBlank((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { rawCapabilities.remove(CapabilityType.BROWSER_NAME); } MutableCapabilities returnedCapabilities = new BaseOptions<>(rawCapabilities); - try { - Field capsField = RemoteWebDriver.class.getDeclaredField("capabilities"); - capsField.setAccessible(true); - capsField.set(this, returnedCapabilities); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new WebDriverException(e); - } + ReflectionHelpers.setPrivateFieldValue( + RemoteWebDriver.class, this, "capabilities", returnedCapabilities + ); setSessionId(response.getSessionId()); } diff --git a/src/main/java/io/appium/java_client/AppiumFluentWait.java b/src/main/java/io/appium/java_client/AppiumFluentWait.java index d914f6c16..9061600a0 100644 --- a/src/main/java/io/appium/java_client/AppiumFluentWait.java +++ b/src/main/java/io/appium/java_client/AppiumFluentWait.java @@ -17,6 +17,7 @@ package io.appium.java_client; import com.google.common.base.Throwables; +import io.appium.java_client.internal.ReflectionHelpers; import lombok.AccessLevel; import lombok.Getter; import org.openqa.selenium.TimeoutException; @@ -24,7 +25,6 @@ import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.Sleeper; -import java.lang.reflect.Field; import java.time.Clock; import java.time.Duration; import java.time.Instant; @@ -99,23 +99,11 @@ public AppiumFluentWait(T input, Clock clock, Sleeper sleeper) { } private B getPrivateFieldValue(String fieldName, Class fieldType) { - try { - final Field f = getClass().getSuperclass().getDeclaredField(fieldName); - f.setAccessible(true); - return fieldType.cast(f.get(this)); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new WebDriverException(e); - } + return ReflectionHelpers.getPrivateFieldValue(FluentWait.class, this, fieldName, fieldType); } private Object getPrivateFieldValue(String fieldName) { - try { - final Field f = getClass().getSuperclass().getDeclaredField(fieldName); - f.setAccessible(true); - return f.get(this); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new WebDriverException(e); - } + return getPrivateFieldValue(fieldName, Object.class); } protected Clock getClock() { 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 f3b812584..0fc1c5917 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -240,6 +240,20 @@ public AndroidDriver(Capabilities capabilities) { super(ensurePlatformName(capabilities, ANDROID_PLATFORM)); } + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + * @param automationName The name of the target automation. + */ + public AndroidDriver(URL remoteSessionAddress, String automationName) { + super(remoteSessionAddress, ANDROID_PLATFORM, automationName); + } + /** * Get test-coverage data. * diff --git a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java index 6a7a55cab..07cb9e3e7 100644 --- a/src/main/java/io/appium/java_client/gecko/GeckoDriver.java +++ b/src/main/java/io/appium/java_client/gecko/GeckoDriver.java @@ -75,6 +75,20 @@ public GeckoDriver(HttpClient.Factory httpClientFactory, Capabilities capabiliti super(httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); } + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + * @param platformName The name of the target platform. + */ + public GeckoDriver(URL remoteSessionAddress, String platformName) { + super(remoteSessionAddress, platformName, AUTOMATION_NAME); + } + /** * Creates a new instance based on the given ClientConfig and {@code capabilities}. * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. diff --git a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java new file mode 100644 index 000000000..cbaa7c796 --- /dev/null +++ b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java @@ -0,0 +1,63 @@ +/* + * 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.internal; + +import org.openqa.selenium.WebDriverException; + +import java.lang.reflect.Field; + +public class ReflectionHelpers { + + /** + * Sets the given value to a private instance field. + * + * @param cls The target class or a superclass. + * @param target Target instance. + * @param fieldName Target field name. + * @param newValue The value to be set. + * @return The same instance for chaining. + */ + public static T setPrivateFieldValue(Class cls, T target, String fieldName, Object newValue) { + try { + final Field f = cls.getDeclaredField(fieldName); + f.setAccessible(true); + f.set(target, newValue); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new WebDriverException(e); + } + return target; + } + + /** + * Fetches the value of a private instance field. + * + * @param cls The target class or a superclass. + * @param target Target instance. + * @param fieldName Target field name. + * @param fieldType Field type. + * @return The retrieved field value. + */ + public static T getPrivateFieldValue(Class cls, Object target, String fieldName, Class fieldType) { + try { + final Field f = cls.getDeclaredField(fieldName); + f.setAccessible(true); + return fieldType.cast(f.get(target)); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new WebDriverException(e); + } + } +} diff --git a/src/main/java/io/appium/java_client/internal/SessionHelpers.java b/src/main/java/io/appium/java_client/internal/SessionHelpers.java new file mode 100644 index 000000000..b3b9f0eca --- /dev/null +++ b/src/main/java/io/appium/java_client/internal/SessionHelpers.java @@ -0,0 +1,59 @@ +/* + * 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.internal; + +import lombok.Data; +import org.openqa.selenium.InvalidArgumentException; +import org.openqa.selenium.WebDriverException; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SessionHelpers { + private static final Pattern SESSION = Pattern.compile("/session/([^/]+)"); + + @Data public static class SessionAddress { + private final URL serverUrl; + private final String id; + } + + /** + * Parses the address of a running remote session. + * + * @param address The address string containing /session/id suffix. + * @return Parsed address object. + * @throws InvalidArgumentException If no session identifier could be parsed. + */ + public static SessionAddress parseSessionAddress(URL address) { + String addressString = address.toString(); + Matcher matcher = SESSION.matcher(addressString); + if (!matcher.find()) { + throw new InvalidArgumentException( + String.format("The server URL '%s' must include /session/ suffix", addressString) + ); + } + try { + return new SessionAddress( + new URL(addressString.replace(matcher.group(), "")), matcher.group(1) + ); + } catch (MalformedURLException e) { + throw new WebDriverException(e); + } + } +} 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 d450c1b0f..ad00a5f90 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -31,6 +31,7 @@ import io.appium.java_client.PushesFiles; import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.battery.HasBattery; +import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.SupportsContextSwitching; import io.appium.java_client.remote.SupportsLocation; import io.appium.java_client.remote.SupportsRotation; @@ -220,6 +221,18 @@ public IOSDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilitie super(appiumClientConfig, ensurePlatformName(capabilities, PLATFORM_NAME)); } + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + */ + public IOSDriver(URL remoteSessionAddress) { + super(remoteSessionAddress, PLATFORM_NAME, AutomationName.IOS_XCUI_TEST); + } /** * Creates a new instance based on {@code capabilities}. diff --git a/src/main/java/io/appium/java_client/mac/Mac2Driver.java b/src/main/java/io/appium/java_client/mac/Mac2Driver.java index 905cbec77..46911c314 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2Driver.java +++ b/src/main/java/io/appium/java_client/mac/Mac2Driver.java @@ -86,6 +86,19 @@ public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities capabilitie capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + */ + public Mac2Driver(URL remoteSessionAddress) { + super(remoteSessionAddress, PLATFORM_NAME, AUTOMATION_NAME); + } + /** * Creates a new instance based on the given ClientConfig and {@code capabilities}. * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index b3acea991..0085f457d 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -21,6 +21,7 @@ import com.google.common.net.HttpHeaders; import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumUserAgentFilter; +import io.appium.java_client.internal.ReflectionHelpers; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Command; @@ -42,7 +43,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; -import java.lang.reflect.Field; import java.net.ConnectException; import java.net.MalformedURLException; import java.net.URL; @@ -128,25 +128,13 @@ public AppiumCommandExecutor(Map additionalCommands, @SuppressWarnings("SameParameterValue") protected B getPrivateFieldValue( Class cls, String fieldName, Class fieldType) { - try { - final Field f = cls.getDeclaredField(fieldName); - f.setAccessible(true); - return fieldType.cast(f.get(this)); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new WebDriverException(e); - } + return ReflectionHelpers.getPrivateFieldValue(cls, this, fieldName, fieldType); } @SuppressWarnings("SameParameterValue") protected void setPrivateFieldValue( Class cls, String fieldName, Object newValue) { - try { - final Field f = cls.getDeclaredField(fieldName); - f.setAccessible(true); - f.set(this, newValue); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new WebDriverException(e); - } + ReflectionHelpers.setPrivateFieldValue(cls, this, fieldName, newValue); } protected Map getAdditionalCommands() { @@ -159,11 +147,11 @@ protected CommandCodec getCommandCodec() { return getPrivateFieldValue(HttpCommandExecutor.class, "commandCodec", CommandCodec.class); } - protected void setCommandCodec(CommandCodec newCodec) { + public void setCommandCodec(CommandCodec newCodec) { setPrivateFieldValue(HttpCommandExecutor.class, "commandCodec", newCodec); } - protected void setResponseCodec(ResponseCodec codec) { + public void setResponseCodec(ResponseCodec codec) { setPrivateFieldValue(HttpCommandExecutor.class, "responseCodec", codec); } diff --git a/src/main/java/io/appium/java_client/safari/SafariDriver.java b/src/main/java/io/appium/java_client/safari/SafariDriver.java index 97d1f96e4..f8f10bb01 100644 --- a/src/main/java/io/appium/java_client/safari/SafariDriver.java +++ b/src/main/java/io/appium/java_client/safari/SafariDriver.java @@ -83,6 +83,19 @@ public SafariDriver(HttpClient.Factory httpClientFactory, Capabilities capabilit capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + */ + public SafariDriver(URL remoteSessionAddress) { + super(remoteSessionAddress, PLATFORM_NAME, AUTOMATION_NAME); + } + /** * Creates a new instance based on the given ClientConfig and {@code capabilities}. * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 62d2a98ce..b58191ec2 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -17,6 +17,7 @@ package io.appium.java_client.service.local; import com.google.common.annotations.VisibleForTesting; +import io.appium.java_client.internal.ReflectionHelpers; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.net.UrlChecker; @@ -31,7 +32,6 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; -import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; @@ -226,15 +226,15 @@ private int destroyProcess(Duration timeout) { // it does not exit after two seconds, which is in most cases not enough for // Appium try { - Field processField = process.getClass().getDeclaredField("process"); - processField.setAccessible(true); - Object osProcess = processField.get(process); - Field watchdogField = osProcess.getClass().getDeclaredField("executeWatchdog"); - watchdogField.setAccessible(true); - Object watchdog = watchdogField.get(osProcess); - Field nativeProcessField = watchdog.getClass().getDeclaredField("process"); - nativeProcessField.setAccessible(true); - Process nativeProcess = (Process) nativeProcessField.get(watchdog); + Object osProcess = ReflectionHelpers.getPrivateFieldValue( + process.getClass(), process, "process", Object.class + ); + Object watchdog = ReflectionHelpers.getPrivateFieldValue( + osProcess.getClass(), osProcess, "executeWatchdog", Object.class + ); + Process nativeProcess = ReflectionHelpers.getPrivateFieldValue( + watchdog.getClass(), watchdog, "process", Process.class + ); nativeProcess.destroy(); nativeProcess.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS); } catch (Exception e) { diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 9a441d68a..7c6e68a7a 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -46,7 +46,6 @@ public WindowsDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } - public WindowsDriver(URL remoteAddress, Capabilities capabilities) { super(remoteAddress, ensurePlatformAndAutomationNames( capabilities, PLATFORM_NAME, AUTOMATION_NAME)); @@ -82,6 +81,10 @@ public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities capabili capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + public WindowsDriver(URL remoteSessionAddress) { + super(remoteSessionAddress, PLATFORM_NAME, AUTOMATION_NAME); + } + /** * Creates a new instance based on the given ClientConfig and {@code capabilities}. * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. diff --git a/src/test/java/io/appium/java_client/internal/SessionConnectTest.java b/src/test/java/io/appium/java_client/internal/SessionConnectTest.java new file mode 100644 index 000000000..52b4b051a --- /dev/null +++ b/src/test/java/io/appium/java_client/internal/SessionConnectTest.java @@ -0,0 +1,37 @@ +/* + * 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.internal; + +import io.appium.java_client.ios.IOSDriver; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.WebDriverException; + +import java.net.MalformedURLException; +import java.net.URL; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class SessionConnectTest { + + @Test + void canConnectToASession() throws MalformedURLException { + IOSDriver driver = new IOSDriver(new URL("http://localhost:4723/session/1234")); + assertEquals(driver.getSessionId().toString(), "1234"); + assertThrows(WebDriverException.class, driver::quit); + } + +} From 2f4b2c2e168998e4b8f82bab1957b6f70baabcd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Dec 2022 16:44:44 +0300 Subject: [PATCH 156/501] build(deps): bump org.owasp.dependencycheck from 7.3.2 to 7.4.0 (#1814) Bumps org.owasp.dependencycheck from 7.3.2 to 7.4.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3b89ad341..42275f208 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.3.2' + id 'org.owasp.dependencycheck' version '7.4.0' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 318aa4025b2da700bb3c640200bf81be45428577 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 9 Dec 2022 13:47:56 +0100 Subject: [PATCH 157/501] fix: Use ipv4 address instead of localhost (#1815) --- .../io/appium/java_client/android/ListensToLogcatMessages.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java index 44cae6765..8f9cf1b38 100644 --- a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java +++ b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java @@ -38,7 +38,7 @@ public interface ListensToLogcatMessages extends ExecutesMethod { * is assigned to the default port (4723). */ default void startLogcatBroadcast() { - startLogcatBroadcast("localhost", DEFAULT_APPIUM_PORT); + startLogcatBroadcast("127.0.0.1", DEFAULT_APPIUM_PORT); } /** From a6a08b191be42eada88a97052d34061b358d5088 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 07:54:54 +0200 Subject: [PATCH 158/501] build(deps): bump slf4j-api from 2.0.5 to 2.0.6 (#1824) Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 2.0.5 to 2.0.6. - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/compare/v_2.0.5...v_2.0.6) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 42275f208..701ccbbf7 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:2.0.5' + implementation 'org.slf4j:slf4j-api:2.0.6' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' From 20e64ae3dbd78abe4ed4e5baf8bbb7627d5d7274 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Dec 2022 17:41:13 +0300 Subject: [PATCH 159/501] build(deps): bump org.owasp.dependencycheck from 7.4.0 to 7.4.1 (#1817) Bumps org.owasp.dependencycheck from 7.4.0 to 7.4.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 701ccbbf7..aec7f9f34 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.4.0' + id 'org.owasp.dependencycheck' version '7.4.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 99804d0f9270b4a4617d35a035cee10648078dac Mon Sep 17 00:00:00 2001 From: rerorero Date: Fri, 30 Dec 2022 01:02:24 +0900 Subject: [PATCH 160/501] chore: deprecate tapWithShortPressDuration cap (#1825) --- .../io/appium/java_client/remote/IOSMobileCapabilityType.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java index 410e551a9..b23150244 100644 --- a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java @@ -170,7 +170,10 @@ public interface IOSMobileCapabilityType extends CapabilityType { /** * The desired capability to specify a length for tapping, if the regular * tap is too long for the app under test. The XCUITest specific capability. + * + * @deprecated This capability is not being used. */ + @Deprecated String TAP_WITH_SHORT_PRESS_DURATION = "tapWithShortPressDuration"; /** From 25c178a893517013b750ac010c0b07b25a16d5f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 21:16:19 +0300 Subject: [PATCH 161/501] build(deps): bump org.owasp.dependencycheck from 7.4.1 to 7.4.3 (#1826) Bumps org.owasp.dependencycheck from 7.4.1 to 7.4.3. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index aec7f9f34..e167b6e64 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.4.1' + id 'org.owasp.dependencycheck' version '7.4.3' id 'com.github.johnrengelman.shadow' version '7.1.2' } From a90d718c2241fc4916efd8f2a09d4ed0d1e1f3b7 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 5 Jan 2023 17:11:18 +0300 Subject: [PATCH 162/501] ci: Run Gradle wrapper validation only on Gradle files changes (#1828) --- .github/workflows/gradle-wrapper-validation.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index ba0201318..a0d1170f2 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -4,9 +4,19 @@ on: push: branches: - master + paths: + - 'gradlew' + - 'gradlew.bat' + - 'gradle/wrapper/**' + - '.github/workflows/gradle-wrapper-validation.yml' pull_request: branches: - master + paths: + - 'gradlew' + - 'gradlew.bat' + - 'gradle/wrapper/**' + - '.github/workflows/gradle-wrapper-validation.yml' jobs: validation: From 05b203e79744adbb7165b4792605e4351278191e Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 5 Jan 2023 18:27:53 +0300 Subject: [PATCH 163/501] build: Upgrade to Gradle 7.6 (#1830) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 61574 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 12 ++++++++---- gradlew.bat | 1 + 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index e167b6e64..95ae332fa 100644 --- a/build.gradle +++ b/build.gradle @@ -184,7 +184,7 @@ signing { } wrapper { - gradleVersion = '7.5.1' + gradleVersion = '7.6' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..943f0cbfa754578e88a3dae77fce6e3dea56edbf 100644 GIT binary patch delta 36524 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%0DGK?7GHTj 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 VwlMN}`%er%aGR6olj~j${vQ;P=LY}) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5a9..2b22d057a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb6c..65dcd68d6 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/gradlew.bat b/gradlew.bat index 53a6b238d..6689b85be 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% From 46931ddd9f2da89ba268131c636604241aa883c5 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 5 Jan 2023 18:40:18 +0300 Subject: [PATCH 164/501] ci: Skip GH Actions build on changes in docs (#1829) --- .github/workflows/gradle.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index caf838f59..397bf1661 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -4,9 +4,15 @@ on: push: branches: - master + paths-ignore: + - 'docs/**' + - '*.md' pull_request: branches: - master + paths-ignore: + - 'docs/**' + - '*.md' jobs: build: From 26f045a05d96d473e0153509c9939da0271fe4a1 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 5 Jan 2023 19:17:35 +0300 Subject: [PATCH 165/501] docs: Describe transitive Selenium dependencies management (#1827) --- README.md | 7 +++ docs/transitive-dependencies-management.md | 68 ++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 docs/transitive-dependencies-management.md diff --git a/README.md b/README.md index 596d6e564..507aa8899 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,13 @@ dependencies { } ``` +### How to pin Selenium dependencies? + +Appium Java Client declares Selenium dependencies using open version range which is handled in differently by different +build tools. Sometimes users may want to pin used Selenium dependencies for [various reasons](https://github.com/appium/java-client/issues/1823). +Follow the [Transitive Dependencies Management article](docs/transitive-dependencies-management.md) for more information +about establishing a fixed Selenium version for your Java test framework. + ## Drivers Support Appium java client has dedicated classes to support the following Appium drivers: diff --git a/docs/transitive-dependencies-management.md b/docs/transitive-dependencies-management.md new file mode 100644 index 000000000..dc148d816 --- /dev/null +++ b/docs/transitive-dependencies-management.md @@ -0,0 +1,68 @@ +# Maven + +Maven downloads dependency of [the latest version](https://cwiki.apache.org/confluence/display/MAVENOLD/Dependency+Mediation+and+Conflict+Resolution#DependencyMediationandConflictResolution-DependencyVersionRanges) +matching the declared range by default, in other words whenever new versions of Selenium 4 libraries are published +they are pulled transitively as Appium Java Client dependencies at the first project (re)build automatically. + +In order to pin Selenium dependencies they should be declared in `pom.xml` in the following way: + +```xml + + + io.appium + java-client + X.Y.Z + + + org.seleniumhq.selenium + selenium-api + + + org.seleniumhq.selenium + selenium-remote-driver + + + org.seleniumhq.selenium + selenium-support + + + + + org.seleniumhq.selenium + selenium-api + A.B.C + + + org.seleniumhq.selenium + selenium-remote-driver + A.B.C + + + org.seleniumhq.selenium + selenium-support + A.B.C + + +``` + +# Gradle + +Gradle uses [Module Metadata](https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html) +to perform improved dependency resolution whenever it is available. Gradle Module Metadata for Appium Java Client is +published automatically with every release and is available on Maven Central. + +Appium Java Client declares [preferred](https://docs.gradle.org/current/userguide/rich_versions.html#rich-version-constraints) +Selenium dependencies version which is equal to the lowest boundary in the version range, i.e. the lowest compatible +Selenium dependencies are pulled by Gradle by default. It's strictly recommended to do not use versions lower than the +range boundary, because unresolvable compilation and runtime errors may occur. + +In order to use newer Selenium dependencies they should be explicitly added to Gradle build script (`build.gradle`): + +```gradle +dependencies { + implementation('io.appium:java-client:X.Y.Z') + implementation('org.seleniumhq.selenium:selenium-api:A.B.C') + implementation('org.seleniumhq.selenium:selenium-remote-driver:A.B.C') + implementation('org.seleniumhq.selenium:selenium-support:A.B.C') +} +``` From 1d8a01e8298229eb8cd57d9062c03f9c833eb081 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 6 Jan 2023 08:56:42 +0300 Subject: [PATCH 166/501] build: Remove Checkstyle exclusion of removed Selenium package (#1831) --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 95ae332fa..aab5eeaec 100644 --- a/build.gradle +++ b/build.gradle @@ -100,7 +100,6 @@ checkstyle { showViolations = true ignoreFailures = false } -checkstyleMain.excludes = ['**/org/openqa/selenium/**'] javadoc { options.addStringOption('encoding', 'UTF-8') From 6bdbe08ea1d71c8cf4b54bd90c09c052ddaf586c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 15:04:19 +0300 Subject: [PATCH 167/501] build(deps): bump gson from 2.10 to 2.10.1 (#1832) Bumps [gson](https://github.com/google/gson) from 2.10 to 2.10.1. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.10...gson-parent-2.10.1) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index aab5eeaec..8c4a4e0ab 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ dependencies { prefer "${seleniumVersion}" } } - implementation 'com.google.code.gson:gson:2.10' + implementation 'com.google.code.gson:gson:2.10.1' implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' From 78336d19027a0980c386877b854debcbd8d699ae Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 23 Jan 2023 23:55:35 +0200 Subject: [PATCH 168/501] test: Fix test broken by updates in `appium-xcuitest-driver` (#1839) Changes affecting the behavior of the test: - https://github.com/appium/appium-xcuitest-driver/pull/1487 - https://github.com/appium/appium/pull/18037 --- src/test/java/io/appium/java_client/ios/IOSDriverTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index ba62dcf34..43d296d55 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -73,7 +73,7 @@ public void addCustomCommandWithElementIdTest() { String.format("/session/%s/appium/element/%s/value", driver.getSessionId(), ((RemoteWebElement) intA).getId()), "setNewValue"); final Response setNewValue = driver.execute("setNewValue", - ImmutableMap.of("id", ((RemoteWebElement) intA).getId(), "value", "8")); + ImmutableMap.of("id", ((RemoteWebElement) intA).getId(), "text", "8")); assertNotNull(setNewValue.getSessionId()); } From 66e9b605e0019d328d61e346c9665e5f05e88717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 01:22:18 +0300 Subject: [PATCH 169/501] build(deps): bump webdrivermanager from 5.3.1 to 5.3.2 (#1837) Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.3.1 to 5.3.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.3.1...webdrivermanager-5.3.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8c4a4e0ab..1069c134e 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.2') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From a51433694d90bb733065504789ed2b0f69885303 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 10:16:51 +0530 Subject: [PATCH 170/501] build(deps): bump junit-jupiter from 5.9.1 to 5.9.2 (#1834) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1069c134e..5f57abe5b 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.slf4j:slf4j-api:2.0.6' - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.2') { exclude group: 'org.seleniumhq.selenium' From 37ac6e4167878c16002e59c5d9aa6b490431690a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 08:01:06 +0200 Subject: [PATCH 171/501] build(deps): bump org.owasp.dependencycheck from 7.4.3 to 8.0.1 (#1838) Bumps org.owasp.dependencycheck from 7.4.3 to 8.0.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5f57abe5b..ec2d1801f 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'checkstyle' id 'signing' - id 'org.owasp.dependencycheck' version '7.4.3' + id 'org.owasp.dependencycheck' version '8.0.1' id 'com.github.johnrengelman.shadow' version '7.1.2' } From 8e3b2e4eb37fbbd59d073d4884c157b77cee4e99 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 24 Jan 2023 22:49:35 +0200 Subject: [PATCH 172/501] build: Migrate to Checkstyle 10 (#1842) --- .github/workflows/gradle.yml | 2 +- appium-style.xml | 3 +- azure-pipelines.yml | 6 +- build.gradle | 17 +++-- jitpack.yml | 2 +- .../java/io/appium/java_client/MobileBy.java | 44 +++++++------ .../io/appium/java_client/MobileCommand.java | 62 +++++++------------ .../android/AndroidMobileCommandHelper.java | 18 +++--- .../internal/CapabilityHelpers.java | 2 +- .../pagefactory/HowToUseLocators.java | 6 +- .../pagefactory/bys/builder/ByAll.java | 2 - 11 files changed, 75 insertions(+), 89 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 397bf1661..dfde4399d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -33,4 +33,4 @@ jobs: java-version: ${{ matrix.java }} cache: 'gradle' - name: Build with Gradle - run: ./gradlew clean build -x unitTest -x checkstyleTest + run: ./gradlew clean build -x unitTest diff --git a/appium-style.xml b/appium-style.xml index 03937a66d..24b63f8c6 100755 --- a/appium-style.xml +++ b/appium-style.xml @@ -175,10 +175,9 @@ - - + diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f158f224d..558a97c23 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,7 +43,7 @@ jobs: jdkArchitectureOption: 'x64' publishJUnitResults: true tasks: 'build' - options: 'uiAutomationTest -x checkstyleTest -x test' + options: 'uiAutomationTest -x test' - job: iOS_E2E_Tests # timeoutInMinutes: '90' steps: @@ -63,7 +63,7 @@ jobs: jdkArchitectureOption: 'x64' publishJUnitResults: true tasks: 'build' - options: 'xcuiTest -x checkstyleTest -x test' + options: 'xcuiTest -x test' - job: Misc_Tests steps: - task: Gradle@2 @@ -75,4 +75,4 @@ jobs: jdkArchitectureOption: 'x64' publishJUnitResults: true tasks: 'build' - options: 'miscTest -x checkstyleTest -x test -x signMavenJavaPublication' + options: 'miscTest -x test -x signMavenJavaPublication' diff --git a/build.gradle b/build.gradle index ec2d1801f..837836f17 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ plugins { id 'eclipse' id 'maven-publish' id 'jacoco' - id 'checkstyle' id 'signing' id 'org.owasp.dependencycheck' version '8.0.1' id 'com.github.johnrengelman.shadow' version '7.1.2' @@ -94,11 +93,17 @@ tasks.withType(JacocoReport) { } jacocoTestReport.dependsOn test -checkstyle { - toolVersion = '8.32' - configFile = file("$projectDir/appium-style.xml") - showViolations = true - ignoreFailures = false +// Checkstyle requires Java 11 starting from 10.0 +if (JavaVersion.current().isJava11Compatible()) { + apply plugin: 'checkstyle' + + checkstyle { + toolVersion = '10.6.0' + configFile = file("$projectDir/appium-style.xml") + showViolations = true + ignoreFailures = false + } + checkstyleTest.enabled = false } javadoc { diff --git a/jitpack.yml b/jitpack.yml index c4432703f..e594bc18b 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,4 @@ jdk: - openjdk8 install: - - ./gradlew clean build publishToMavenLocal -x signMavenJavaPublication -x test -x checkstyleTest + - ./gradlew clean build publishToMavenLocal -x signMavenJavaPublication -x test diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java index 7d30bd855..902baa249 100644 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ b/src/main/java/io/appium/java_client/MobileBy.java @@ -35,9 +35,10 @@ protected MobileBy(String selector, String locatorString, String locatorName) { /** * Refer to https://developer.android.com/training/testing/ui-automator - * @deprecated Use {@link AppiumBy#androidUIAutomator(String)} instead. + * * @param uiautomatorText is Android UIAutomator string * @return an instance of {@link ByAndroidUIAutomator} + * @deprecated Use {@link AppiumBy#androidUIAutomator(String)} instead. */ @Deprecated public static By AndroidUIAutomator(final String uiautomatorText) { @@ -50,9 +51,10 @@ public static By AndroidUIAutomator(final String uiautomatorText) { * About iOS accessibility * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ * UIAccessibilityIdentification_Protocol/index.html - * @deprecated Use {@link AppiumBy#accessibilityId(String)} instead. + * * @param accessibilityId id is a convenient UI automation accessibility Id. * @return an instance of {@link ByAndroidUIAutomator} + * @deprecated Use {@link AppiumBy#accessibilityId(String)} instead. */ @Deprecated public static By AccessibilityId(final String accessibilityId) { @@ -61,11 +63,12 @@ public static By AccessibilityId(final String accessibilityId) { /** * This locator strategy is available in XCUITest Driver mode. - * @deprecated Use {@link AppiumBy#iOSClassChain(String)} instead. + * * @param iOSClassChainString is a valid class chain locator string. * See * the documentation for more details * @return an instance of {@link ByIosClassChain} + * @deprecated Use {@link AppiumBy#iOSClassChain(String)} instead. */ @Deprecated public static By iOSClassChain(final String iOSClassChainString) { @@ -74,11 +77,12 @@ public static By iOSClassChain(final String iOSClassChainString) { /** * This locator strategy is only available in Espresso Driver mode. - * @deprecated Use {@link AppiumBy#androidDataMatcher(String)} instead. + * * @param dataMatcherString is a valid json string detailing hamcrest matcher for Espresso onData(). - * See - * the documentation for more details + * See + * the documentation for more details * @return an instance of {@link ByAndroidDataMatcher} + * @deprecated Use {@link AppiumBy#androidDataMatcher(String)} instead. */ @Deprecated public static By androidDataMatcher(final String dataMatcherString) { @@ -87,11 +91,12 @@ public static By androidDataMatcher(final String dataMatcherString) { /** * This locator strategy is only available in Espresso Driver mode. - * @deprecated Use {@link AppiumBy#androidViewMatcher(String)} instead. + * * @param viewMatcherString is a valid json string detailing hamcrest matcher for Espresso onView(). - * See - * the documentation for more details + * See + * the documentation for more details * @return an instance of {@link ByAndroidViewMatcher} + * @deprecated Use {@link AppiumBy#androidViewMatcher(String)} instead. */ @Deprecated public static By androidViewMatcher(final String viewMatcherString) { @@ -100,9 +105,10 @@ public static By androidViewMatcher(final String viewMatcherString) { /** * This locator strategy is available in XCUITest Driver mode. - * @deprecated Use {@link AppiumBy#iOSNsPredicateString(String)} instead. + * * @param iOSNsPredicateString is an iOS NsPredicate String * @return an instance of {@link ByIosNsPredicate} + * @deprecated Use {@link AppiumBy#iOSNsPredicateString(String)} instead. */ @Deprecated public static By iOSNsPredicateString(final String iOSNsPredicateString) { @@ -111,9 +117,10 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) { /** * The Windows UIAutomation selector. - * @deprecated Not supported on the server side. + * * @param windowsAutomation The element name in the Windows UIAutomation selector * @return an instance of {@link MobileBy.ByWindowsAutomation} + * @deprecated Not supported on the server side. */ @Deprecated public static By windowsAutomation(final String windowsAutomation) { @@ -122,10 +129,11 @@ public static By windowsAutomation(final String windowsAutomation) { /** * This locator strategy is available in Espresso Driver mode. - * @deprecated Use {@link AppiumBy#androidViewTag(String)} instead. - * @since Appium 1.8.2 beta + * * @param tag is an view tag string * @return an instance of {@link ByAndroidViewTag} + * @since Appium 1.8.2 beta + * @deprecated Use {@link AppiumBy#androidViewTag(String)} instead. */ @Deprecated public static By AndroidViewTag(final String tag) { @@ -136,15 +144,15 @@ public static By AndroidViewTag(final String tag) { * This locator strategy is available only if OpenCV libraries and * NodeJS bindings are installed on the server machine. * - * @deprecated Use {@link AppiumBy#image(String)} instead. + * @param b64Template base64-encoded template image string. Supported image formats are the same + * as for OpenCV library. + * @return an instance of {@link ByImage} * @see * The documentation on Image Comparison Features * @see * The settings available for lookup fine-tuning * @since Appium 1.8.2 - * @param b64Template base64-encoded template image string. Supported image formats are the same - * as for OpenCV library. - * @return an instance of {@link ByImage} + * @deprecated Use {@link AppiumBy#image(String)} instead. */ @Deprecated public static By image(final String b64Template) { @@ -155,10 +163,10 @@ public static By image(final String b64Template) { * This type of locator requires the use of the 'customFindModules' capability and a * separately-installed element finding plugin. * - * @deprecated Use {@link AppiumBy#custom(String)} instead. * @param selector selector to pass to the custom element finding plugin * @return an instance of {@link ByCustom} * @since Appium 1.9.2 + * @deprecated Use {@link AppiumBy#custom(String)} instead. */ @Deprecated public static By custom(final String selector) { diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index b87e76949..f5e9c7fb1 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -317,13 +317,11 @@ public static AppiumCommandInfo deleteC(String url) { } /** - * This method forms a {@link java.util.Map} of parameters for the - * keyboard hiding. + * This method forms a {@link Map} of parameters for the keyboard hiding. * * @param keyName The button pressed by the mobile driver to attempt hiding the * keyboard. - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> hideKeyboardCommand(String keyName) { return new AbstractMap.SimpleEntry<>( @@ -331,14 +329,12 @@ public static AppiumCommandInfo deleteC(String url) { } /** - * This method forms a {@link java.util.Map} of parameters for the - * keyboard hiding. + * This method forms a {@link Map} of parameters for the keyboard hiding. * * @param strategy HideKeyboardStrategy. * @param keyName a String, representing the text displayed on the button of the * keyboard you want to press. For example: "Done". - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> hideKeyboardCommand(String strategy, String keyName) { @@ -381,12 +377,10 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * key event invocation. + * This method forms a {@link Map} of parameters for the key event invocation. * * @param key code for the key pressed on the device. - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> pressKeyCodeCommand(int key) { return new AbstractMap.SimpleEntry<>( @@ -394,13 +388,11 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * key event invocation. + * This method forms a {@link Map} of parameters for the key event invocation. * * @param key code for the key pressed on the Android device. * @param metastate metastate for the keypress. - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> pressKeyCodeCommand(int key, Integer metastate) { @@ -411,12 +403,10 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * long key event invocation. + * This method forms a {@link Map} of parameters for the long key event invocation. * * @param key code for the long key pressed on the device. - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> longPressKeyCodeCommand(int key) { return new AbstractMap.SimpleEntry<>( @@ -424,13 +414,11 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * long key event invocation. + * This method forms a {@link Map} of parameters for the long key event invocation. * * @param key code for the long key pressed on the Android device. * @param metastate metastate for the long key press. - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> longPressKeyCodeCommand(int key, Integer metastate) { @@ -441,12 +429,10 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * device locking. + * This method forms a {@link Map} of parameters for the device locking. * * @param duration for how long to lock the screen for. Minimum time resolution is one second - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> lockDeviceCommand(Duration duration) { return new AbstractMap.SimpleEntry<>( @@ -454,22 +440,18 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * device unlocking. + * This method forms a {@link Map} of parameters for the device unlocking. * - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> unlockDeviceCommand() { return new AbstractMap.SimpleEntry<>(UNLOCK, ImmutableMap.of()); } /** - * This method forms a {@link java.util.Map} of parameters for the - * device locked query. + * This method forms a {@link Map} of parameters for the device locked query. * - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> getIsDeviceLockedCommand() { return new AbstractMap.SimpleEntry<>(IS_LOCKED, ImmutableMap.of()); @@ -488,13 +470,11 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * This method forms a {@link java.util.Map} of parameters for the - * file pushing. + * This method forms a {@link Map} of parameters for the file pushing. * * @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 - * @return a key-value pair. The key is the command name. The value is a - * {@link java.util.Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> pushFileCommand(String remotePath, byte[] base64Data) { String[] parameters = new String[]{"path", "data"}; @@ -513,7 +493,7 @@ public static ImmutableMap prepareArguments(String[] params, } /** - * Forms a {@link java.util.Map} of parameters for images comparison. + * Forms a {@link Map} of parameters for images comparison. * * @param mode one of possible comparison modes * @param img1Data base64-encoded data of the first image 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 c5fa63080..6b46ce945 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -113,11 +113,9 @@ public class AndroidMobileCommandHelper extends MobileCommand { } /** - * This method forms a {@link Map} of parameters to - * Retrieve the display density of the Android device. + * This method forms a {@link Map} of parameters to retrieve the display density of the Android device. * - * @return a key-value pair. The key is the command name. The value is a - * {@link Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> getDisplayDensityCommand() { return new AbstractMap.SimpleEntry<>(GET_DISPLAY_DENSITY, ImmutableMap.of()); @@ -126,16 +124,15 @@ public class AndroidMobileCommandHelper extends MobileCommand { /** * This method forms a {@link Map} of parameters for the getting of a network connection value. * - * @return a key-value pair. The key is the command name. The value is a - * {@link Map} command arguments. + * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ public static Map.Entry> getNetworkConnectionCommand() { return new AbstractMap.SimpleEntry<>(GET_NETWORK_CONNECTION, ImmutableMap.of()); } /** - * This method forms a {@link Map} of parameters to - * Retrieve visibility and bounds information of the status and navigation bars. + * This method forms a {@link Map} of parameters to retrieve visibility and bounds information of the status and + * navigation bars. * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ @@ -144,8 +141,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { } /** - * This method forms a {@link java.util.Map} of parameters for the - * finger print authentication invocation. + * This method forms a {@link Map} of parameters for the finger print authentication invocation. * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ @@ -243,7 +239,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { } /** - * This method forms a {@link java.util.Map} of parameters for the element. + * This method forms a {@link Map} of parameters for the element. * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ diff --git a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java index 995385b4b..3645a7520 100644 --- a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java +++ b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java @@ -159,8 +159,8 @@ public static Duration toDuration(Object value, * Converts generic capability value to a url. * * @param value The capability value. - * @throws IllegalArgumentException If the given value cannot be parsed to a valid url. * @return null is the passed value is null otherwise the converted value. + * @throws IllegalArgumentException If the given value cannot be parsed to a valid url. */ @Nullable public static URL toUrl(Object value) { diff --git a/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java b/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java index 88a9abb7d..2e091064f 100644 --- a/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java +++ b/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java @@ -29,7 +29,7 @@ * or the searching by all possible locators. * * @return the strategy which defines how to use locators which are described by the - * {@link AndroidFindBy} annotation + * {@link AndroidFindBy} annotation */ LocatorGroupStrategy androidAutomation() default LocatorGroupStrategy.CHAIN; @@ -39,7 +39,7 @@ * or the searching by all possible locators. * * @return the strategy which defines how to use locators which are described by the - * {@link WindowsFindBy} annotation + * {@link WindowsFindBy} annotation */ LocatorGroupStrategy windowsAutomation() default LocatorGroupStrategy.CHAIN; @@ -49,7 +49,7 @@ * or the searching by all possible locators. * * @return the strategy which defines how to use locators which are described by the - * {@link iOSXCUITFindBy} annotation + * {@link iOSXCUITFindBy} annotation */ LocatorGroupStrategy iOSXCUITAutomation() default LocatorGroupStrategy.CHAIN; } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java index 243d49306..4999c294d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java @@ -16,11 +16,9 @@ /** * Mechanism used to locate elements within a document using a series of lookups. This class will * find all DOM elements that matches any of the locators in sequence, e.g. - * *
  * driver.findElements(new ByAll(by1, by2))
  * 
- * * will find all elements that match by1 and then all elements that match by2. * This means that the list of elements returned may not be in document order. * From 7f9b6c08b417cef63bbfc2f231e9047dd53e0274 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Jan 2023 04:57:45 +0200 Subject: [PATCH 173/501] docs: Fix build badge to point GH Actions CI (#1844) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 507aa8899..6825ba82c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client) [![Javadocs](https://www.javadoc.io/badge/io.appium/java-client.svg)](https://www.javadoc.io/doc/io.appium/java-client) -[![Build Status](https://travis-ci.org/appium/java-client.svg?branch=master)](https://travis-ci.org/appium/java-client) +[![Appium Java Client CI](https://github.com/appium/java-client/actions/workflows/gradle.yml/badge.svg)](https://github.com/appium/java-client/actions/workflows/gradle.yml) This is the Java language bindings for writing Appium Tests that conform to [WebDriver Protocol](https://w3c.github.io/webdriver/) From 54070e602b28b7d7b06c5c1f7099dc2f24cb3f8d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Jan 2023 04:58:26 +0200 Subject: [PATCH 174/501] build: Enable Checkstyle checks for test code (#1843) * build: Move Checkstyle config to a dedicated folder * build: Configure Checkstyle suppressions for test code * build: Fix all Checkstyle violations in test code * build: Enable check for Checkstyle violations in test code during build --- build.gradle | 3 +- .../checkstyle/appium-style.xml | 5 +++ config/checkstyle/suppressions.xml | 5 +++ .../java_client/android/LogEventTest.java | 4 +- .../drivers/options/OptionsBuildingTest.java | 4 +- .../internal/SessionConnectTest.java | 1 + .../appium/java_client/ios/IOSDriverTest.java | 3 +- .../AndroidPageObjectTest.java | 38 +++++++++---------- .../pagefactory_tests/TimeoutTest.java | 6 +-- .../tests/combined/CombinedAppTest.java | 24 ++++++------ .../java_client/proxy/ProxyHelpersTest.java | 3 +- .../service/local/ServerBuilderTest.java | 4 +- 12 files changed, 57 insertions(+), 43 deletions(-) rename appium-style.xml => config/checkstyle/appium-style.xml (98%) create mode 100644 config/checkstyle/suppressions.xml diff --git a/build.gradle b/build.gradle index 837836f17..798d03182 100644 --- a/build.gradle +++ b/build.gradle @@ -99,11 +99,10 @@ if (JavaVersion.current().isJava11Compatible()) { checkstyle { toolVersion = '10.6.0' - configFile = file("$projectDir/appium-style.xml") + configFile = configDirectory.file('appium-style.xml').get().getAsFile() showViolations = true ignoreFailures = false } - checkstyleTest.enabled = false } javadoc { diff --git a/appium-style.xml b/config/checkstyle/appium-style.xml similarity index 98% rename from appium-style.xml rename to config/checkstyle/appium-style.xml index 24b63f8c6..2feb5eeff 100755 --- a/appium-style.xml +++ b/config/checkstyle/appium-style.xml @@ -203,4 +203,9 @@
+ + + + +
diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml new file mode 100644 index 000000000..0587e646e --- /dev/null +++ b/config/checkstyle/suppressions.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/test/java/io/appium/java_client/android/LogEventTest.java b/src/test/java/io/appium/java_client/android/LogEventTest.java index ea820fa94..16d28f31e 100644 --- a/src/test/java/io/appium/java_client/android/LogEventTest.java +++ b/src/test/java/io/appium/java_client/android/LogEventTest.java @@ -36,8 +36,8 @@ public void verifyLoggingCustomEvents() { driver.logEvent(evt); ServerEvents events = driver.getEvents(); boolean hasCustomEvent = events.events.stream().anyMatch((TimedEvent event) -> - event.name.equals("appium:funEvent") && - event.occurrences.get(0).intValue() > 0 + event.name.equals("appium:funEvent") + && event.occurrences.get(0).intValue() > 0 ); boolean hasCommandName = events.commands.stream().anyMatch((CommandEvent event) -> event.name.equals("logCustomEvent") diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java index ab10f1ec1..908ff709e 100644 --- a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -108,7 +108,7 @@ public void canBuildEspressoOptions() { "com.dep1:1.2.3", "com.dep2:1.2.3" )) - ); + ); assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); assertEquals("CN", options.getAppLocale().orElse(null).getCountry().orElse(null)); assertEquals(2, options.getEspressoBuildConfig().orElse(null) @@ -172,7 +172,7 @@ public void canBuildSafariOptions() { .setWebkitWebrtc(new WebrtcData() .withDisableIceCandidateFiltering(true) .withDisableInsecureMediaCapture(true) - ); + ); assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); assertTrue(options.doesSafariUseSimulator().orElse(false)); assertTrue(options.getWebkitWebrtc().orElse(null) diff --git a/src/test/java/io/appium/java_client/internal/SessionConnectTest.java b/src/test/java/io/appium/java_client/internal/SessionConnectTest.java index 52b4b051a..a97653882 100644 --- a/src/test/java/io/appium/java_client/internal/SessionConnectTest.java +++ b/src/test/java/io/appium/java_client/internal/SessionConnectTest.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.appium.java_client.internal; import io.appium.java_client.ios.IOSDriver; diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index 43d296d55..f977289c0 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -60,7 +60,8 @@ public void addCustomCommandTest() { @Test public void addCustomCommandWithSessionIdTest() { - driver.addCommand(HttpMethod.POST, "/session/" + driver.getSessionId() + "/appium/app/launch", "launchApplication"); + driver.addCommand(HttpMethod.POST, "/session/" + driver.getSessionId() + "/appium/app/launch", + "launchApplication"); final Response launchApplication = driver.execute("launchApplication"); assertNotNull(launchApplication.getSessionId()); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index a135c30e3..abcd92c80 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -167,41 +167,41 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidFindBy(id = "android:id/text1", priority = 2) @AndroidFindAll(value = { - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), - @AndroidBy(id = "android:id/fakeId")}, priority = 1) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidBy(id = "android:id/fakeId")}, priority = 1) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") private WebElement androidElementViewFoundByMixedSearching; @AndroidFindBy(id = "android:id/text1", priority = 2) @AndroidFindAll(value = { - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), - @AndroidBy(id = "android:id/fakeId")}, priority = 1) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidBy(id = "android:id/fakeId")}, priority = 1) @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")") private List androidElementsViewFoundByMixedSearching; @AndroidFindBys({ - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), - @AndroidBy(className = "android.widget.FrameLayout")}) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), + @AndroidBy(className = "android.widget.FrameLayout")}) @AndroidFindBys({@AndroidBy(id = "android:id/text1", priority = 1), - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) private WebElement androidElementViewFoundByMixedSearching2; @AndroidFindBys({ - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), - @AndroidBy(className = "android.widget.FrameLayout")}) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), + @AndroidBy(className = "android.widget.FrameLayout")}) @AndroidFindBys({ - @AndroidBy(id = "android:id/text1", priority = 1), - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) + @AndroidBy(id = "android:id/text1", priority = 1), + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")")}) private List androidElementsViewFoundByMixedSearching2; @HowToUseLocators(androidAutomation = ALL_POSSIBLE) @AndroidFindBy(id = "android:id/fakeId1") @AndroidFindBy(id = "android:id/fakeId2", priority = 1) @AndroidFindBys(value = { - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), - @AndroidBy(id = "android:id/text1", priority = 3), - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")", priority = 2), - @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), + @AndroidBy(id = "android:id/text1", priority = 3), + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")", priority = 2), + @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) @AndroidFindBy(id = "android:id/fakeId3", priority = 3) @AndroidFindBy(id = "android:id/fakeId4", priority = 4) private WebElement androidElementViewFoundByMixedSearching3; @@ -210,10 +210,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @AndroidFindBy(id = "android:id/fakeId1") @AndroidFindBy(id = "android:id/fakeId2", priority = 1) @AndroidFindBys(value = { - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), - @AndroidBy(id = "android:id/text1", priority = 3), - @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")", priority = 2), - @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/content\")", priority = 1), + @AndroidBy(id = "android:id/text1", priority = 3), + @AndroidBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")", priority = 2), + @AndroidBy(className = "android.widget.FrameLayout")}, priority = 2) @AndroidFindBy(id = "android:id/fakeId3", priority = 3) @AndroidFindBy(id = "android:id/fakeId4", priority = 4) private List androidElementsViewFoundByMixedSearching3; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java index 2fbe87f41..1ae9157a3 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java @@ -50,13 +50,13 @@ public class TimeoutTest { private WebDriver driver; @FindAll({ - @FindBy(className = "ClassWhichDoesNotExist"), - @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) + @FindBy(className = "ClassWhichDoesNotExist"), + @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) private List stubElements; @WithTimeout(time = 5, chronoUnit = SECONDS) @FindAll({@FindBy(className = "ClassWhichDoesNotExist"), - @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) + @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) private List stubElements2; private Duration timeOutDuration; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index 100f0322c..2a453c2d9 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -19,6 +19,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.openqa.selenium.support.PageFactory.initElements; @SuppressWarnings({"unused", "unchecked"}) @@ -31,29 +32,30 @@ public class CombinedAppTest { */ public static Stream data() { return Stream.of( - Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), + arguments(new CombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), + arguments(new CombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultIosXCUITWidget.class), - Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), - Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), - Arguments.of(new CombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), + arguments(new CombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), + arguments(new CombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), + arguments(new CombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class), - Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), + arguments(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), - Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), + arguments(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultStubWidget.class), - Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), + arguments(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultStubWidget.class), - Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), + arguments(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), - Arguments.of(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), + arguments(new PartiallyCombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class) ); } @ParameterizedTest @MethodSource("data") - void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { + void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, + Class widgetClass) { initElements(new AppiumFieldDecorator(driver), app); assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSelfReference().getClass(), diff --git a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java index fc389b6c6..218c56270 100644 --- a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java +++ b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java @@ -43,7 +43,8 @@ public FakeIOSDriver(URL url, Capabilities caps) { } @Override - protected void startSession(Capabilities capabilities) {} + protected void startSession(Capabilities capabilities) { + } } @Test diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index 923fa57b8..5d4fd5715 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -319,21 +319,21 @@ void checkAbilityToStartServiceWithLogFileUsingShortFlag() { @Test void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() { - String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); String basePath = "wd/hub"; service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); service.start(); assertTrue(service.isRunning()); + String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); assertEquals(baseUrl + basePath + "/", service.getUrl().toString()); } @Test void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { - String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); String basePath = "/wd/"; service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); service.start(); assertTrue(service.isRunning()); + String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); assertEquals(baseUrl + basePath.substring(1), service.getUrl().toString()); } From bd5635f55d6a69b7d7514f070f65f537cf5ceae9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Jan 2023 19:11:46 +0200 Subject: [PATCH 175/501] chore: Configure `CODEOWNERS` to automate review requests (#1846) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..49cf4f31e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @mykola-mokhnach @SrinivasanTarget @saikrishna321 @valfirst From 8ee8500593c90052f29a370ac97ae1edd1aba9a5 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Jan 2023 21:04:56 +0200 Subject: [PATCH 176/501] ci: Enable execution of unit tests in CI (#1845) --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index dfde4399d..e9d7c7ef5 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -33,4 +33,4 @@ jobs: java-version: ${{ matrix.java }} cache: 'gradle' - name: Build with Gradle - run: ./gradlew clean build -x unitTest + run: ./gradlew clean build unitTest From 2c87e7be2de19d9a7d3ff72195e22ef912eb8d00 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Jan 2023 21:05:43 +0200 Subject: [PATCH 177/501] test: Add Simple SLF4J binding to unit tests runtime (#1848) This change fixes the following error: ``` SLF4J: No SLF4J providers were found. SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details. ``` --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 798d03182..c4bff9b07 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') + slf4jVersion = '2.0.6' } dependencies { @@ -54,7 +55,7 @@ dependencies { implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.slf4j:slf4j-api:2.0.6' + implementation "org.slf4j:slf4j-api:${slf4jVersion}" testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.hamcrest:hamcrest:2.2' @@ -67,6 +68,7 @@ dependencies { prefer "${seleniumVersion}" } } + testRuntimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" } ext { From ca86a3905dc8826354eab543f6e88d543f14a1ca Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 26 Jan 2023 09:53:46 +0200 Subject: [PATCH 178/501] perf: Improve performance of proxy `Interceptor` logging (#1849) --- .../io/appium/java_client/proxy/Interceptor.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java index 921b86124..d343fc9c1 100644 --- a/src/main/java/io/appium/java_client/proxy/Interceptor.java +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -72,10 +72,10 @@ public static Object intercept( } catch (NotImplementedException e) { // ignore } catch (Exception e) { - logger.error( - String.format("Got an unexpected error in beforeCall listener of %s.%s method", - self.getClass().getName(), method.getName()), e - ); + logger.atError() + .addArgument(() -> self.getClass().getName()) + .addArgument(method::getName) + .log("Got an unexpected error in beforeCall listener of {}.{} method", e); } }); @@ -118,10 +118,10 @@ public static Object intercept( } catch (NotImplementedException e) { // ignore } catch (Exception e) { - logger.error( - String.format("Got an unexpected error in afterCall listener of %s.%s method", - self.getClass().getName(), method.getName()), e - ); + logger.atError() + .addArgument(() -> self.getClass().getName()) + .addArgument(method::getName) + .log("Got an unexpected error in afterCall listener of {}.{} method", e); } }); return endResult; From 4be4904c239ccddb7a1fbe9492be8e687711f0a1 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 27 Jan 2023 12:51:05 +0200 Subject: [PATCH 179/501] build: Merge misc tests suite into unit tests suite (#1850) --- azure-pipelines.yml | 12 ------------ build.gradle | 16 ++++------------ 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 558a97c23..c52cbfca3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -64,15 +64,3 @@ jobs: publishJUnitResults: true tasks: 'build' options: 'xcuiTest -x test' -- job: Misc_Tests - steps: - - task: Gradle@2 - inputs: - gradleWrapperFile: 'gradlew' - gradleOptions: '-Xmx3072m' - javaHomeOption: 'JDKVersion' - jdkVersionOption: "$(JDK_VERSION)" - jdkArchitectureOption: 'x64' - publishJUnitResults: true - tasks: 'build' - options: 'miscTest -x test -x signMavenJavaPublication' diff --git a/build.gradle b/build.gradle index c4bff9b07..7e9991551 100644 --- a/build.gradle +++ b/build.gradle @@ -205,8 +205,12 @@ task unitTest( type: Test ) { testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { + includeTestsMatching 'io.appium.java_client.drivers.options.*' + includeTestsMatching 'io.appium.java_client.events.*' includeTestsMatching 'io.appium.java_client.internal.*' includeTestsMatching 'io.appium.java_client.proxy.*' + includeTestsMatching 'io.appium.java_client.remote.*' + includeTestsMatching 'io.appium.java_client.touch.*' } } @@ -241,15 +245,3 @@ task uiAutomationTest( type: Test ) { includeTestsMatching 'io.appium.java_client.service.local.ThreadSafetyTest' } } - -task miscTest( type: Test ) { - useJUnitPlatform() - testLogging.showStandardStreams = true - testLogging.exceptionFormat = 'full' - filter { - includeTestsMatching 'io.appium.java_client.touch.*' - includeTestsMatching 'io.appium.java_client.events.*' - includeTestsMatching 'io.appium.java_client.remote.*' - includeTestsMatching 'io.appium.java_client.drivers.options.*' - } -} From 585bb1b02f5b87169b19564ac045513d8a065f3d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 1 Feb 2023 05:58:54 +0200 Subject: [PATCH 180/501] build: Bump JaCoCo from `0.8.5` to `0.8.8` (#1854) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7e9991551..098ebe28f 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,7 @@ dependencyCheck { } jacoco { - toolVersion = '0.8.5' + toolVersion = '0.8.8' } tasks.withType(JacocoReport) { From dc5a97d20e4f3c90793a65f5534d5143cde7c7eb Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 2 Feb 2023 12:23:24 +0200 Subject: [PATCH 181/501] build: Make unit tests execution a part of Gradle build lifecycle (#1853) --- .github/workflows/gradle.yml | 2 +- azure-pipelines.yml | 6 ++---- build.gradle | 3 ++- jitpack.yml | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e9d7c7ef5..cd399065c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -33,4 +33,4 @@ jobs: java-version: ${{ matrix.java }} cache: 'gradle' - name: Build with Gradle - run: ./gradlew clean build unitTest + run: ./gradlew clean build diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c52cbfca3..a3d59c308 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -42,8 +42,7 @@ jobs: jdkVersionOption: "$(JDK_VERSION)" jdkArchitectureOption: 'x64' publishJUnitResults: true - tasks: 'build' - options: 'uiAutomationTest -x test' + tasks: 'build uiAutomationTest' - job: iOS_E2E_Tests # timeoutInMinutes: '90' steps: @@ -62,5 +61,4 @@ jobs: jdkVersionOption: "$(JDK_VERSION)" jdkArchitectureOption: 'x64' publishJUnitResults: true - tasks: 'build' - options: 'xcuiTest -x test' + tasks: 'build xcuiTest' diff --git a/build.gradle b/build.gradle index 098ebe28f..f5decafd4 100644 --- a/build.gradle +++ b/build.gradle @@ -200,7 +200,7 @@ processResources { ] } -task unitTest( type: Test ) { +test { useJUnitPlatform() testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' @@ -212,6 +212,7 @@ task unitTest( type: Test ) { includeTestsMatching 'io.appium.java_client.remote.*' includeTestsMatching 'io.appium.java_client.touch.*' } + finalizedBy jacocoTestReport } task xcuiTest( type: Test ) { diff --git a/jitpack.yml b/jitpack.yml index e594bc18b..f5edf063b 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,4 @@ jdk: - openjdk8 install: - - ./gradlew clean build publishToMavenLocal -x signMavenJavaPublication -x test + - ./gradlew clean build publishToMavenLocal -x signMavenJavaPublication From 3adfd03af555cd92b62fc942af102de9f808f648 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 12:18:43 +0300 Subject: [PATCH 182/501] build(deps): bump org.projectlombok:lombok from 1.18.24 to 1.18.26 (#1856) * build(deps): bump org.projectlombok:lombok from 1.18.24 to 1.18.26 Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.24 to 1.18.26. - [Release notes](https://github.com/projectlombok/lombok/releases) - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.24...v1.18.26) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: Bump lombok used by annotation processor as well --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Valery Yatsynovich --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f5decafd4..cec2cf33b 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.24' - annotationProcessor 'org.projectlombok:lombok:1.18.24' + compileOnly 'org.projectlombok:lombok:1.18.26' + annotationProcessor 'org.projectlombok:lombok:1.18.26' api ('org.seleniumhq.selenium:selenium-api') { version { From d4240e7b1d63baf3ca797e561aa14266d7bbae81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:15:18 +0300 Subject: [PATCH 183/501] build(deps): Bump org.owasp.dependencycheck from 8.0.1 to 8.1.0 (#1863) Bumps org.owasp.dependencycheck from 8.0.1 to 8.1.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cec2cf33b..59c376ed0 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.0.1' + id 'org.owasp.dependencycheck' version '8.1.0' id 'com.github.johnrengelman.shadow' version '7.1.2' } From a9fd23ffd7c0ef77119afb00699a8f5b464d34e3 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 27 Feb 2023 13:22:29 +0300 Subject: [PATCH 184/501] chore: Upgrade to Gradle 8.0.1 (#1865) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 59c376ed0..0b8eb9c4d 100644 --- a/build.gradle +++ b/build.gradle @@ -90,7 +90,7 @@ tasks.withType(JacocoReport) { sourceSets sourceSets.main reports { html.required = true - html.destination file("${buildDir}/Reports/jacoco") + html.outputLocation = file("${buildDir}/Reports/jacoco") } } jacocoTestReport.dependsOn test diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 5094 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 delta 5107 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 I6Xdi10eY*&F8}}l diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2b22d057a..6ec1567a0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68d6..79a61d421 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac From 919c2257dbe7acd2e62c36aa4bd6611f50d88e05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:08:48 +0300 Subject: [PATCH 185/501] build(deps): Bump com.github.johnrengelman.shadow from 7.1.2 to 8.0.0 (#1866) Bumps com.github.johnrengelman.shadow from 7.1.2 to 8.0.0. --- updated-dependencies: - dependency-name: com.github.johnrengelman.shadow dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0b8eb9c4d..3452af8a3 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '8.1.0' - id 'com.github.johnrengelman.shadow' version '7.1.2' + id 'com.github.johnrengelman.shadow' version '8.0.0' } repositories { From 73518775dfee83b5930d158f12d9eba1232b8e21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 15:39:26 +0300 Subject: [PATCH 186/501] build(deps): Bump com.github.johnrengelman.shadow from 8.0.0 to 8.1.0 (#1868) Bumps com.github.johnrengelman.shadow from 8.0.0 to 8.1.0. --- updated-dependencies: - dependency-name: com.github.johnrengelman.shadow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3452af8a3..63ff01ba1 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '8.1.0' - id 'com.github.johnrengelman.shadow' version '8.0.0' + id 'com.github.johnrengelman.shadow' version '8.1.0' } repositories { From 653213f513783a9bea1cca83664d7a52fb1fba1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 16:33:46 +0300 Subject: [PATCH 187/501] build(deps): Bump org.owasp.dependencycheck from 8.1.0 to 8.1.2 (#1867) Bumps org.owasp.dependencycheck from 8.1.0 to 8.1.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 63ff01ba1..3b06d2e62 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.1.0' + id 'org.owasp.dependencycheck' version '8.1.2' id 'com.github.johnrengelman.shadow' version '8.1.0' } From 71f51cde48d1015b791ae4825a14cd9650f5fd85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 15:24:02 +0300 Subject: [PATCH 188/501] build(deps): Bump slf4jVersion from 2.0.6 to 2.0.7 (#1870) Bumps `slf4jVersion` from 2.0.6 to 2.0.7. Updates `org.slf4j:slf4j-api` from 2.0.6 to 2.0.7 - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/commits) Updates `org.slf4j:slf4j-simple` from 2.0.6 to 2.0.7 - [Release notes](https://github.com/qos-ch/slf4j/releases) - [Commits](https://github.com/qos-ch/slf4j/commits) --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3b06d2e62..b9319ca4d 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.6' + slf4jVersion = '2.0.7' } dependencies { From 4107f7068fa4dce393c869500944c5a2ee3d48af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 22:01:00 +0300 Subject: [PATCH 189/501] build(deps): Bump org.owasp.dependencycheck from 8.1.2 to 8.2.1 (#1873) Bumps org.owasp.dependencycheck from 8.1.2 to 8.2.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b9319ca4d..b1cade693 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.1.2' + id 'org.owasp.dependencycheck' version '8.2.1' id 'com.github.johnrengelman.shadow' version '8.1.0' } From 06ce52a24d82fcb4e65314daf06087cd1665da43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 17:29:48 +0300 Subject: [PATCH 190/501] build(deps): Bump com.github.johnrengelman.shadow from 8.1.0 to 8.1.1 (#1874) Bumps com.github.johnrengelman.shadow from 8.1.0 to 8.1.1. --- updated-dependencies: - dependency-name: com.github.johnrengelman.shadow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b1cade693..3c6be8d18 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '8.2.1' - id 'com.github.johnrengelman.shadow' version '8.1.0' + id 'com.github.johnrengelman.shadow' version '8.1.1' } repositories { From 0c269b77bbe48858a43d9e08cf7fc99659b176bd Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 28 Mar 2023 17:36:06 +0200 Subject: [PATCH 191/501] fix: Avoid NPE in destroyProcess call (#1878) --- .../java_client/service/local/AppiumDriverLocalService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index b58191ec2..b16570f1e 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -54,7 +54,6 @@ public final class AppiumDriverLocalService extends DriverService { private static final String URL_MASK = "http://%s:%d/"; private static final Logger LOG = LoggerFactory.getLogger(AppiumDriverLocalService.class); - private static final Pattern LOG_MESSAGE_PATTERN = Pattern.compile("^(.*)\\R"); private static final Pattern LOGGER_CONTEXT_PATTERN = Pattern.compile("^(\\[debug\\] )?\\[(.+?)\\]"); private static final String APPIUM_SERVICE_SLF4J_LOGGER_PREFIX = "appium.service"; private static final Duration DESTROY_TIMEOUT = Duration.ofSeconds(60); @@ -217,7 +216,7 @@ public void stop() { * @return The exit code of the process or zero if the process was not running. */ private int destroyProcess(Duration timeout) { - if (!process.isRunning()) { + if (process == null || !process.isRunning()) { return 0; } From 6bd82d6f6d5d310f56f94c858ce63f2b9e743d39 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 4 Apr 2023 07:22:12 +0200 Subject: [PATCH 192/501] chore: Bump the minimum selenium client version to 4.8.2 (#1880) --- gradle.properties | 2 +- .../local/AppiumDriverLocalService.java | 6 +----- .../service/local/AppiumServiceBuilder.java | 21 +++++++++++++++---- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index 716bc2a39..e1a1cc258 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.7.0 +selenium.version=4.8.2 # Please increment the value in a release appiumClient.version=8.3.0 diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index b16570f1e..d2b4d37fc 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -123,11 +123,7 @@ public URL getUrl() { public boolean isRunning() { lock.lock(); try { - if (process == null) { - return false; - } - - if (!process.isRunning()) { + if (process == null || !process.isRunning()) { return false; } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 1e6885c48..0b795872d 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import io.appium.java_client.internal.ReflectionHelpers; import io.appium.java_client.remote.AndroidMobileCapabilityType; import io.appium.java_client.remote.MobileBrowserType; import io.appium.java_client.remote.MobileCapabilityType; @@ -160,7 +161,6 @@ private static File findMainScript() { return mainAppiumJs; } - @Override protected File findDefaultExecutable() { if (this.node != null) { validatePath(this.node.getAbsolutePath(), NODE_JS_NOT_EXIST_ERROR.apply(this.node)); @@ -228,8 +228,10 @@ public AppiumServiceBuilder withArgument(ServerArgument argument, String value) private static String sanitizeBasePath(String basePath) { basePath = checkNotNull(basePath).trim(); - checkArgument(!basePath.isEmpty(), - "Given base path is not valid - blank or empty values are not allowed for base path"); + checkArgument( + !basePath.isEmpty(), + "Given base path is not valid - blank or empty values are not allowed for base path" + ); return basePath.endsWith("/") ? basePath : basePath + "/"; } @@ -401,6 +403,17 @@ protected ImmutableList createArgs() { return new ImmutableList.Builder().addAll(argList).build(); } + @Override + public AppiumDriverLocalService build() { + File driverExecutable = ReflectionHelpers.getPrivateFieldValue( + DriverService.Builder.class, this, "exe", File.class + ); + if (driverExecutable == null) { + usingDriverExecutable(findDefaultExecutable()); + } + return super.build(); + } + /** * Sets which Node.js the builder will use. * @@ -468,4 +481,4 @@ protected AppiumDriverLocalService createDriverService(File nodeJSExecutable, in return new AppiumDriverLocalService(ipAddress, nodeJSExecutable, nodeJSPort, startupTimeout, nodeArguments, nodeEnvironment).withBasePath(basePath); } -} +} \ No newline at end of file From 9be6de41e41f03afb68ce239db86e71545c63f6a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 14 Apr 2023 08:34:11 +0200 Subject: [PATCH 193/501] refactor: Replace non-W3C API calls with corresponding extension calls in app management (#1883) --- .../java_client/CommandExecutionHelper.java | 29 ++++++++ .../appium/java_client/InteractsWithApps.java | 70 +++++++++---------- .../io/appium/java_client/MobileCommand.java | 61 ++++++++++++++++ 3 files changed, 124 insertions(+), 36 deletions(-) diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 00557b6da..5290f319a 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -18,8 +18,14 @@ import org.openqa.selenium.remote.Response; +import javax.annotation.Nullable; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + public final class CommandExecutionHelper { public static T execute(ExecutesMethod executesMethod, @@ -37,4 +43,27 @@ private static T handleResponse(Response response) { } return null; } + + public static T executeScript(ExecutesMethod executesMethod, String scriptName) { + return executeScript(executesMethod, scriptName, null); + } + + /** + * Simplifies arguments preparation for the script execution command. + * + * @param executesMethod Method executor instance. + * @param scriptName Extension script name. + * @param args Extension script arguments (if present). + * @return Script execution result. + */ + public static T executeScript( + ExecutesMethod executesMethod, String scriptName, @Nullable Map args + ) { + Map payload = new HashMap<>(); + payload.put("script", scriptName); + if (args != null) { + payload.put("args", args.isEmpty() ? Collections.emptyList() : Collections.singletonList(args)); + } + return execute(executesMethod, new AbstractMap.SimpleEntry<>(EXECUTE_SCRIPT, payload)); + } } diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index eb73e6e30..fc5e17ada 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -20,21 +20,17 @@ import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.appmanagement.BaseActivateApplicationOptions; import io.appium.java_client.appmanagement.BaseInstallApplicationOptions; +import io.appium.java_client.appmanagement.BaseOptions; import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; import javax.annotation.Nullable; import java.time.Duration; -import java.util.AbstractMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; -import static io.appium.java_client.MobileCommand.ACTIVATE_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.QUERY_APP_STATE; -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.TERMINATE_APP; -import static io.appium.java_client.MobileCommand.prepareArguments; @SuppressWarnings("rawtypes") public interface InteractsWithApps extends ExecutesMethod { @@ -56,12 +52,11 @@ default void installApp(String appPath) { * the particular platform. */ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) { - String[] parameters = options == null ? new String[]{"appPath"} : - new String[]{"appPath", "options"}; - Object[] values = options == null ? new Object[]{appPath} : - new Object[]{appPath, options.build()}; - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(INSTALL_APP, prepareArguments(parameters, values))); + Map args = new HashMap<>(); + args.put("app", appPath); + args.put("appPath", appPath); + Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); + CommandExecutionHelper.executeScript(this, "mobile: installApp", args); } /** @@ -71,8 +66,10 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions * @return True if app is installed, false otherwise. */ default boolean isAppInstalled(String bundleId) { - return CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, prepareArguments("bundleId", bundleId))); + return CommandExecutionHelper.executeScript(this, "mobile: isAppInstalled", ImmutableMap.of( + "bundleId", bundleId, + "appId", bundleId + )); } /** @@ -106,12 +103,11 @@ default boolean removeApp(String bundleId) { * @return true if the uninstall was successful. */ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOptions options) { - String[] parameters = options == null ? new String[]{"bundleId"} : - new String[]{"bundleId", "options"}; - Object[] values = options == null ? new Object[]{bundleId} : - new Object[]{bundleId, options.build()}; - return CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(REMOVE_APP, prepareArguments(parameters, values))); + Map args = new HashMap<>(); + args.put("bundleId", bundleId); + args.put("appId", bundleId); + Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); + return CommandExecutionHelper.executeScript(this, "mobile: removeApp", args); } /** @@ -133,12 +129,11 @@ default void activateApp(String bundleId) { * particular platform. */ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptions options) { - String[] parameters = options == null ? new String[]{"bundleId"} : - new String[]{"bundleId", "options"}; - Object[] values = options == null ? new Object[]{bundleId} : - new Object[]{bundleId, options.build()}; - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(ACTIVATE_APP, prepareArguments(parameters, values))); + Map args = new HashMap<>(); + args.put("bundleId", bundleId); + args.put("appId", bundleId); + Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); + CommandExecutionHelper.executeScript(this, "mobile: activateApp", args); } /** @@ -148,8 +143,12 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio * @return one of possible {@link ApplicationState} values, */ default ApplicationState queryAppState(String bundleId) { - return ApplicationState.ofCode(CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(QUERY_APP_STATE, ImmutableMap.of("bundleId", bundleId)))); + return ApplicationState.ofCode( + CommandExecutionHelper.executeScript(this, "mobile: queryAppState", ImmutableMap.of( + "bundleId", bundleId, + "appId", bundleId + )) + ); } /** @@ -171,11 +170,10 @@ default boolean terminateApp(String bundleId) { * @return true if the app was running before and has been successfully stopped. */ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplicationOptions options) { - String[] parameters = options == null ? new String[]{"bundleId"} : - new String[]{"bundleId", "options"}; - Object[] values = options == null ? new Object[]{bundleId} : - new Object[]{bundleId, options.build()}; - return CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(TERMINATE_APP, prepareArguments(parameters, values))); + Map args = new HashMap<>(); + args.put("bundleId", bundleId); + args.put("appId", bundleId); + Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); + return CommandExecutionHelper.executeScript(this, "mobile: terminateApp", args); } } diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index f5e9c7fb1..dbcab47b2 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -35,83 +35,144 @@ /** * The repository of mobile commands defined in the Mobile JSON * wire protocol. + * + * Most of these commands are platform-specific obsolete things and should eventually be replaced with + * calls to corresponding `mobile:` extensions, so we don't abuse non-w3c APIs */ public class MobileCommand { //General + @Deprecated protected static final String RESET; + @Deprecated protected static final String GET_STRINGS; + @Deprecated public static final String SET_VALUE; + @Deprecated protected static final String PULL_FILE; + @Deprecated protected static final String PULL_FOLDER; public static final String RUN_APP_IN_BACKGROUND; + @Deprecated protected static final String PERFORM_TOUCH_ACTION; + @Deprecated protected static final String PERFORM_MULTI_TOUCH; + @Deprecated public static final String LAUNCH_APP; + @Deprecated public static final String CLOSE_APP; + @Deprecated protected static final String GET_DEVICE_TIME; + @Deprecated protected static final String GET_SESSION; protected static final String LOG_EVENT; protected static final String GET_EVENTS; //region Applications Management + @Deprecated protected static final String IS_APP_INSTALLED; + @Deprecated protected static final String INSTALL_APP; + @Deprecated protected static final String ACTIVATE_APP; + @Deprecated protected static final String QUERY_APP_STATE; + @Deprecated protected static final String TERMINATE_APP; + @Deprecated protected static final String REMOVE_APP; //endregion //region Clipboard + @Deprecated public static final String GET_CLIPBOARD; + @Deprecated public static final String SET_CLIPBOARD; //endregion + @Deprecated protected static final String GET_PERFORMANCE_DATA; + @Deprecated protected static final String GET_SUPPORTED_PERFORMANCE_DATA_TYPES; + @Deprecated public static final String START_RECORDING_SCREEN; + @Deprecated public static final String STOP_RECORDING_SCREEN; + @Deprecated protected static final String HIDE_KEYBOARD; + @Deprecated protected static final String LOCK; //iOS + @Deprecated protected static final String SHAKE; + @Deprecated protected static final String TOUCH_ID; + @Deprecated protected static final String TOUCH_ID_ENROLLMENT; //Android + @Deprecated protected static final String CURRENT_ACTIVITY; + @Deprecated protected static final String END_TEST_COVERAGE; + @Deprecated protected static final String GET_DISPLAY_DENSITY; + @Deprecated protected static final String GET_NETWORK_CONNECTION; + @Deprecated protected static final String GET_SYSTEM_BARS; + @Deprecated protected static final String IS_KEYBOARD_SHOWN; + @Deprecated protected static final String IS_LOCKED; + @Deprecated public static final String LONG_PRESS_KEY_CODE; + @Deprecated protected static final String FINGER_PRINT; + @Deprecated protected static final String OPEN_NOTIFICATIONS; + @Deprecated public static final String PRESS_KEY_CODE; + @Deprecated protected static final String PUSH_FILE; + @Deprecated protected static final String SET_NETWORK_CONNECTION; + @Deprecated protected static final String START_ACTIVITY; + @Deprecated protected static final String TOGGLE_LOCATION_SERVICES; + @Deprecated protected static final String UNLOCK; + @Deprecated public static final String REPLACE_VALUE; protected static final String GET_SETTINGS; + @Deprecated protected static final String SET_SETTINGS; + @Deprecated protected static final String GET_CURRENT_PACKAGE; + @Deprecated protected static final String SEND_SMS; + @Deprecated protected static final String GSM_CALL; + @Deprecated protected static final String GSM_SIGNAL; + @Deprecated protected static final String GSM_VOICE; + @Deprecated protected static final String NETWORK_SPEED; + @Deprecated protected static final String POWER_CAPACITY; + @Deprecated protected static final String POWER_AC_STATE; + @Deprecated protected static final String TOGGLE_WIFI; + @Deprecated protected static final String TOGGLE_AIRPLANE_MODE; + @Deprecated protected static final String TOGGLE_DATA; protected static final String COMPARE_IMAGES; protected static final String EXECUTE_DRIVER_SCRIPT; + @Deprecated protected static final String GET_ALLSESSION; protected static final String EXECUTE_GOOGLE_CDP_COMMAND; From 5733d27bd75551bc0efec793afbf0b3b869e4636 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 14 Apr 2023 08:58:40 +0200 Subject: [PATCH 194/501] refactor: Switch the time getter to use mobile extensions (#1884) --- .../java_client/CommandExecutionHelper.java | 6 ++---- .../io/appium/java_client/HasDeviceTime.java | 17 +++-------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 5290f319a..e0a379e17 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -38,10 +38,8 @@ public static T execute(ExecutesMethod executesMethod, String command) { } private static T handleResponse(Response response) { - if (response != null) { - return (T) response.getValue(); - } - return null; + //noinspection unchecked + return response == null ? null : (T) response.getValue(); } public static T executeScript(ExecutesMethod executesMethod, String scriptName) { diff --git a/src/main/java/io/appium/java_client/HasDeviceTime.java b/src/main/java/io/appium/java_client/HasDeviceTime.java index fb9fc59b6..f29e3f3f1 100644 --- a/src/main/java/io/appium/java_client/HasDeviceTime.java +++ b/src/main/java/io/appium/java_client/HasDeviceTime.java @@ -16,14 +16,7 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import org.openqa.selenium.remote.DriverCommand; -import org.openqa.selenium.remote.Response; - -import java.util.Map; - -import static io.appium.java_client.MobileCommand.GET_DEVICE_TIME; public interface HasDeviceTime extends ExecutesMethod { @@ -38,12 +31,9 @@ public interface HasDeviceTime extends ExecutesMethod { * @return Device time string */ default String getDeviceTime(String format) { - Map params = ImmutableMap.of( - "script", "mobile: getDeviceTime", - "args", ImmutableList.of(ImmutableMap.of("format", format)) + return CommandExecutionHelper.executeScript( + this, "mobile: getDeviceTime", ImmutableMap.of("format", format) ); - Response response = execute(DriverCommand.EXECUTE_SCRIPT, params); - return response.getValue().toString(); } /** @@ -53,7 +43,6 @@ default String getDeviceTime(String format) { * @return Device time string */ default String getDeviceTime() { - Response response = execute(GET_DEVICE_TIME); - return response.getValue().toString(); + return CommandExecutionHelper.executeScript(this, "mobile: getDeviceTime"); } } From 6f19f27d36ab2d25936b02c908b30babe5d3e51a Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 14 Apr 2023 16:18:16 +0300 Subject: [PATCH 195/501] build: Upgrade to Gradle 8.1 (#1882) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 61608 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 ++++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 3c6be8d18..88070b21e 100644 --- a/build.gradle +++ b/build.gradle @@ -189,7 +189,7 @@ signing { } wrapper { - gradleVersion = '7.6' + gradleVersion = '8.1' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba7710deaf9f98673a68957ea02138b60d0a..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 8979 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 F{TFmrHLU;u delta 8469 zcmY*q~ZGqoW{=01$bgB@1Nex`%9%S2I04)5Jw9+UyLS&r+9O2bq{gY;dCa zHW3WY0%Dem?S7n5JZO%*yiT9fb!XGk9^Q`o-EO{a^j%&)ZsxsSN@2k2eFx1*psqn0e*crIbAO}Rd~_BifMu*q7SUn{>WD$=7n_$uiQ0wGc$?u1hM%gf??nL?m22h!8{ zYmFMLvx6fjz*nwF^tAqx1uv0yEW9-tcIV5Q{HNh`9PMsuqD8VE%oAs5FsWa0mLV$L zPAF5e^$tJ8_Kwp!$N1M<#Z154n!X6hFpk8)eMLu; zaXS71&`24 zV`x~}yAxBw##Oj@qo_@DcBqc+2TB&=bJyZWTeR55zG<{Z@T^hSbMdm~Ikkr?4{7WT zcjPyu>0sDjl7&?TL@ z)cW?lW@Pfwu#nm7E1%6*nBIzQrKhHl`t54$-m>j8f%0vVr?N0PTz`}VrYAl+8h^O~ zuWQj@aZSZmGPtcVjGq-EQ1V`)%x{HZ6pT-tZttJOQm?q-#KzchbH>>5-jEX*K~KDa z#oO&Qf4$@}ZGQ7gxn<;D$ziphThbi6zL^YC;J#t0GCbjY)NHdqF=M4e(@|DUPY_=F zLcX1HAJ+O-3VkU#LW`4;=6szwwo%^R4#UK}HdAXK` z{m!VZj5q9tVYL=^TqPH*6?>*yr>VxyYF4tY{~?qJ*eIoIU0}-TLepzga4g}}D7#Qu zn;6I;l!`xaL^8r*Tz*h`^(xJCnuVR_O@Gl*Q}y$lp%!kxD`%zN19WTIf`VX*M=cDp z*s4<9wP|ev;PARRV`g$R*QV@rr%Ku~z(2-s>nt{JI$357vnFAz9!ZsiiH#4wOt+!1 zM;h;EN__zBn)*-A^l!`b?b*VI-?)Sj6&Ov3!j9k$5+#w)M>`AExCm0!#XL+E{Bp)s;Hochs+-@@)7_XDMPby#p<9mLu+S{8e2Jn`1`1nrffBfy4u)p7FFQWzgYt zXC}GypRdkTUS+mP!jSH$K71PYI%QI-{m;DvlRb*|4GMPmvURv0uD2bvS%FOSe_$4zc--*>gfRMKN|D ztP^WFfGEkcm?sqXoyRmuCgb?bSG17#QSv4~XsbPH>BE%;bZQ_HQb?q%CjykL7CWDf z!rtrPk~46_!{V`V<;AjAza;w-F%t1^+b|r_um$#1cHZ1|WpVUS&1aq?Mnss|HVDRY z*sVYNB+4#TJAh4#rGbr}oSnxjD6_LIkanNvZ9_#bm?$HKKdDdg4%vxbm-t@ZcKr#x z6<$$VPNBpWM2S+bf5IBjY3-IY2-BwRfW_DonEaXa=h{xOH%oa~gPW6LTF26Y*M)$N z=9i`Y8};Qgr#zvU)_^yU5yB;9@yJjrMvc4T%}a|jCze826soW-d`V~eo%RTh)&#XR zRe<8$42S2oz|NVcB%rG(FP2U&X>3 z4M^}|K{v64>~rob;$GO55t;Nb&T+A3u(>P6;wtp6DBGWbX|3EZBDAM2DCo&4w|WGpi;~qUY?Ofg$pX&`zR~)lr)8}z^U3U38Nrtnmf~e7$i=l>+*R%hQgDrj%P7F zIjyBCj2$Td=Fp=0Dk{=8d6cIcW6zhK!$>k*uC^f}c6-NR$ zd<)oa+_fQDyY-}9DsPBvh@6EvLZ}c)C&O-+wY|}RYHbc2cdGuNcJ7#yE}9=!Vt-Q~ z4tOePK!0IJ0cW*jOkCO? zS-T!bE{5LD&u!I4tqy;dI*)#e^i)uIDxU?8wK1COP3Qk{$vM3Sm8(F2VwM?1A+dle z6`M6bbZye|kew%w9l`GS74yhLluJU5R=#!&zGwB7lmTt}&eCt0g(-a;Mom-{lL6u~ zFgjyUs1$K*0R51qQTW_165~#WRrMxiUx{0F#+tvgtcjV$U|Z}G*JWo6)8f!+(4o>O zuaAxLfUl;GHI}A}Kc>A8h^v6C-9bb}lw@rtA*4Q8)z>0oa6V1>N4GFyi&v69#x&CwK*^!w&$`dv zQKRMKcN$^=$?4to7X4I`?PKGi(=R}d8cv{74o|9FwS zvvTg0D~O%bQpbp@{r49;r~5`mcE^P<9;Zi$?4LP-^P^kuY#uBz$F!u1d{Ens6~$Od zf)dV+8-4!eURXZZ;lM4rJw{R3f1Ng<9nn2_RQUZDrOw5+DtdAIv*v@3ZBU9G)sC&y!vM28daSH7(SKNGcV z&5x#e#W2eY?XN@jyOQiSj$BlXkTG3uAL{D|PwoMp$}f3h5o7b4Y+X#P)0jlolgLn9xC%zr3jr$gl$8?II`DO6gIGm;O`R`bN{;DlXaY4b`>x6xH=Kl@ z!>mh~TLOo)#dTb~F;O z8hpjW9Ga?AX&&J+T#RM6u*9x{&%I8m?vk4eDWz^l2N_k(TbeBpIwcV4FhL(S$4l5p z@{n7|sax){t!3t4O!`o(dYCNh90+hl|p%V_q&cwBzT*?Nu*D0wZ)fPXv z@*;`TO7T0WKtFh8~mQx;49VG_`l`g|&VK}LysK%eU4})Cvvg3YN)%;zI?;_Nr z)5zuU1^r3h;Y+mJov*->dOOj>RV^u2*|RraaQWsY5N?Uu)fKJOCSL2^G=RB%(4K{* zx!^cB@I|kJR`b+5IK}(6)m=O{49P5E^)!XvD5zVuzJH{01^#$@Cn514w41BB;FAoS2SYl3SRrOBDLfl5MvgA3 zU6{T?BW}l~8vU;q@p9IOM(=;WdioeQmt?X|=L9kyM&ZsNc*-Knv8@U*O96T@4ZiJ$ zeFL2}pw_~Tm3d4#q!zZS0km@vYgym33C0h(6D)6|Y)*UXI^T`(QPQh$WF?&h(3QYh zqGw@?BTk@VA_VxK@z?a@UrMhY zUD16oqx4$$6J_k0HnXgARm}N#(^yA1MLdbwmEqHnX*JdHN>$5k2E|^_bL< zGf5Z+D!9dXR>^(5F&5gIew1%kJtFUwI5P1~I$4LL_6)3RPzw|@2vV;Q^MeQUKzc=KxSTTX`}u%z?h~;qI#%dE@OZwehZyDBsWTc&tOC1c%HS#AyTJ= zQixj=BNVaRS*G!;B$}cJljeiVQabC25O+xr4A+32HVb;@+%r}$^u4-R?^3yij)0xb z86i@aoVxa%?bfOE;Bgvm&8_8K(M-ZEj*u9ms_Hk#2eL`PSnD#At!0l{f!v`&Kg}M$n(&R)?AigC5Z?T7Jv^lrDL!yYS{4 zq_H}oezX-Svu>dp)wE@khE@aR5vY=;{C-8Hws++5LDpArYd)U47jc-;f~07_TPa^1 zO`0+uIq)@?^!%JXCDid+nt|c@NG1+ce@ijUX&@rV9UiT|m+t-nqVB7?&UX*|{yDBFw9x52&dTh@;CL)Q?6s1gL=CUQTX7#TJPs9cpw<4>GFMUKo|f{! z&(%2hP6ghr%UFVO-N^v9l|tKy>&e%8us}wT0N*l(tezoctVtLmNdGPOF6oaAGJI5R zZ*|k@z3H!~Mm9fXw{bbP6?lV-j#Rfgnjf++O7*|5vz2#XK;kk ztJbi%r0{U5@QwHYfwdjtqJ6?;X{Ul3?W0O0bZ$k*y z4jWsNedRoCb7_|>nazmq{T3Y_{<5IO&zQ?9&uS@iL+|K|eXy^F>-60HDoVvovHelY zy6p(}H^7b+$gu@7xLn_^oQryjVu#pRE5&-w5ZLCK&)WJ5jJF{B>y;-=)C;xbF#wig zNxN^>TwzZbV+{+M?}UfbFSe#(x$c)|d_9fRLLHH?Xbn!PoM{(+S5IEFRe4$aHg~hP zJYt`h&?WuNs4mVAmk$yeM;8?R6;YBMp8VilyM!RXWj<95=yp=4@y?`Ua8 znR^R?u&g%`$Wa~usp|pO$aMF-en!DrolPjD_g#{8X1f=#_7hH8i|WF+wMqmxUm*!G z*4p980g{sgR9?{}B+a0yiOdR()tWE8u)vMPxAdK)?$M+O_S+;nB34@o<%lGJbXbP` z5)<({mNpHp&45UvN`b&K5SD#W){}6Y_d4v~amZPGg|3GdlWDB;;?a=Z{dd zELTfXnjCqq{Dgbh9c%LjK!Epi1TGI{A7AP|eg2@TFQiUd4Bo!JsCqsS-8ml`j{gM& zEd7yU`djX!EX2I{WZq=qasFzdDWD`Z?ULFVIP!(KQP=fJh5QC9D|$JGV95jv)!sYWY?irpvh06rw&O?iIvMMj=X zr%`aa(|{Ad=Vr9%Q(61{PB-V_(3A%p&V#0zGKI1O(^;tkS{>Y<`Ql@_-b7IOT&@?l zavh?#FW?5otMIjq+Bp?Lq)w7S(0Vp0o!J*~O1>av;)Cdok@h&JKaoHDV6IVtJ?N#XY=lknPN+SN8@3Gb+D-X*y5pQ)wnIpQlRR!Rd)@0LdA85}1 zu7W6tJ*p26ovz+`YCPePT>-+p@T_QsW$uE`McLlXb;k}!wwWuh$YC4qHRd=RS!s>2 zo39VCB-#Ew?PAYOx`x!@0qa5lZKrE?PJEwVfkww#aB_$CLKlkzHSIi4p3#IeyA@u@ z`x^!`0HJxe>#V7+Grku^in>Ppz|TD*`Ca4X%R3Yo|J=!)l$vYks|KhG{1CEfyuzK( zLjCz{5l}9>$J=FC?59^85awK0$;^9t9UxwOU8kP7ReVCc*rPOr(9uMY*aCZi2=JBu z(D0svsJRB&a9nY;6|4kMr1Er5kUVOh1TuBwa3B2C<+rS|xJo&Lnx3K-*P83eXQCJ= z(htQSA3hgOMcs`#NdYB17#zP_1N_P0peHrNo1%NsYn=;PgLXTic6b#{Y0Z~x9Ffav z^3eO+diquPfo1AXW*>G(JcGn{yN?segqKL$Wc9po(Kex z#tw_};zd++we+MPhOOgaXSmguul67JOvBysmg?wRf=OUeh(XyRcyY@8RTV@xck_c~ zLFMWAWb4^7xwR)3iO1PIs1<}L3CMJ1L-}s=>_y!`!FvYf^pJO|&nII{!Dz+b?=bUd zPJUUn))z)-TcpqKF(1tr-x1;lS?SB@mT#O7skl0sER{a|d?&>EKKaw* zQ>D^m*pNgV`54BKv?knU-T5bcvBKnI@KZo^UYjKp{2hpCo?_6v(Sg77@nQa{tSKbn zUgMtF>A3hndGocRY+Snm#)Q4%`|Qq3YTOU^uG}BGlz!B=zb?vB16sN&6J`L(k1r+$ z5G6E9tJ~Iwd!d!NH7Q%Z@BR@0e{p6#XF2))?FLAVG`npIjih*I+0!f6;+DM zLOP-qDsm9=ZrI!lfSDn%XuF17$j~gZE@I}S(Ctw&Te75P5?Fj%FLT;p-tm33FaUQc z5cR;$SwV|N0xmjox3V~XL3sV?YN}U0kkfmygW@a5JOCGgce6JyzGmgN$?NM%4;wEhUMg0uTTB~L==1Fvc(6)KMLmU z(12l^#g&9OpF7+Ll30F6(q=~>NIY=-YUJJ}@&;!RYnq*xA9h!iMi`t;B2SUqbyNGn zye@*0#Uu`OQy%utS%IA%$M1f4B|bOH={!3K1=Tc7Ra|%qZgZ{mjAGKXb)}jUu1mQ_ zRW7<;tkHv(m7E0m>**8D;+2ddTL>EcH_1YqCaTTu_#6Djm z*64!w#=Hz<>Fi1n+P}l#-)0e0P4o+D8^^Mk& zhHeJoh2paKlO+8r?$tx`qEcm|PSt6|1$1q?r@VvvMd1!*zAy3<`X9j?ZI|;jE-F(H zIn1+sm(zAnoJArtytHC|0&F0`i*dy-PiwbD-+j`ezvd4C`%F1y^7t}2aww}ZlPk)t z=Y`tm#jNM$d`pG%F42Xmg_pZnEnvC%avz=xNs!=6b%%JSuc(WObezkCeZ#C|3PpXj zkR8hDPyTIUv~?<%*)6=8`WfPPyB9goi+p$1N2N<%!tS2wopT2x`2IZi?|_P{GA|I5 z?7DP*?Gi#2SJZ!x#W9Npm)T;=;~Swyeb*!P{I^s@o5m_3GS2Lg?VUeBdOeae7&s5$ zSL_VuTJih_fq7g8O8b0g+GbmE+xG}^Wx`g~{mWTyr@=h zKlAymoHeZa`DgR?Pj8Yc+I|MrSB>X*ts#wNFOJxs!3aGE)xeTHlF`fC5^g(DTacl$ zx!ezQJdwIyc$8RyNS~Wh{0pp>8NcW)*J=7AQYdT?(QhJuq4u`QniZ!%6l{KWp-0Xp z4ZC6(E(_&c$$U_cmGFslsyX6(62~m*z8Yx2p+F5xmD%6A7eOnx`1lJA-Mrc#&xZWJ zzXV{{OIgzYaq|D4k^j%z|8JB8GnRu3hw#8Z@({sSmsF(x>!w0Meg5y(zg!Z0S^0k# z5x^g1@L;toCK$NB|Fn Date: Mon, 17 Apr 2023 15:55:58 +0200 Subject: [PATCH 196/501] refactor: Switch file management APIs to use mobile: extensions (#1886) --- .../io/appium/java_client/PullsFiles.java | 30 ++++++++--------- .../io/appium/java_client/PushesFiles.java | 33 ++++++++----------- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/main/java/io/appium/java_client/PullsFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java index f85c18a6e..2dd403771 100644 --- a/src/main/java/io/appium/java_client/PullsFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -17,14 +17,10 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; -import org.openqa.selenium.remote.Response; import java.nio.charset.StandardCharsets; import java.util.Base64; -import static io.appium.java_client.MobileCommand.PULL_FILE; -import static io.appium.java_client.MobileCommand.PULL_FOLDER; - public interface PullsFiles extends ExecutesMethod { /** @@ -33,15 +29,16 @@ public interface PullsFiles extends ExecutesMethod { * built with debuggable flag enabled in order to get access to its container * on the internal file system. * - * @param remotePath If the path starts with @applicationId// prefix, then the file - * will be pulled from the root of the corresponding application container. - * Otherwise, the root folder is considered as / on Android and - * on iOS it is a media folder root (real devices only). + * @param remotePath Path to file to read data from the remote device. + * Check the documentation on `mobile: pullFile` + * extension for more details on possible values + * for different platforms. * @return A byte array of Base64 encoded data. */ default byte[] pullFile(String remotePath) { - Response response = execute(PULL_FILE, ImmutableMap.of("path", remotePath)); - String base64String = response.getValue().toString(); + String base64String = CommandExecutionHelper.executeScript(this, "mobile: pullFile", ImmutableMap.of( + "remotePath", remotePath + )); return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } @@ -51,15 +48,16 @@ default byte[] pullFile(String remotePath) { * built with debuggable flag enabled in order to get access to its container * on the internal file system. * - * @param remotePath If the path starts with @applicationId/ prefix, then the folder - * will be pulled from the root of the corresponding application container. - * Otherwise, the root folder is considered as / on Android and - * on iOS it is a media folder root (real devices only). + * @param remotePath Path to a folder to read data from the remote device. + * Check the documentation on `mobile: pullFolder` + * extension for more details on possible values + * for different platforms. * @return A byte array of Base64 encoded zip archive data. */ default byte[] pullFolder(String remotePath) { - Response response = execute(PULL_FOLDER, ImmutableMap.of("path", remotePath)); - String base64String = response.getValue().toString(); + String base64String = CommandExecutionHelper.executeScript(this, "mobile: pullFolder", ImmutableMap.of( + "remotePath", remotePath + )); return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } diff --git a/src/main/java/io/appium/java_client/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java index 552c25a83..813dcb5b1 100644 --- a/src/main/java/io/appium/java_client/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -16,47 +16,40 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Base64; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.pushFileCommand; - public interface PushesFiles extends ExecutesMethod { /** - * Saves base64 encoded data as a media file on the remote system. + * Saves base64-encoded data as a file on the remote system. * - * @param remotePath Path to file to write data to on remote device - * Only the filename part matters there on Simulator, so the remote end - * can figure out which type of media data it is and save - * it into a proper folder on the target device. Check - * 'xcrun simctl addmedia' output to get more details on - * supported media types. - * If the path starts with @applicationId/ prefix, then the file - * will be pushed to the root of the corresponding application container. + * @param remotePath Path to file to write data to on remote device. + * Check the documentation on `mobile: pushFile` + * extension for more details on possible values + * for different platforms. * @param base64Data Base64 encoded byte array of media file data to write to remote device */ default void pushFile(String remotePath, byte[] base64Data) { - CommandExecutionHelper.execute(this, pushFileCommand(remotePath, base64Data)); + CommandExecutionHelper.executeScript(this, "mobile: pushFile", ImmutableMap.of( + "remotePath", remotePath, + "payload", new String(base64Data, StandardCharsets.UTF_8) + )); } /** - * Saves base64 encoded data as a media file on the remote system. + * Sends the file to the remote device. * * @param remotePath See the documentation on {@link #pushFile(String, byte[])} * @param file Is an existing local file to be written to the remote device - * @throws IOException when there are problems with a file or current file system + * @throws IOException when there are problems with a file on current file system */ 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(String.format("The given file %s doesn't exist", - file.getAbsolutePath())); - } pushFile(remotePath, Base64.getEncoder().encode(FileUtils.readFileToByteArray(file))); } From 1a7a12a2b625fe5da523bcd0ca61183433f4ad30 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 19 Apr 2023 12:21:32 +0200 Subject: [PATCH 197/501] refactor: Use mobile extensions for app strings getters and keyboard commands (#1890) --- .../java_client/CommandExecutionHelper.java | 26 ++++++----- .../io/appium/java_client/HasAppStrings.java | 46 +++++++++++++++---- .../appium/java_client/HasBrowserCheck.java | 12 ++--- .../java_client/HasOnScreenKeyboard.java | 13 +++++- .../io/appium/java_client/HidesKeyboard.java | 13 +++++- .../java_client/HidesKeyboardWithKeyName.java | 20 +++++++- .../appium/java_client/InteractsWithApps.java | 17 +++++-- .../io/appium/java_client/PullsFiles.java | 14 ++++-- .../java_client/android/AndroidDriver.java | 8 +--- .../android/ListensToLogcatMessages.java | 10 ++-- .../connection/HasNetworkConnection.java | 40 ++++++++++++++-- .../io/appium/java_client/ios/IOSDriver.java | 9 +--- .../ios/ListensToSyslogMessages.java | 10 ++-- 13 files changed, 166 insertions(+), 72 deletions(-) diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index e0a379e17..0a41f17b6 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -16,32 +16,37 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; import java.util.AbstractMap; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; public final class CommandExecutionHelper { - public static T execute(ExecutesMethod executesMethod, - Map.Entry> keyValuePair) { + @Nullable + public static T execute( + ExecutesMethod executesMethod, Map.Entry> keyValuePair + ) { return handleResponse(executesMethod.execute(keyValuePair.getKey(), keyValuePair.getValue())); } + @Nullable public static T execute(ExecutesMethod executesMethod, String command) { return handleResponse(executesMethod.execute(command)); } + @Nullable private static T handleResponse(Response response) { //noinspection unchecked return response == null ? null : (T) response.getValue(); } + @Nullable public static T executeScript(ExecutesMethod executesMethod, String scriptName) { return executeScript(executesMethod, scriptName, null); } @@ -50,18 +55,17 @@ public static T executeScript(ExecutesMethod executesMethod, String scriptNa * Simplifies arguments preparation for the script execution command. * * @param executesMethod Method executor instance. - * @param scriptName Extension script name. - * @param args Extension script arguments (if present). + * @param scriptName Extension script name. + * @param args Extension script arguments (if present). * @return Script execution result. */ + @Nullable public static T executeScript( ExecutesMethod executesMethod, String scriptName, @Nullable Map args ) { - Map payload = new HashMap<>(); - payload.put("script", scriptName); - if (args != null) { - payload.put("args", args.isEmpty() ? Collections.emptyList() : Collections.singletonList(args)); - } - return execute(executesMethod, new AbstractMap.SimpleEntry<>(EXECUTE_SCRIPT, payload)); + return execute(executesMethod, new AbstractMap.SimpleEntry<>(EXECUTE_SCRIPT, ImmutableMap.of( + "script", scriptName, + "args", (args == null || args.isEmpty()) ? Collections.emptyList() : Collections.singletonList(args) + ))); } } diff --git a/src/main/java/io/appium/java_client/HasAppStrings.java b/src/main/java/io/appium/java_client/HasAppStrings.java index 1983d4667..d093e777f 100644 --- a/src/main/java/io/appium/java_client/HasAppStrings.java +++ b/src/main/java/io/appium/java_client/HasAppStrings.java @@ -16,6 +16,9 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.UnsupportedCommandException; + import java.util.AbstractMap; import java.util.Map; @@ -25,37 +28,62 @@ public interface HasAppStrings extends ExecutesMethod { /** * Get all defined Strings from an app for the default language. + * See the documentation for 'mobile: getAppStrings' extension for more details. * * @return a map with localized strings defined in the app */ default Map getAppStringMap() { - return CommandExecutionHelper.execute(this, GET_STRINGS); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getAppStrings"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute(this, GET_STRINGS); + } } /** * Get all defined Strings from an app for the specified language. + * See the documentation for 'mobile: getAppStrings' extension for more details. * * @param language strings language code * @return a map with localized strings defined in the app */ default Map getAppStringMap(String language) { - return CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(GET_STRINGS, - prepareArguments("language", language))); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getAppStrings", ImmutableMap.of( + "language", language + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute( + this, new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments("language", language)) + ); + } } /** * Get all defined Strings from an app for the specified language and - * strings filename. + * strings filename. See the documentation for 'mobile: getAppStrings' + * extension for more details. * * @param language strings language code - * @param stringFile strings filename + * @param stringFile strings filename. Ignored on Android * @return a map with localized strings defined in the app */ 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))); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getAppStrings", ImmutableMap.of( + "language", language, + "stringFile", stringFile + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + 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/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java index efa5c6c62..6b00a8d5d 100644 --- a/src/main/java/io/appium/java_client/HasBrowserCheck.java +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -1,17 +1,14 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.internal.CapabilityHelpers; import org.openqa.selenium.ContextAware; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; -import java.util.Collections; - +import static com.google.common.base.Preconditions.checkNotNull; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isBlank; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { /** @@ -24,10 +21,9 @@ default boolean isBrowser() { CapabilityType.BROWSER_NAME, String.class); if (!isBlank(browserName)) { try { - return (boolean) execute(EXECUTE_SCRIPT, ImmutableMap.of( - "script", "return !!window.navigator;", - "args", Collections.emptyList() - )).getValue(); + return checkNotNull( + CommandExecutionHelper.executeScript(this, "return !!window.navigator;") + ); } catch (WebDriverException ign) { // ignore } diff --git a/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java b/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java index 7a9d6febb..322c849db 100644 --- a/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java +++ b/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java @@ -1,15 +1,24 @@ package io.appium.java_client; +import org.openqa.selenium.UnsupportedCommandException; + +import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.isKeyboardShownCommand; public interface HasOnScreenKeyboard extends ExecutesMethod { /** - * Check if the keyboard is displayed. + * Check if the on-screen keyboard is displayed. + * See the documentation for 'mobile: isKeyboardShown' extension for more details. * * @return true if keyboard is displayed. False otherwise */ default boolean isKeyboardShown() { - return CommandExecutionHelper.execute(this, isKeyboardShownCommand()); + try { + return checkNotNull(CommandExecutionHelper.executeScript(this, "mobile: isKeyboardShown")); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return checkNotNull(CommandExecutionHelper.execute(this, isKeyboardShownCommand())); + } } } diff --git a/src/main/java/io/appium/java_client/HidesKeyboard.java b/src/main/java/io/appium/java_client/HidesKeyboard.java index 5f292b0ce..6de1e0516 100644 --- a/src/main/java/io/appium/java_client/HidesKeyboard.java +++ b/src/main/java/io/appium/java_client/HidesKeyboard.java @@ -16,14 +16,25 @@ package io.appium.java_client; +import org.openqa.selenium.UnsupportedCommandException; + import static io.appium.java_client.MobileCommand.HIDE_KEYBOARD; public interface HidesKeyboard extends ExecutesMethod { /** * Hides the keyboard if it is showing. + * If the on-screen keyboard does not have any dedicated button that + * hides it then an error is going to be thrown. In such case you must emulate + * same actions an app user would do to hide the keyboard. + * See the documentation for 'mobile: hideKeyboard' extension for more details. */ default void hideKeyboard() { - execute(HIDE_KEYBOARD); + try { + CommandExecutionHelper.executeScript(this, "mobile: hideKeyboard"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, HIDE_KEYBOARD); + } } } diff --git a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java index 2549ad018..c7e809911 100644 --- a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java +++ b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java @@ -16,19 +16,33 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.UnsupportedCommandException; + import static io.appium.java_client.MobileCommand.hideKeyboardCommand; public interface HidesKeyboardWithKeyName extends HidesKeyboard { /** * Hides the keyboard by pressing the button specified by keyName if it is - * showing. + * showing. If the on-screen keyboard does not have any dedicated button that + * hides it then an error is going to be thrown. In such case you must emulate + * same actions an app user would do to hide the keyboard. + * See the documentation for 'mobile: hideKeyboard' extension for more details. * * @param keyName The button pressed by the mobile driver to attempt hiding the * keyboard. */ default void hideKeyboard(String keyName) { - CommandExecutionHelper.execute(this, hideKeyboardCommand(keyName)); + try { + CommandExecutionHelper.executeScript(this, "mobile: hideKeyboard", ImmutableMap.of( + "keys", ImmutableList.of(keyName) + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, hideKeyboardCommand(keyName)); + } } /** @@ -39,7 +53,9 @@ default void hideKeyboard(String keyName) { * @param strategy HideKeyboardStrategy. * @param keyName a String, representing the text displayed on the button of the * keyboard you want to press. For example: "Done". + * @deprecated This API is deprecated and will be removed in the future. */ + @Deprecated default void hideKeyboard(String strategy, String keyName) { CommandExecutionHelper.execute(this, hideKeyboardCommand(strategy, keyName)); } diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index fc5e17ada..fedf957c8 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Optional; +import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; @SuppressWarnings("rawtypes") @@ -66,10 +67,12 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions * @return True if app is installed, false otherwise. */ default boolean isAppInstalled(String bundleId) { - return CommandExecutionHelper.executeScript(this, "mobile: isAppInstalled", ImmutableMap.of( + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: isAppInstalled", ImmutableMap.of( "bundleId", bundleId, "appId", bundleId - )); + )) + ); } /** @@ -107,7 +110,9 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption args.put("bundleId", bundleId); args.put("appId", bundleId); Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); - return CommandExecutionHelper.executeScript(this, "mobile: removeApp", args); + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: removeApp", args) + ); } /** @@ -144,10 +149,12 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio */ default ApplicationState queryAppState(String bundleId) { return ApplicationState.ofCode( + checkNotNull( CommandExecutionHelper.executeScript(this, "mobile: queryAppState", ImmutableMap.of( "bundleId", bundleId, "appId", bundleId )) + ) ); } @@ -174,6 +181,8 @@ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplication args.put("bundleId", bundleId); args.put("appId", bundleId); Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); - return CommandExecutionHelper.executeScript(this, "mobile: terminateApp", args); + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: terminateApp", args) + ); } } diff --git a/src/main/java/io/appium/java_client/PullsFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java index 2dd403771..0042b0997 100644 --- a/src/main/java/io/appium/java_client/PullsFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -21,6 +21,8 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; +import static com.google.common.base.Preconditions.checkNotNull; + public interface PullsFiles extends ExecutesMethod { /** @@ -36,9 +38,11 @@ public interface PullsFiles extends ExecutesMethod { * @return A byte array of Base64 encoded data. */ default byte[] pullFile(String remotePath) { - String base64String = CommandExecutionHelper.executeScript(this, "mobile: pullFile", ImmutableMap.of( + String base64String = checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: pullFile", ImmutableMap.of( "remotePath", remotePath - )); + )) + ); return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } @@ -55,9 +59,11 @@ default byte[] pullFile(String remotePath) { * @return A byte array of Base64 encoded zip archive data. */ default byte[] pullFolder(String remotePath) { - String base64String = CommandExecutionHelper.executeScript(this, "mobile: pullFolder", ImmutableMap.of( + String base64String = checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: pullFolder", ImmutableMap.of( "remotePath", remotePath - )); + )) + ); return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } 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 0fc1c5917..c7290882b 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -16,7 +16,6 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; @@ -50,13 +49,10 @@ import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; -import java.util.Collections; -import java.util.Map; import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; /** * Android driver implementation. @@ -275,11 +271,9 @@ public void toggleLocationServices() { CommandExecutionHelper.execute(this, toggleLocationServicesCommand()); } - @SuppressWarnings("unchecked") @Override public AndroidBatteryInfo getBatteryInfo() { - return new AndroidBatteryInfo((Map) execute(EXECUTE_SCRIPT, ImmutableMap.of( - "script", "mobile: batteryInfo", "args", Collections.emptyList())).getValue()); + return new AndroidBatteryInfo(CommandExecutionHelper.executeScript(this, "mobile: batteryInfo")); } @Override diff --git a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java index 8f9cf1b38..8d16bf7de 100644 --- a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java +++ b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java @@ -16,18 +16,16 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.remote.RemoteWebDriver; import java.net.URI; import java.net.URISyntaxException; -import java.util.Collections; import java.util.function.Consumer; import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; public interface ListensToLogcatMessages extends ExecutesMethod { StringWebSocketClient getLogcatClient(); @@ -58,8 +56,7 @@ default void startLogcatBroadcast(String host) { * @param port the port of the host where Appium server is running */ default void startLogcatBroadcast(String host, int port) { - execute(EXECUTE_SCRIPT, ImmutableMap.of("script", "mobile: startLogsBroadcast", - "args", Collections.emptyList())); + CommandExecutionHelper.executeScript(this, "mobile: startLogsBroadcast"); final URI endpointUri; try { endpointUri = new URI(String.format("ws://%s:%s/ws/session/%s/appium/device/logcat", @@ -132,7 +129,6 @@ default void removeAllLogcatListeners() { */ default void stopLogcatBroadcast() { removeAllLogcatListeners(); - execute(EXECUTE_SCRIPT, ImmutableMap.of("script", "mobile: stopLogsBroadcast", - "args", Collections.emptyList())); + CommandExecutionHelper.executeScript(this, "mobile: stopLogsBroadcast"); } } diff --git a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java index 7f76340a3..f77bf7d3a 100644 --- a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java +++ b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java @@ -16,9 +16,14 @@ package io.appium.java_client.android.connection; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand; @@ -31,8 +36,21 @@ public interface HasNetworkConnection extends ExecutesMethod { * @return Connection object, which represents the resulting state */ default ConnectionState setConnection(ConnectionState connection) { - return new ConnectionState(CommandExecutionHelper.execute(this, - setConnectionCommand(connection.getBitMask()))); + try { + CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + "wifi", connection.isWiFiEnabled(), + "data", connection.isDataEnabled(), + "airplaneMode", connection.isAirplaneModeEnabled() + )); + return getConnection(); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return new ConnectionState( + checkNotNull( + CommandExecutionHelper.execute(this, setConnectionCommand(connection.getBitMask())) + ) + ); + } } /** @@ -41,6 +59,22 @@ default ConnectionState setConnection(ConnectionState connection) { * @return Connection object, which lets you to inspect the current status */ default ConnectionState getConnection() { - return new ConnectionState(CommandExecutionHelper.execute(this, getNetworkConnectionCommand())); + try { + Map result = checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + ); + return new ConnectionState( + ((boolean) result.get("wifi") ? ConnectionState.WIFI_MASK : 0) + | ((boolean) result.get("data") ? ConnectionState.DATA_MASK : 0) + | ((boolean) result.get("airplaneMode") ? ConnectionState.AIRPLANE_MODE_MASK : 0) + ); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return new ConnectionState( + checkNotNull( + CommandExecutionHelper.execute(this, getNetworkConnectionCommand()) + ) + ); + } } } 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 ad00a5f90..2b735d649 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -16,9 +16,9 @@ package io.appium.java_client.ios; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.AppiumDriver; +import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.HasAppStrings; import io.appium.java_client.HasDeviceTime; import io.appium.java_client.HasOnScreenKeyboard; @@ -50,11 +50,8 @@ import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; -import java.util.Collections; -import java.util.Map; import static io.appium.java_client.MobileCommand.prepareArguments; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; /** * iOS driver implementation. @@ -247,11 +244,9 @@ public IOSDriver(Capabilities capabilities) { return new InnerTargetLocator(); } - @SuppressWarnings("unchecked") @Override public IOSBatteryInfo getBatteryInfo() { - return new IOSBatteryInfo((Map) execute(EXECUTE_SCRIPT, ImmutableMap.of( - "script", "mobile: batteryInfo", "args", Collections.emptyList())).getValue()); + return new IOSBatteryInfo(CommandExecutionHelper.executeScript(this, "mobile: batteryInfo")); } private class InnerTargetLocator extends RemoteTargetLocator { diff --git a/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java b/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java index 3341f753d..ef0bd3f9d 100644 --- a/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java +++ b/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java @@ -16,18 +16,16 @@ package io.appium.java_client.ios; -import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.ws.StringWebSocketClient; import org.openqa.selenium.remote.RemoteWebDriver; import java.net.URI; import java.net.URISyntaxException; -import java.util.Collections; import java.util.function.Consumer; import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; -import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; public interface ListensToSyslogMessages extends ExecutesMethod { @@ -59,8 +57,7 @@ default void startSyslogBroadcast(String host) { * @param port the port of the host where Appium server is running */ default void startSyslogBroadcast(String host, int port) { - execute(EXECUTE_SCRIPT, ImmutableMap.of("script", "mobile: startLogsBroadcast", - "args", Collections.emptyList())); + CommandExecutionHelper.executeScript(this, "mobile: startLogsBroadcast"); final URI endpointUri; try { endpointUri = new URI(String.format("ws://%s:%s/ws/session/%s/appium/device/syslog", @@ -132,7 +129,6 @@ default void removeAllSyslogListeners() { * Stops syslog messages broadcast via web socket. */ default void stopSyslogBroadcast() { - execute(EXECUTE_SCRIPT, ImmutableMap.of("script", "mobile: stopLogsBroadcast", - "args", Collections.emptyList())); + CommandExecutionHelper.executeScript(this, "mobile: stopLogsBroadcast"); } } From 1c0cf78fa995d8153709c991ebdbad0f1e01dc7c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 21 Apr 2023 12:10:55 +0200 Subject: [PATCH 198/501] refactor: Finish replacing iOS extensions with their mobile alternatives (#1892) --- .../io/appium/java_client/LocksDevice.java | 33 +++++++++++++++++-- .../io/appium/java_client/MobileCommand.java | 23 ++++++++++++- .../ios/IOSMobileCommandHelper.java | 11 +++++-- .../java_client/ios/PerformsTouchID.java | 22 +++++++------ .../appium/java_client/ios/ShakesDevice.java | 10 ++++-- 5 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/appium/java_client/LocksDevice.java b/src/main/java/io/appium/java_client/LocksDevice.java index ce4d794c8..6f3033e05 100644 --- a/src/main/java/io/appium/java_client/LocksDevice.java +++ b/src/main/java/io/appium/java_client/LocksDevice.java @@ -16,8 +16,12 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.UnsupportedCommandException; + import java.time.Duration; +import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.getIsDeviceLockedCommand; import static io.appium.java_client.MobileCommand.lockDeviceCommand; import static io.appium.java_client.MobileCommand.unlockDeviceCommand; @@ -41,7 +45,14 @@ default void lockDevice() { * A negative/zero value will lock the device and return immediately. */ default void lockDevice(Duration duration) { - CommandExecutionHelper.execute(this, lockDeviceCommand(duration)); + try { + CommandExecutionHelper.executeScript(this, "mobile: lock", ImmutableMap.of( + "seconds", duration.getSeconds() + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, lockDeviceCommand(duration)); + } } /** @@ -49,7 +60,16 @@ default void lockDevice(Duration duration) { * is not locked. */ default void unlockDevice() { - CommandExecutionHelper.execute(this, unlockDeviceCommand()); + try { + //noinspection ConstantConditions + if (!(Boolean) CommandExecutionHelper.executeScript(this, "mobile: isLocked")) { + return; + } + CommandExecutionHelper.executeScript(this, "mobile: unlock"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, unlockDeviceCommand()); + } } /** @@ -58,6 +78,13 @@ default void unlockDevice() { * @return true if the device is locked or false otherwise. */ default boolean isDeviceLocked() { - return CommandExecutionHelper.execute(this, getIsDeviceLockedCommand()); + try { + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: isLocked") + ); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return checkNotNull(CommandExecutionHelper.execute(this, getIsDeviceLockedCommand())); + } } } diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index dbcab47b2..8c2f4f350 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -35,7 +35,6 @@ /** * The repository of mobile commands defined in the Mobile JSON * wire protocol. - * * Most of these commands are platform-specific obsolete things and should eventually be replaced with * calls to corresponding `mobile:` extensions, so we don't abuse non-w3c APIs */ @@ -383,7 +382,9 @@ public static AppiumCommandInfo deleteC(String url) { * @param keyName The button pressed by the mobile driver to attempt hiding the * keyboard. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> hideKeyboardCommand(String keyName) { return new AbstractMap.SimpleEntry<>( HIDE_KEYBOARD, prepareArguments("keyName", keyName)); @@ -396,7 +397,9 @@ public static AppiumCommandInfo deleteC(String url) { * @param keyName a String, representing the text displayed on the button of the * keyboard you want to press. For example: "Done". * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> hideKeyboardCommand(String strategy, String keyName) { String[] parameters = new String[]{"strategy", "key"}; @@ -442,7 +445,9 @@ public static ImmutableMap prepareArguments(String[] params, * * @param key code for the key pressed on the device. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> pressKeyCodeCommand(int key) { return new AbstractMap.SimpleEntry<>( PRESS_KEY_CODE, prepareArguments("keycode", key)); @@ -454,7 +459,9 @@ public static ImmutableMap prepareArguments(String[] params, * @param key code for the key pressed on the Android device. * @param metastate metastate for the keypress. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> pressKeyCodeCommand(int key, Integer metastate) { String[] parameters = new String[]{"keycode", "metastate"}; @@ -468,7 +475,9 @@ public static ImmutableMap prepareArguments(String[] params, * * @param key code for the long key pressed on the device. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> longPressKeyCodeCommand(int key) { return new AbstractMap.SimpleEntry<>( LONG_PRESS_KEY_CODE, prepareArguments("keycode", key)); @@ -480,7 +489,9 @@ public static ImmutableMap prepareArguments(String[] params, * @param key code for the long key pressed on the Android device. * @param metastate metastate for the long key press. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> longPressKeyCodeCommand(int key, Integer metastate) { String[] parameters = new String[]{"keycode", "metastate"}; @@ -494,7 +505,9 @@ public static ImmutableMap prepareArguments(String[] params, * * @param duration for how long to lock the screen for. Minimum time resolution is one second * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> lockDeviceCommand(Duration duration) { return new AbstractMap.SimpleEntry<>( LOCK, prepareArguments("seconds", duration.getSeconds())); @@ -504,7 +517,9 @@ public static ImmutableMap prepareArguments(String[] params, * This method forms a {@link Map} of parameters for the device unlocking. * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> unlockDeviceCommand() { return new AbstractMap.SimpleEntry<>(UNLOCK, ImmutableMap.of()); } @@ -513,7 +528,9 @@ public static ImmutableMap prepareArguments(String[] params, * This method forms a {@link Map} of parameters for the device locked query. * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> getIsDeviceLockedCommand() { return new AbstractMap.SimpleEntry<>(IS_LOCKED, ImmutableMap.of()); } @@ -536,7 +553,9 @@ public static ImmutableMap prepareArguments(String[] params, * @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 * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> pushFileCommand(String remotePath, byte[] base64Data) { String[] parameters = new String[]{"path", "data"}; Object[] values = new Object[]{remotePath, new String(base64Data, StandardCharsets.UTF_8)}; @@ -580,7 +599,9 @@ public static ImmutableMap prepareArguments(String[] params, * This method forms a {@link Map} of parameters for the checking of the keyboard state (is it shown or not). * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated This helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> isKeyboardShownCommand() { return new AbstractMap.SimpleEntry<>(IS_KEYBOARD_SHOWN, ImmutableMap.of()); } 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 8e61cb5cf..390079d19 100644 --- a/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java @@ -22,23 +22,28 @@ import java.util.AbstractMap; import java.util.Map; +@Deprecated public class IOSMobileCommandHelper extends MobileCommand { /** * This method forms a {@link Map} of parameters for the device shaking. * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated this helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> shakeCommand() { return new AbstractMap.SimpleEntry<>(SHAKE, ImmutableMap.of()); } - + /** * This method forms a {@link Map} of parameters for the touchId simulator. - * + * * @param match If true, simulates a successful fingerprint scan. If false, simulates a failed fingerprint scan. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated this helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> touchIdCommand(boolean match) { return new AbstractMap.SimpleEntry<>( TOUCH_ID, prepareArguments("match", match)); @@ -50,7 +55,9 @@ public class IOSMobileCommandHelper extends MobileCommand { * * @param enabled Whether to enable or disable Touch ID Enrollment for Simulator. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. + * @deprecated this helper is deprecated and will be removed in future versions. */ + @Deprecated public static Map.Entry> toggleTouchIdEnrollmentCommand(boolean enabled) { return new AbstractMap.SimpleEntry<>( TOUCH_ID_ENROLLMENT, prepareArguments("enabled", enabled)); diff --git a/src/main/java/io/appium/java_client/ios/PerformsTouchID.java b/src/main/java/io/appium/java_client/ios/PerformsTouchID.java index 907a86655..af574bd2f 100644 --- a/src/main/java/io/appium/java_client/ios/PerformsTouchID.java +++ b/src/main/java/io/appium/java_client/ios/PerformsTouchID.java @@ -16,34 +16,36 @@ package io.appium.java_client.ios; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; -import static io.appium.java_client.ios.IOSMobileCommandHelper.toggleTouchIdEnrollmentCommand; -import static io.appium.java_client.ios.IOSMobileCommandHelper.touchIdCommand; - public interface PerformsTouchID extends ExecutesMethod { /** - * Simulate touchId event. + * Simulate touchId event on iOS Simulator. Check the documentation on 'mobile: sendBiometricMatch' + * extension for more details. * * @param match If true, simulates a successful fingerprint scan. If false, simulates a failed fingerprint scan. */ default void performTouchID(boolean match) { - CommandExecutionHelper.execute(this, touchIdCommand(match)); + CommandExecutionHelper.executeScript(this, "mobile: sendBiometricMatch", ImmutableMap.of( + "type", "touchId", + "match", match + )); } /** - * Enrolls touchId in iOS Simulators. This call will only work if Appium process or its - * parent application (e.g. Terminal.app or Appium.app) has - * access to Mac OS accessibility in System Preferences > - * Security & Privacy > Privacy > Accessibility list. + * Enrolls touchId in iOS Simulator. Check the documentation on 'mobile: enrollBiometric' + * extension for more details. * * @param enabled Whether to enable or disable Touch ID Enrollment. The actual state of the feature * will only be changed if the current value is different from the previous one. * Multiple calls of the method with the same argument value have no effect. */ default void toggleTouchIDEnrollment(boolean enabled) { - CommandExecutionHelper.execute(this, toggleTouchIdEnrollmentCommand(enabled)); + CommandExecutionHelper.executeScript(this, "mobile: enrollBiometric", ImmutableMap.of( + "isEnabled", enabled + )); } } diff --git a/src/main/java/io/appium/java_client/ios/ShakesDevice.java b/src/main/java/io/appium/java_client/ios/ShakesDevice.java index abd601852..1f34ecbfa 100644 --- a/src/main/java/io/appium/java_client/ios/ShakesDevice.java +++ b/src/main/java/io/appium/java_client/ios/ShakesDevice.java @@ -18,15 +18,21 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; import static io.appium.java_client.ios.IOSMobileCommandHelper.shakeCommand; public interface ShakesDevice extends ExecutesMethod { /** - * Simulate shaking the device. + * Simulate shaking the Simulator. This API does not work for real devices. */ default void shake() { - CommandExecutionHelper.execute(this, shakeCommand()); + try { + CommandExecutionHelper.executeScript(this, "mobile: shake"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, shakeCommand()); + } } } From 99445bf9b169839014298aa48c976ee943f0b528 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 23 Apr 2023 20:09:45 +0200 Subject: [PATCH 199/501] refactor: Change some Android APIs to use mobile extensions (#1893) --- .../java_client/android/StartsActivity.java | 11 +++-- .../SupportsNetworkStateManagement.java | 48 ++++++++++++++++--- .../android/nativekey/PressesKey.java | 25 ++++++++-- 3 files changed, 70 insertions(+), 14 deletions(-) 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 ea4c04ce5..f01d50998 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -40,13 +40,16 @@ public interface StartsActivity extends ExecutesMethod { * * * @param activity The {@link Activity} object + * @deprecated Use 'mobile: startActivity' extension instead */ + @Deprecated default void startActivity(Activity activity) { CommandExecutionHelper.execute(this, - startActivityCommand(activity.getAppPackage(), activity.getAppActivity(), - activity.getAppWaitPackage(), activity.getAppWaitActivity(), - activity.getIntentAction(), activity.getIntentCategory(), activity.getIntentFlags(), - activity.getOptionalIntentArguments(), activity.isStopApp())); + startActivityCommand(activity.getAppPackage(), activity.getAppActivity(), + activity.getAppWaitPackage(), activity.getAppWaitActivity(), + activity.getIntentAction(), activity.getIntentCategory(), activity.getIntentFlags(), + activity.getOptionalIntentArguments(), activity.isStopApp()) + ); } /** diff --git a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java index 9100fbb69..9fdbd23c9 100644 --- a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java +++ b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java @@ -1,8 +1,13 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleAirplaneCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleDataCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleWifiCommand; @@ -13,21 +18,52 @@ public interface SupportsNetworkStateManagement extends ExecutesMethod { * Toggles Wifi on and off. */ default void toggleWifi() { - CommandExecutionHelper.execute(this, toggleWifiCommand()); + try { + Map result = checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + ); + CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + "wifi", !((Boolean) result.get("wifi")) + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, toggleWifiCommand()); + } } /** - * Toggle Airplane mode and this works on OS 6.0 and lesser - * and does not work on OS 7.0 and greater + * Toggle Airplane mode and this works on Android versions below + * 6 and above 10. */ default void toggleAirplaneMode() { - CommandExecutionHelper.execute(this, toggleAirplaneCommand()); + try { + Map result = checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + ); + CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + "airplaneMode", !((Boolean) result.get("airplaneMode")) + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, toggleAirplaneCommand()); + } } /** - * Toggle Mobile Data and this works on Emulator and rooted device. + * Toggle Mobile Data and this works on Emulators and real devices + * running Android version above 10. */ default void toggleData() { - CommandExecutionHelper.execute(this, toggleDataCommand()); + try { + Map result = checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + ); + CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + "data", !((Boolean) result.get("data")) + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, toggleDataCommand()); + } } } diff --git a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java index 6c9f36212..9584ff517 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java +++ b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java @@ -16,10 +16,13 @@ package io.appium.java_client.android.nativekey; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; import java.util.AbstractMap; +import java.util.Map; import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE; import static io.appium.java_client.MobileCommand.PRESS_KEY_CODE; @@ -32,8 +35,13 @@ public interface PressesKey extends ExecutesMethod { * @param keyEvent The generated native key event */ default void pressKey(KeyEvent keyEvent) { - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(PRESS_KEY_CODE, keyEvent.build())); + try { + CommandExecutionHelper.executeScript(this, "mobile: pressKey", keyEvent.build()); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(PRESS_KEY_CODE, keyEvent.build())); + } } /** @@ -42,7 +50,16 @@ default void pressKey(KeyEvent keyEvent) { * @param keyEvent The generated native key event */ default void longPressKey(KeyEvent keyEvent) { - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(LONG_PRESS_KEY_CODE, keyEvent.build())); + try { + Map args = ImmutableMap.builder() + .putAll(keyEvent.build()) + .put("isLongPress", true) + .build(); + CommandExecutionHelper.executeScript(this, "mobile: pressKey", args); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(LONG_PRESS_KEY_CODE, keyEvent.build())); + } } } From c6fcd2ae98d8e9af7ca099f1c6b1b7543755fe81 Mon Sep 17 00:00:00 2001 From: wazzeps <120301053+wazzeps@users.noreply.github.com> Date: Mon, 24 Apr 2023 21:31:11 +0200 Subject: [PATCH 200/501] feat: Add SupportsEnforceAppInstallOption to XCUITestOptions (#1895) --- .../java_client/android/options/EspressoOptions.java | 2 +- .../java_client/android/options/UiAutomator2Options.java | 2 +- .../appium/java_client/ios/options/XCUITestOptions.java | 2 ++ .../java_client/remote/IOSMobileCapabilityType.java | 9 +++++++++ .../options}/SupportsEnforceAppInstallOption.java | 6 ++---- 5 files changed, 15 insertions(+), 6 deletions(-) rename src/main/java/io/appium/java_client/{android/options/app => remote/options}/SupportsEnforceAppInstallOption.java (91%) diff --git a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java index c081be4f9..8cbe2cf33 100644 --- a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java +++ b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java @@ -37,7 +37,6 @@ import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption; import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption; import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption; -import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption; import io.appium.java_client.android.options.app.SupportsIntentOptionsOption; import io.appium.java_client.android.options.app.SupportsRemoteAppsCacheLimitOption; import io.appium.java_client.android.options.app.SupportsUninstallOtherPackagesOption; @@ -89,6 +88,7 @@ import io.appium.java_client.remote.options.SupportsAppOption; import io.appium.java_client.remote.options.SupportsAutoWebViewOption; import io.appium.java_client.remote.options.SupportsDeviceNameOption; +import io.appium.java_client.remote.options.SupportsEnforceAppInstallOption; import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.remote.options.SupportsLanguageOption; import io.appium.java_client.remote.options.SupportsLocaleOption; diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index adc161950..3c6a7bc51 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -37,7 +37,6 @@ import io.appium.java_client.android.options.app.SupportsAppWaitForLaunchOption; import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption; import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption; -import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption; import io.appium.java_client.android.options.app.SupportsIntentActionOption; import io.appium.java_client.android.options.app.SupportsIntentCategoryOption; import io.appium.java_client.android.options.app.SupportsIntentFlagsOption; @@ -95,6 +94,7 @@ import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; import io.appium.java_client.remote.options.SupportsDeviceNameOption; import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsEnforceAppInstallOption; import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.remote.options.SupportsLanguageOption; import io.appium.java_client.remote.options.SupportsLocaleOption; diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index 2eb61386d..53465b4dd 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -106,6 +106,7 @@ import io.appium.java_client.remote.options.SupportsClearSystemFilesOption; import io.appium.java_client.remote.options.SupportsDeviceNameOption; import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption; +import io.appium.java_client.remote.options.SupportsEnforceAppInstallOption; import io.appium.java_client.remote.options.SupportsIsHeadlessOption; import io.appium.java_client.remote.options.SupportsLanguageOption; import io.appium.java_client.remote.options.SupportsLocaleOption; @@ -136,6 +137,7 @@ public class XCUITestOptions extends BaseOptions implements SupportsOtherAppsOption, SupportsAppPushTimeoutOption, SupportsAppInstallStrategyOption, + SupportsEnforceAppInstallOption, // WebDriverAgent options: https://github.com/appium/appium-xcuitest-driver#webdriveragent SupportsXcodeCertificateOptions, SupportsKeychainOptions, diff --git a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java index b23150244..046dd4952 100644 --- a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java @@ -302,6 +302,15 @@ public interface IOSMobileCapabilityType extends CapabilityType { */ String UPDATE_WDA_BUNDLEID = "updatedWDABundleId"; + /** + * By default application installation is not skipped if newer or the same version of this app is already present on + * the device under test. Setting this option to {@code false} will enforce Appium to always skip the current + * application build. Defaults to {@code true}. + * + * @since 4.19.0 + */ + String ENFORCE_APP_INSTALL = "enforceAppInstall"; + /** * Whether to perform reset on test session finish (false) or not (true). * Keeping this variable set to true and Simulator running diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsEnforceAppInstallOption.java similarity index 91% rename from src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java rename to src/main/java/io/appium/java_client/remote/options/SupportsEnforceAppInstallOption.java index 3acc25875..5e343938c 100644 --- a/src/main/java/io/appium/java_client/android/options/app/SupportsEnforceAppInstallOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsEnforceAppInstallOption.java @@ -14,10 +14,8 @@ * limitations under the License. */ -package io.appium.java_client.android.options.app; +package io.appium.java_client.remote.options; -import io.appium.java_client.remote.options.BaseOptions; -import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; import java.util.Optional; @@ -40,7 +38,7 @@ default T enforceAppInstall() { /** * Allows setting whether the application under test is always reinstalled even - * if a newer version of it already exists on the device under test. false by default. + * if a newer version of it already exists on the device under test. False (Android), true (iOS) by default. * * @param value True to allow test packages installation. * @return self instance for chaining. From ec812f244a13279771421afc4a695b8a15b87865 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 26 Apr 2023 11:10:47 +0200 Subject: [PATCH 201/501] refactor: Change backgroundApp command to use the corresponding mobile extension (#1896) --- .../io/appium/java_client/InteractsWithApps.java | 16 ++++++++++++---- .../io/appium/java_client/MobileCommand.java | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index fedf957c8..0793cd79f 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -23,6 +23,7 @@ import io.appium.java_client.appmanagement.BaseOptions; import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; +import org.openqa.selenium.UnsupportedCommandException; import javax.annotation.Nullable; import java.time.Duration; @@ -76,15 +77,22 @@ default boolean isAppInstalled(String bundleId) { } /** - * Runs the current app as a background app for the time + * Runs the current app in the background for the time * requested. This is a synchronous method, it blocks while the * application is in background. * - * @param duration The time to run App in background. Minimum time resolution is one millisecond. - * Passing zero or a negative value will switch to Home screen and return immediately. + * @param duration The time to run App in background. Minimum time resolution unit is one millisecond. + * Passing a negative value will switch to Home screen and return immediately. */ default void runAppInBackground(Duration duration) { - execute(RUN_APP_IN_BACKGROUND, ImmutableMap.of("seconds", duration.toMillis() / 1000.0)); + try { + CommandExecutionHelper.executeScript(this, "mobile: backgroundApp", ImmutableMap.of( + "seconds", duration.toMillis() / 1000.0 + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + execute(RUN_APP_IN_BACKGROUND, ImmutableMap.of("seconds", duration.toMillis() / 1000.0)); + } } /** diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 8c2f4f350..5b2a6587d 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -50,6 +50,7 @@ public class MobileCommand { protected static final String PULL_FILE; @Deprecated protected static final String PULL_FOLDER; + @Deprecated public static final String RUN_APP_IN_BACKGROUND; @Deprecated protected static final String PERFORM_TOUCH_ACTION; From 6a4adb7bc70e538c459b3202ee33b2638b24f573 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 26 Apr 2023 14:49:48 +0200 Subject: [PATCH 202/501] fix: Send arguments for mobile methods depending on the target platform (#1897) --- .../appium/java_client/InteractsWithApps.java | 165 +++++++++++++----- 1 file changed, 125 insertions(+), 40 deletions(-) diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index 0793cd79f..da39a0ded 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -23,18 +23,26 @@ import io.appium.java_client.appmanagement.BaseOptions; import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; +import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.UnsupportedCommandException; import javax.annotation.Nullable; import java.time.Duration; -import java.util.HashMap; +import java.util.AbstractMap; +import java.util.Collections; import java.util.Map; import java.util.Optional; import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.MobileCommand.ACTIVATE_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.QUERY_APP_STATE; +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.TERMINATE_APP; -@SuppressWarnings("rawtypes") +@SuppressWarnings({"rawtypes", "unchecked"}) public interface InteractsWithApps extends ExecutesMethod { /** @@ -54,11 +62,23 @@ default void installApp(String appPath) { * the particular platform. */ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) { - Map args = new HashMap<>(); - args.put("app", appPath); - args.put("appPath", appPath); - Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); - CommandExecutionHelper.executeScript(this, "mobile: installApp", args); + try { + Map args = ImmutableMap.builder() + .put("app", appPath) + .put("appPath", appPath) + .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) + .build(); + CommandExecutionHelper.executeScript(this, "mobile: installApp", args); + } catch (UnsupportedCommandException | InvalidArgumentException e) { + // TODO: Remove the fallback + Map args = ImmutableMap.builder() + .put("appPath", appPath) + .putAll(Optional.ofNullable(options).map( + (opts) -> ImmutableMap.of("options", opts.build()) + ).orElseGet(ImmutableMap::of)) + .build(); + CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(INSTALL_APP, args)); + } } /** @@ -68,12 +88,21 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions * @return True if app is installed, false otherwise. */ default boolean isAppInstalled(String bundleId) { - return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: isAppInstalled", ImmutableMap.of( - "bundleId", bundleId, - "appId", bundleId - )) - ); + try { + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: isAppInstalled", ImmutableMap.of( + "bundleId", bundleId, + "appId", bundleId + )) + ); + } catch (UnsupportedCommandException | InvalidArgumentException e) { + // TODO: Remove the fallback + return checkNotNull( + CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, ImmutableMap.of("bundleId", bundleId)) + ) + ); + } } /** @@ -114,13 +143,30 @@ default boolean removeApp(String bundleId) { * @return true if the uninstall was successful. */ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOptions options) { - Map args = new HashMap<>(); - args.put("bundleId", bundleId); - args.put("appId", bundleId); - Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); - return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: removeApp", args) - ); + try { + Map args = ImmutableMap.builder() + .put("bundleId", bundleId) + .put("appId", bundleId) + .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) + .build(); + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: removeApp", args) + ); + } catch (UnsupportedCommandException | InvalidArgumentException e) { + // TODO: Remove the fallback + Map args = ImmutableMap.builder() + .put("bundleId", bundleId) + .putAll(Optional.ofNullable(options).map( + (opts) -> ImmutableMap.of("options", opts.build()) + ).orElseGet(ImmutableMap::of)) + .build(); + //noinspection RedundantCast + return checkNotNull( + (Boolean) CommandExecutionHelper.execute( + this, new AbstractMap.SimpleEntry<>(REMOVE_APP, args) + ) + ); + } } /** @@ -142,11 +188,23 @@ default void activateApp(String bundleId) { * particular platform. */ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptions options) { - Map args = new HashMap<>(); - args.put("bundleId", bundleId); - args.put("appId", bundleId); - Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); - CommandExecutionHelper.executeScript(this, "mobile: activateApp", args); + try { + Map args = ImmutableMap.builder() + .put("bundleId", bundleId) + .put("appId", bundleId) + .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) + .build(); + CommandExecutionHelper.executeScript(this, "mobile: activateApp", args); + } catch (UnsupportedCommandException | InvalidArgumentException e) { + // TODO: Remove the fallback + Map args = ImmutableMap.builder() + .put("bundleId", bundleId) + .putAll(Optional.ofNullable(options).map( + (opts) -> ImmutableMap.of("options", opts.build()) + ).orElseGet(ImmutableMap::of)) + .build(); + CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(ACTIVATE_APP, args)); + } } /** @@ -156,14 +214,24 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio * @return one of possible {@link ApplicationState} values, */ default ApplicationState queryAppState(String bundleId) { - return ApplicationState.ofCode( - checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: queryAppState", ImmutableMap.of( - "bundleId", bundleId, - "appId", bundleId - )) - ) - ); + try { + return ApplicationState.ofCode( + checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: queryAppState", ImmutableMap.of( + "bundleId", bundleId, + "appId", bundleId + )) + ) + ); + } catch (UnsupportedCommandException | InvalidArgumentException e) { + // TODO: Remove the fallback + return ApplicationState.ofCode( + checkNotNull( + CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(QUERY_APP_STATE, ImmutableMap.of("bundleId", bundleId))) + ) + ); + } } /** @@ -185,12 +253,29 @@ default boolean terminateApp(String bundleId) { * @return true if the app was running before and has been successfully stopped. */ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplicationOptions options) { - Map args = new HashMap<>(); - args.put("bundleId", bundleId); - args.put("appId", bundleId); - Optional.ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); - return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: terminateApp", args) - ); + try { + Map args = ImmutableMap.builder() + .put("bundleId", bundleId) + .put("appId", bundleId) + .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) + .build(); + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: terminateApp", args) + ); + } catch (UnsupportedCommandException | InvalidArgumentException e) { + // TODO: Remove the fallback + Map args = ImmutableMap.builder() + .put("bundleId", bundleId) + .putAll(Optional.ofNullable(options).map( + (opts) -> ImmutableMap.of("options", opts.build()) + ).orElseGet(ImmutableMap::of)) + .build(); + //noinspection RedundantCast + return checkNotNull( + (Boolean) CommandExecutionHelper.execute( + this, new AbstractMap.SimpleEntry<>(TERMINATE_APP, args) + ) + ); + } } } From d163f8d2bd231a0ccca0ec80c28be197fbdc4674 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 29 Apr 2023 09:12:03 +0200 Subject: [PATCH 203/501] feat: Switch more Android helpers to use extensions (#1898) --- .../io/appium/java_client/MobileCommand.java | 18 ++-- .../java_client/android/AndroidDriver.java | 2 + .../android/AndroidMobileCommandHelper.java | 24 +++++ .../android/AuthenticatesByFinger.java | 11 +- .../android/CanReplaceElementValue.java | 26 +++-- .../android/HasAndroidDeviceDetails.java | 15 ++- .../java_client/android/StartsActivity.java | 30 +++++- .../SupportsSpecialEmulatorCommands.java | 102 +++++++++++++++--- .../android/AndroidDriverTest.java | 5 - 9 files changed, 190 insertions(+), 43 deletions(-) diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 5b2a6587d..721c854a7 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -112,7 +112,7 @@ public class MobileCommand { protected static final String TOUCH_ID_ENROLLMENT; //Android @Deprecated - protected static final String CURRENT_ACTIVITY; + public static final String CURRENT_ACTIVITY; @Deprecated protected static final String END_TEST_COVERAGE; @Deprecated @@ -149,21 +149,21 @@ public class MobileCommand { @Deprecated protected static final String SET_SETTINGS; @Deprecated - protected static final String GET_CURRENT_PACKAGE; + public static final String GET_CURRENT_PACKAGE; @Deprecated - protected static final String SEND_SMS; + public static final String SEND_SMS; @Deprecated - protected static final String GSM_CALL; + public static final String GSM_CALL; @Deprecated - protected static final String GSM_SIGNAL; + public static final String GSM_SIGNAL; @Deprecated - protected static final String GSM_VOICE; + public static final String GSM_VOICE; @Deprecated - protected static final String NETWORK_SPEED; + public static final String NETWORK_SPEED; @Deprecated - protected static final String POWER_CAPACITY; + public static final String POWER_CAPACITY; @Deprecated - protected static final String POWER_AC_STATE; + public static final String POWER_AC_STATE; @Deprecated protected static final String TOGGLE_WIFI; @Deprecated 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 c7290882b..9606be761 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -255,7 +255,9 @@ public AndroidDriver(URL remoteSessionAddress, String automationName) { * * @param intent intent to broadcast. * @param path path to .ec file. + * @deprecated This API will be removed */ + @Deprecated public void endTestCoverage(String intent, String path) { CommandExecutionHelper.execute(this, endTestCoverageCommand(intent, path)); } 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 6b46ce945..1bed116d7 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -37,6 +37,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> currentActivityCommand() { return new AbstractMap.SimpleEntry<>(CURRENT_ACTIVITY, ImmutableMap.of()); } @@ -46,6 +47,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> currentPackageCommand() { return new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()); } @@ -57,6 +59,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * @param path path to .ec file. * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> endTestCoverageCommand(String intent, String path) { String[] parameters = new String[] {"intent", "path"}; @@ -117,6 +120,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> getDisplayDensityCommand() { return new AbstractMap.SimpleEntry<>(GET_DISPLAY_DENSITY, ImmutableMap.of()); } @@ -126,6 +130,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> getNetworkConnectionCommand() { return new AbstractMap.SimpleEntry<>(GET_NETWORK_CONNECTION, ImmutableMap.of()); } @@ -136,6 +141,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> getSystemBarsCommand() { return new AbstractMap.SimpleEntry<>(GET_SYSTEM_BARS, ImmutableMap.of()); } @@ -145,6 +151,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> isLockedCommand() { return new AbstractMap.SimpleEntry<>(IS_LOCKED, ImmutableMap.of()); } @@ -155,6 +162,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10) * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> fingerPrintCommand(int fingerPrintId) { return new AbstractMap.SimpleEntry<>(FINGER_PRINT, prepareArguments("fingerprintId", fingerPrintId)); @@ -165,6 +173,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> openNotificationsCommand() { return new AbstractMap.SimpleEntry<>(OPEN_NOTIFICATIONS, ImmutableMap.of()); } @@ -175,6 +184,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * @param bitMask The bitmask of the desired connection * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> setConnectionCommand(long bitMask) { String[] parameters = new String[] {"name", "parameters"}; Object[] values = new Object[] {"network_connection", ImmutableMap.of("type", bitMask)}; @@ -198,6 +208,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. * @throws IllegalArgumentException when any required argument is empty */ + @Deprecated public static Map.Entry> startActivityCommand(String appPackage, String appActivity, String appWaitPackage, String appWaitActivity, String intentAction, String intentCategory, String intentFlags, @@ -234,6 +245,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> toggleLocationServicesCommand() { return new AbstractMap.SimpleEntry<>(TOGGLE_LOCATION_SERVICES, ImmutableMap.of()); } @@ -243,6 +255,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> unlockCommand() { return new AbstractMap.SimpleEntry<>(UNLOCK, ImmutableMap.of()); } @@ -256,6 +269,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * @param value a new value * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> replaceElementValueCommand( RemoteWebElement remoteWebElement, String value) { String[] parameters = new String[] {"id", "value"}; @@ -275,6 +289,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> sendSMSCommand( String phoneNumber, String message) { ImmutableMap parameters = ImmutableMap @@ -294,6 +309,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> gsmCallCommand( String phoneNumber, GsmCallActions gsmCallActions) { String[] parameters = new String[] {"phoneNumber", "action"}; @@ -309,6 +325,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> gsmSignalStrengthCommand( GsmSignalStrength gsmSignalStrength) { return new AbstractMap.SimpleEntry<>(GSM_SIGNAL, @@ -327,6 +344,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> gsmVoiceCommand( GsmVoiceState gsmVoiceState) { return new AbstractMap.SimpleEntry<>(GSM_VOICE, @@ -341,6 +359,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> networkSpeedCommand( NetworkSpeed networkSpeed) { return new AbstractMap.SimpleEntry<>(NETWORK_SPEED, @@ -355,6 +374,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> powerCapacityCommand( int percent) { return new AbstractMap.SimpleEntry<>(POWER_CAPACITY, @@ -369,6 +389,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> powerACCommand( PowerACState powerACState) { return new AbstractMap.SimpleEntry<>(POWER_AC_STATE, @@ -380,6 +401,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> toggleWifiCommand() { return new AbstractMap.SimpleEntry<>(TOGGLE_WIFI, ImmutableMap.of()); } @@ -389,6 +411,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> toggleAirplaneCommand() { return new AbstractMap.SimpleEntry<>(TOGGLE_AIRPLANE_MODE, ImmutableMap.of()); } @@ -398,6 +421,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ + @Deprecated public static Map.Entry> toggleDataCommand() { return new AbstractMap.SimpleEntry<>(TOGGLE_DATA, ImmutableMap.of()); } diff --git a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java index 15503e239..a9ecf128f 100644 --- a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java +++ b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java @@ -1,7 +1,9 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand; @@ -13,6 +15,13 @@ public interface AuthenticatesByFinger extends ExecutesMethod { * @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10) */ default void fingerPrint(int fingerPrintId) { - CommandExecutionHelper.execute(this, fingerPrintCommand(fingerPrintId)); + try { + CommandExecutionHelper.executeScript(this, "mobile: fingerprint", ImmutableMap.of( + "fingerprintId", fingerPrintId + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, fingerPrintCommand(fingerPrintId)); + } } } diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java index 72a170f32..949e7964c 100644 --- a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -1,21 +1,35 @@ package io.appium.java_client.android; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.MobileCommand; +import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.remote.RemoteWebElement; public interface CanReplaceElementValue extends ExecutesMethod { /** - * Replaces element value with the given one. + * Sends a text to the given element by replacing its previous content. * * @param element The destination element. - * @param value The value to set. + * @param value The text to enter. It could also contain Unicode characters. + * If the text ends with `\\n` (the backslash must be escaped, so the + * char is NOT translated into `0x0A`) then the Enter key press is going to + * be emulated after it is entered (the `\\n` substring itself will be cut + * off from the typed text). */ default void replaceElementValue(RemoteWebElement element, String value) { - this.execute(MobileCommand.REPLACE_VALUE, ImmutableMap.of( - "id", element.getId(), - "value", value - )); + try { + CommandExecutionHelper.executeScript(this, "mobile: replaceValue", ImmutableMap.of( + "elementId", element.getId(), + "text", value + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(MobileCommand.REPLACE_VALUE, ImmutableMap.of( + "id", element.getId(), + "value", value + )); + } } } diff --git a/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java b/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java index 66c084480..bcdcf1fd4 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java @@ -2,6 +2,7 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; import java.util.Map; @@ -16,7 +17,12 @@ public interface HasAndroidDeviceDetails extends ExecutesMethod { @return The density value in dpi */ default Long getDisplayDensity() { - return CommandExecutionHelper.execute(this, getDisplayDensityCommand()); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getDisplayDensity"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute(this, getDisplayDensityCommand()); + } } /** @@ -25,7 +31,12 @@ default Long getDisplayDensity() { @return The map where keys are bar types and values are mappings of bar properties. */ default Map> getSystemBars() { - return CommandExecutionHelper.execute(this, getSystemBarsCommand()); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getSystemBars"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute(this, getSystemBarsCommand()); + } } } 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 f01d50998..9291e5020 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -16,11 +16,17 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; -import static io.appium.java_client.android.AndroidMobileCommandHelper.currentActivityCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.currentPackageCommand; +import javax.annotation.Nullable; + +import java.util.AbstractMap; + +import static io.appium.java_client.MobileCommand.CURRENT_ACTIVITY; +import static io.appium.java_client.MobileCommand.GET_CURRENT_PACKAGE; import static io.appium.java_client.android.AndroidMobileCommandHelper.startActivityCommand; public interface StartsActivity extends ExecutesMethod { @@ -57,8 +63,16 @@ default void startActivity(Activity activity) { * * @return a current activity being run on the mobile device. */ + @Nullable default String currentActivity() { - return CommandExecutionHelper.execute(this, currentActivityCommand()); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getCurrentActivity"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute( + this, new AbstractMap.SimpleEntry<>(CURRENT_ACTIVITY, ImmutableMap.of()) + ); + } } /** @@ -66,7 +80,15 @@ default String currentActivity() { * * @return a current package being run on the mobile device. */ + @Nullable default String getCurrentPackage() { - return CommandExecutionHelper.execute(this, currentPackageCommand()); + try { + return CommandExecutionHelper.executeScript(this, "mobile: getCurrentPackage"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute( + this, new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()) + ); + } } } diff --git a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java index 6baeef8a0..29cd6415e 100644 --- a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java +++ b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java @@ -1,15 +1,17 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; -import static io.appium.java_client.android.AndroidMobileCommandHelper.gsmCallCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.gsmSignalStrengthCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.gsmVoiceCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.networkSpeedCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.powerACCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.powerCapacityCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.sendSMSCommand; +import static io.appium.java_client.MobileCommand.GSM_CALL; +import static io.appium.java_client.MobileCommand.GSM_SIGNAL; +import static io.appium.java_client.MobileCommand.GSM_VOICE; +import static io.appium.java_client.MobileCommand.NETWORK_SPEED; +import static io.appium.java_client.MobileCommand.POWER_AC_STATE; +import static io.appium.java_client.MobileCommand.POWER_CAPACITY; +import static io.appium.java_client.MobileCommand.SEND_SMS; public interface SupportsSpecialEmulatorCommands extends ExecutesMethod { @@ -20,17 +22,39 @@ public interface SupportsSpecialEmulatorCommands extends ExecutesMethod { * @param message The message content. */ default void sendSMS(String phoneNumber, String message) { - CommandExecutionHelper.execute(this, sendSMSCommand(phoneNumber, message)); + try { + CommandExecutionHelper.executeScript(this, "mobile: sendSms", ImmutableMap.of( + "phoneNumber", phoneNumber, + "message", message + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(SEND_SMS, ImmutableMap.of( + "phoneNumber", phoneNumber, + "message", message + )); + } } /** * Emulate GSM call event on the connected emulator. * * @param phoneNumber The phone number of the caller. - * @param gsmCallActions One of available {@link GsmCallActions} values. + * @param gsmCallAction One of available {@link GsmCallActions} values. */ - default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallActions) { - CommandExecutionHelper.execute(this, gsmCallCommand(phoneNumber, gsmCallActions)); + default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { + try { + CommandExecutionHelper.executeScript(this, "mobile: gsmCall", ImmutableMap.of( + "phoneNumber", phoneNumber, + "action", gsmCallAction.toString().toLowerCase() + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(GSM_CALL, ImmutableMap.of( + "phoneNumber", phoneNumber, + "action", gsmCallAction.toString().toLowerCase() + )); + } } /** @@ -39,7 +63,17 @@ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallActions) { * @param gsmSignalStrength One of available {@link GsmSignalStrength} values. */ default void setGsmSignalStrength(GsmSignalStrength gsmSignalStrength) { - CommandExecutionHelper.execute(this, gsmSignalStrengthCommand(gsmSignalStrength)); + try { + CommandExecutionHelper.executeScript(this, "mobile: gsmSignal", ImmutableMap.of( + "strength", gsmSignalStrength.ordinal() + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(GSM_SIGNAL, ImmutableMap.of( + "signalStrengh", gsmSignalStrength.ordinal(), + "signalStrength", gsmSignalStrength.ordinal() + )); + } } /** @@ -48,7 +82,16 @@ default void setGsmSignalStrength(GsmSignalStrength gsmSignalStrength) { * @param gsmVoiceState One of available {@link GsmVoiceState} values. */ default void setGsmVoice(GsmVoiceState gsmVoiceState) { - CommandExecutionHelper.execute(this, gsmVoiceCommand(gsmVoiceState)); + try { + CommandExecutionHelper.executeScript(this, "mobile: gsmVoice", ImmutableMap.of( + "state", gsmVoiceState.toString().toLowerCase() + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(GSM_VOICE, ImmutableMap.of( + "state", gsmVoiceState.name().toLowerCase() + )); + } } /** @@ -57,7 +100,16 @@ default void setGsmVoice(GsmVoiceState gsmVoiceState) { * @param networkSpeed One of available {@link NetworkSpeed} values. */ default void setNetworkSpeed(NetworkSpeed networkSpeed) { - CommandExecutionHelper.execute(this, networkSpeedCommand(networkSpeed)); + try { + CommandExecutionHelper.executeScript(this, "mobile: networkSpeed", ImmutableMap.of( + "speed", networkSpeed.toString().toLowerCase() + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(NETWORK_SPEED, ImmutableMap.of( + "netspeed", networkSpeed.name().toLowerCase() + )); + } } /** @@ -66,7 +118,16 @@ default void setNetworkSpeed(NetworkSpeed networkSpeed) { * @param percent Percentage value in range [0, 100]. */ default void setPowerCapacity(int percent) { - CommandExecutionHelper.execute(this, powerCapacityCommand(percent)); + try { + CommandExecutionHelper.executeScript(this, "mobile: powerCapacity", ImmutableMap.of( + "percent", percent + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(POWER_CAPACITY, ImmutableMap.of( + "percent", percent + )); + } } /** @@ -75,7 +136,16 @@ default void setPowerCapacity(int percent) { * @param powerACState One of available {@link PowerACState} values. */ default void setPowerAC(PowerACState powerACState) { - CommandExecutionHelper.execute(this, powerACCommand(powerACState)); + try { + CommandExecutionHelper.executeScript(this, "mobile: powerAC", ImmutableMap.of( + "state", powerACState.toString().toLowerCase() + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + this.execute(POWER_AC_STATE, ImmutableMap.of( + "state", powerACState.name().toLowerCase() + )); + } } } diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index aa2434d50..246951d8a 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -246,11 +246,6 @@ public void resetTest() { driver.resetApp(); } - @Test - public void endTestCoverage() { - driver.endTestCoverage("android.intent.action.MAIN", ""); - } - @Test public void deviceDetailsAndKeyboardTest() { assertFalse(driver.isKeyboardShown()); From 95d4272def2ad28a9c9ac29aa631fa7a2e664daf Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 29 Apr 2023 18:29:14 +0200 Subject: [PATCH 204/501] ci: Perform xcuitest driver prebuild (#1900) --- azure-pipelines.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a3d59c308..4cea8df6d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,17 +4,17 @@ # https://docs.microsoft.com/azure/devops/pipelines/languages/java pool: - vmImage: 'macos-11' + vmImage: 'macos-12' variables: ANDROID_EMU_NAME: test ANDROID_EMU_ABI: x86 ANDROID_EMU_TARGET: android-28 ANDROID_EMU_TAG: default - XCODE_VERSION: 13.2 - IOS_PLATFORM_VERSION: 15.2 - IOS_DEVICE_NAME: iPhone X - NODE_VERSION: 16.x + XCODE_VERSION: 14.2 + IOS_PLATFORM_VERSION: 16.2 + IOS_DEVICE_NAME: iPhone 12 + NODE_VERSION: 18.x JDK_VERSION: 1.8 jobs: @@ -50,9 +50,14 @@ jobs: - script: | sudo xcode-select -s /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer xcrun simctl list - displayName: Simulator configuration - - script: $NVM_DIR/versions/node/`node --version`/bin/appium driver install xcuitest + target_sim_id=$(xcrun simctl list devices available | grep "$IOS_DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) + open -Fn "/Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer/Applications/Simulator.app" + xcrun simctl bootstatus $target_sim_id -b + displayName: Prepare iOS Simulator + - script: $NVM_DIR/versions/node/$(node --version)/bin/appium driver install xcuitest displayName: Install XCUITest driver + - script: $NVM_DIR/versions/node/$(node --version)/bin/appium driver run xcuitest build-wda + displayName: Prebuild XCUITest driver - task: Gradle@2 inputs: gradleWrapperFile: 'gradlew' From ba63c064bdcf25642ed458b18d784e96efd16e84 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 30 Apr 2023 16:25:42 +0200 Subject: [PATCH 205/501] refactor: Finish migrating Android helpers to mobile extensions (#1901) --- .../java_client/android/AndroidDriver.java | 15 ++------ .../android/CanReplaceElementValue.java | 1 + .../java_client/android/HasNotifications.java | 22 ++++++++++++ .../android/SupportsGpsStateManagement.java | 35 +++++++++++++++++++ 4 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 src/main/java/io/appium/java_client/android/HasNotifications.java create mode 100644 src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java 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 9606be761..27b3bd5cf 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -51,8 +51,6 @@ import java.net.URL; import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; /** * Android driver implementation. @@ -86,6 +84,8 @@ public class AndroidDriver extends AppiumDriver implements HasBattery, ExecuteCDPCommand, CanReplaceElementValue, + SupportsGpsStateManagement, + HasNotifications, SupportsExtendedGeolocationCommands { private static final String ANDROID_PLATFORM = Platform.ANDROID.name(); @@ -262,17 +262,6 @@ public void endTestCoverage(String intent, String path) { CommandExecutionHelper.execute(this, endTestCoverageCommand(intent, path)); } - /** - * Open the notification shade, on Android devices. - */ - public void openNotifications() { - CommandExecutionHelper.execute(this, openNotificationsCommand()); - } - - public void toggleLocationServices() { - CommandExecutionHelper.execute(this, toggleLocationServicesCommand()); - } - @Override public AndroidBatteryInfo getBatteryInfo() { return new AndroidBatteryInfo(CommandExecutionHelper.executeScript(this, "mobile: batteryInfo")); diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java index 949e7964c..eb81ba417 100644 --- a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -28,6 +28,7 @@ default void replaceElementValue(RemoteWebElement element, String value) { // TODO: Remove the fallback this.execute(MobileCommand.REPLACE_VALUE, ImmutableMap.of( "id", element.getId(), + "text", value, "value", value )); } diff --git a/src/main/java/io/appium/java_client/android/HasNotifications.java b/src/main/java/io/appium/java_client/android/HasNotifications.java new file mode 100644 index 000000000..c2e870031 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/HasNotifications.java @@ -0,0 +1,22 @@ +package io.appium.java_client.android; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; + +import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; + +public interface HasNotifications extends ExecutesMethod { + + /** + * Opens notification drawer on the device under test. + */ + default void openNotifications() { + try { + CommandExecutionHelper.executeScript(this, "mobile: openNotifications"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, openNotificationsCommand()); + } + } +} diff --git a/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java new file mode 100644 index 000000000..597c98193 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java @@ -0,0 +1,35 @@ +package io.appium.java_client.android; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; + +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; + +public interface SupportsGpsStateManagement extends ExecutesMethod { + + /** + * Toggles GPS service state. + * This method only works reliably since API 31 (Android 12). + */ + default void toggleLocationServices() { + try { + CommandExecutionHelper.executeScript(this, "mobile: toggleGps"); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, toggleLocationServicesCommand()); + } + } + + /** + * Check GPS service state. + * + * @return true if GPS service is enabled. + */ + default boolean isLocationServicesEnabled() { + return checkNotNull( + CommandExecutionHelper.executeScript(this, "mobile: isGpsEnabled") + ); + } +} From 62a25e55be9e1966921f7112afba8fd45b9142e5 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 1 May 2023 19:33:34 +0200 Subject: [PATCH 206/501] chore: Avoid sending unnecessary requests if corresponding extensions are absent (#1903) --- .../io/appium/java_client/AppiumDriver.java | 19 ++++ .../CanRememberExtensionPresence.java | 25 +++++ .../io/appium/java_client/HasAppStrings.java | 19 ++-- .../java_client/HasOnScreenKeyboard.java | 9 +- .../io/appium/java_client/HidesKeyboard.java | 7 +- .../java_client/HidesKeyboardWithKeyName.java | 5 +- .../appium/java_client/InteractsWithApps.java | 63 ++++++++---- .../io/appium/java_client/LocksDevice.java | 21 ++-- .../android/AuthenticatesByFinger.java | 8 +- .../android/CanReplaceElementValue.java | 21 ++-- .../android/HasAndroidDeviceDetails.java | 13 ++- .../java_client/android/HasNotifications.java | 8 +- .../java_client/android/StartsActivity.java | 15 ++- .../android/SupportsGpsStateManagement.java | 8 +- .../SupportsNetworkStateManagement.java | 24 +++-- .../SupportsSpecialEmulatorCommands.java | 95 ++++++++++++------- .../connection/HasNetworkConnection.java | 19 +++- .../android/nativekey/PressesKey.java | 21 ++-- .../appium/java_client/ios/ShakesDevice.java | 8 +- 19 files changed, 282 insertions(+), 126 deletions(-) create mode 100644 src/main/java/io/appium/java_client/CanRememberExtensionPresence.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index debd404d3..38c80bf6d 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -32,6 +32,7 @@ import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.OutputType; import org.openqa.selenium.SessionNotCreatedException; +import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DriverCommand; @@ -48,7 +49,9 @@ import java.net.URL; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME; @@ -64,6 +67,7 @@ public class AppiumDriver extends RemoteWebDriver implements ExecutesDriverScript, LogsEvents, HasBrowserCheck, + CanRememberExtensionPresence, HasSettings { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); @@ -71,6 +75,7 @@ public class AppiumDriver extends RemoteWebDriver implements private final URL remoteAddress; protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; + private final Set absentExtensionNames = new HashSet<>(); /** * Creates a new instance based on command {@code executor} and {@code capabilities}. @@ -327,4 +332,18 @@ public X convertFromPngBytes(byte[] png) { } }); } + + @Override + public AppiumDriver assertExtensionExists(String extName) { + if (absentExtensionNames.contains(extName)) { + throw new UnsupportedCommandException(); + } + return this; + } + + @Override + public AppiumDriver markExtensionAbsence(String extName) { + absentExtensionNames.add(extName); + return this; + } } diff --git a/src/main/java/io/appium/java_client/CanRememberExtensionPresence.java b/src/main/java/io/appium/java_client/CanRememberExtensionPresence.java new file mode 100644 index 000000000..36cd4b903 --- /dev/null +++ b/src/main/java/io/appium/java_client/CanRememberExtensionPresence.java @@ -0,0 +1,25 @@ +package io.appium.java_client; + +import org.openqa.selenium.UnsupportedCommandException; + +public interface CanRememberExtensionPresence { + /** + * Verifies if the given extension is not present in the list of absent extensions + * for the given driver instance. + * This API is designed for private usage. + * + * @param extName extension name. + * @return self instance for chaining. + * @throws UnsupportedCommandException if the extension is listed in the list of absents. + */ + ExecutesMethod assertExtensionExists(String extName); + + /** + * Marks the given extension as absent for the given driver instance. + * This API is designed for private usage. + * + * @param extName extension name. + * @return self instance for chaining. + */ + ExecutesMethod markExtensionAbsence(String extName); +} diff --git a/src/main/java/io/appium/java_client/HasAppStrings.java b/src/main/java/io/appium/java_client/HasAppStrings.java index d093e777f..439e08bcd 100644 --- a/src/main/java/io/appium/java_client/HasAppStrings.java +++ b/src/main/java/io/appium/java_client/HasAppStrings.java @@ -25,7 +25,7 @@ import static io.appium.java_client.MobileCommand.GET_STRINGS; import static io.appium.java_client.MobileCommand.prepareArguments; -public interface HasAppStrings extends ExecutesMethod { +public interface HasAppStrings extends ExecutesMethod, CanRememberExtensionPresence { /** * Get all defined Strings from an app for the default language. * See the documentation for 'mobile: getAppStrings' extension for more details. @@ -33,11 +33,12 @@ public interface HasAppStrings extends ExecutesMethod { * @return a map with localized strings defined in the app */ default Map getAppStringMap() { + final String extName = "mobile: getAppStrings"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getAppStrings"); + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return CommandExecutionHelper.execute(this, GET_STRINGS); + return CommandExecutionHelper.execute(markExtensionAbsence(extName), GET_STRINGS); } } @@ -49,14 +50,16 @@ default Map getAppStringMap() { * @return a map with localized strings defined in the app */ default Map getAppStringMap(String language) { + final String extName = "mobile: getAppStrings"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getAppStrings", ImmutableMap.of( + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "language", language )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback return CommandExecutionHelper.execute( - this, new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments("language", language)) + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments("language", language)) ); } } @@ -71,8 +74,9 @@ default Map getAppStringMap(String language) { * @return a map with localized strings defined in the app */ default Map getAppStringMap(String language, String stringFile) { + final String extName = "mobile: getAppStrings"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getAppStrings", ImmutableMap.of( + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "language", language, "stringFile", stringFile )); @@ -81,7 +85,8 @@ 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)) + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments(parameters, values)) ); } } diff --git a/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java b/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java index 322c849db..d54c4a91f 100644 --- a/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java +++ b/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java @@ -5,7 +5,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.isKeyboardShownCommand; -public interface HasOnScreenKeyboard extends ExecutesMethod { +public interface HasOnScreenKeyboard extends ExecutesMethod, CanRememberExtensionPresence { /** * Check if the on-screen keyboard is displayed. @@ -14,11 +14,14 @@ public interface HasOnScreenKeyboard extends ExecutesMethod { * @return true if keyboard is displayed. False otherwise */ default boolean isKeyboardShown() { + final String extName = "mobile: isKeyboardShown"; try { - return checkNotNull(CommandExecutionHelper.executeScript(this, "mobile: isKeyboardShown")); + return checkNotNull(CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName)); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return checkNotNull(CommandExecutionHelper.execute(this, isKeyboardShownCommand())); + return checkNotNull( + CommandExecutionHelper.execute(markExtensionAbsence(extName), isKeyboardShownCommand()) + ); } } } diff --git a/src/main/java/io/appium/java_client/HidesKeyboard.java b/src/main/java/io/appium/java_client/HidesKeyboard.java index 6de1e0516..a6f522102 100644 --- a/src/main/java/io/appium/java_client/HidesKeyboard.java +++ b/src/main/java/io/appium/java_client/HidesKeyboard.java @@ -20,7 +20,7 @@ import static io.appium.java_client.MobileCommand.HIDE_KEYBOARD; -public interface HidesKeyboard extends ExecutesMethod { +public interface HidesKeyboard extends ExecutesMethod, CanRememberExtensionPresence { /** * Hides the keyboard if it is showing. @@ -30,11 +30,12 @@ public interface HidesKeyboard extends ExecutesMethod { * See the documentation for 'mobile: hideKeyboard' extension for more details. */ default void hideKeyboard() { + final String extName = "mobile: hideKeyboard"; try { - CommandExecutionHelper.executeScript(this, "mobile: hideKeyboard"); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, HIDE_KEYBOARD); + CommandExecutionHelper.execute(markExtensionAbsence(extName), HIDE_KEYBOARD); } } } diff --git a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java index c7e809911..35d7a7b0c 100644 --- a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java +++ b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java @@ -35,13 +35,14 @@ public interface HidesKeyboardWithKeyName extends HidesKeyboard { * keyboard. */ default void hideKeyboard(String keyName) { + final String extName = "mobile: hideKeyboard"; try { - CommandExecutionHelper.executeScript(this, "mobile: hideKeyboard", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "keys", ImmutableList.of(keyName) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, hideKeyboardCommand(keyName)); + CommandExecutionHelper.execute(markExtensionAbsence(extName), hideKeyboardCommand(keyName)); } } diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index da39a0ded..45f1c285d 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -43,7 +43,7 @@ import static io.appium.java_client.MobileCommand.TERMINATE_APP; @SuppressWarnings({"rawtypes", "unchecked"}) -public interface InteractsWithApps extends ExecutesMethod { +public interface InteractsWithApps extends ExecutesMethod, CanRememberExtensionPresence { /** * Install an app on the mobile device. @@ -62,13 +62,14 @@ default void installApp(String appPath) { * the particular platform. */ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) { + final String extName = "mobile: installApp"; try { Map args = ImmutableMap.builder() .put("app", appPath) .put("appPath", appPath) .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) .build(); - CommandExecutionHelper.executeScript(this, "mobile: installApp", args); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback Map args = ImmutableMap.builder() @@ -77,7 +78,9 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions (opts) -> ImmutableMap.of("options", opts.build()) ).orElseGet(ImmutableMap::of)) .build(); - CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(INSTALL_APP, args)); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), new AbstractMap.SimpleEntry<>(INSTALL_APP, args) + ); } } @@ -88,9 +91,10 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions * @return True if app is installed, false otherwise. */ default boolean isAppInstalled(String bundleId) { + final String extName = "mobile: isAppInstalled"; try { return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: isAppInstalled", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "bundleId", bundleId, "appId", bundleId )) @@ -98,8 +102,9 @@ default boolean isAppInstalled(String bundleId) { } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback return checkNotNull( - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, ImmutableMap.of("bundleId", bundleId)) + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, ImmutableMap.of("bundleId", bundleId)) ) ); } @@ -114,13 +119,19 @@ default boolean isAppInstalled(String bundleId) { * Passing a negative value will switch to Home screen and return immediately. */ default void runAppInBackground(Duration duration) { + final String extName = "mobile: backgroundApp"; try { - CommandExecutionHelper.executeScript(this, "mobile: backgroundApp", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "seconds", duration.toMillis() / 1000.0 )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - execute(RUN_APP_IN_BACKGROUND, ImmutableMap.of("seconds", duration.toMillis() / 1000.0)); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(RUN_APP_IN_BACKGROUND, ImmutableMap.of( + "seconds", duration.toMillis() / 1000.0) + ) + ); } } @@ -143,6 +154,7 @@ default boolean removeApp(String bundleId) { * @return true if the uninstall was successful. */ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOptions options) { + final String extName = "mobile: removeApp"; try { Map args = ImmutableMap.builder() .put("bundleId", bundleId) @@ -150,7 +162,7 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) .build(); return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: removeApp", args) + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback @@ -163,7 +175,8 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption //noinspection RedundantCast return checkNotNull( (Boolean) CommandExecutionHelper.execute( - this, new AbstractMap.SimpleEntry<>(REMOVE_APP, args) + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(REMOVE_APP, args) ) ); } @@ -188,13 +201,14 @@ default void activateApp(String bundleId) { * particular platform. */ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptions options) { + final String extName = "mobile: activateApp"; try { Map args = ImmutableMap.builder() .put("bundleId", bundleId) .put("appId", bundleId) .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) .build(); - CommandExecutionHelper.executeScript(this, "mobile: activateApp", args); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback Map args = ImmutableMap.builder() @@ -203,7 +217,9 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio (opts) -> ImmutableMap.of("options", opts.build()) ).orElseGet(ImmutableMap::of)) .build(); - CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(ACTIVATE_APP, args)); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), new AbstractMap.SimpleEntry<>(ACTIVATE_APP, args) + ); } } @@ -214,21 +230,27 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio * @return one of possible {@link ApplicationState} values, */ default ApplicationState queryAppState(String bundleId) { + final String extName = "mobile: queryAppState"; try { return ApplicationState.ofCode( checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: queryAppState", ImmutableMap.of( - "bundleId", bundleId, - "appId", bundleId - )) + CommandExecutionHelper.executeScript( + assertExtensionExists(extName), + extName, ImmutableMap.of( + "bundleId", bundleId, + "appId", bundleId + ) + ) ) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback return ApplicationState.ofCode( checkNotNull( - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(QUERY_APP_STATE, ImmutableMap.of("bundleId", bundleId))) + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(QUERY_APP_STATE, ImmutableMap.of("bundleId", bundleId)) + ) ) ); } @@ -253,6 +275,7 @@ default boolean terminateApp(String bundleId) { * @return true if the app was running before and has been successfully stopped. */ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplicationOptions options) { + final String extName = "mobile: terminateApp"; try { Map args = ImmutableMap.builder() .put("bundleId", bundleId) @@ -260,7 +283,7 @@ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplication .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) .build(); return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: terminateApp", args) + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback @@ -273,7 +296,7 @@ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplication //noinspection RedundantCast return checkNotNull( (Boolean) CommandExecutionHelper.execute( - this, new AbstractMap.SimpleEntry<>(TERMINATE_APP, args) + markExtensionAbsence(extName), new AbstractMap.SimpleEntry<>(TERMINATE_APP, args) ) ); } diff --git a/src/main/java/io/appium/java_client/LocksDevice.java b/src/main/java/io/appium/java_client/LocksDevice.java index 6f3033e05..60ba88ffc 100644 --- a/src/main/java/io/appium/java_client/LocksDevice.java +++ b/src/main/java/io/appium/java_client/LocksDevice.java @@ -26,7 +26,7 @@ import static io.appium.java_client.MobileCommand.lockDeviceCommand; import static io.appium.java_client.MobileCommand.unlockDeviceCommand; -public interface LocksDevice extends ExecutesMethod { +public interface LocksDevice extends ExecutesMethod, CanRememberExtensionPresence { /** * This method locks a device. It will return silently if the device @@ -45,13 +45,14 @@ default void lockDevice() { * A negative/zero value will lock the device and return immediately. */ default void lockDevice(Duration duration) { + final String extName = "mobile: lock"; try { - CommandExecutionHelper.executeScript(this, "mobile: lock", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "seconds", duration.getSeconds() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, lockDeviceCommand(duration)); + CommandExecutionHelper.execute(markExtensionAbsence(extName), lockDeviceCommand(duration)); } } @@ -60,15 +61,16 @@ default void lockDevice(Duration duration) { * is not locked. */ default void unlockDevice() { + final String extName = "mobile: unlock"; try { //noinspection ConstantConditions - if (!(Boolean) CommandExecutionHelper.executeScript(this, "mobile: isLocked")) { + if (!(Boolean) CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: isLocked")) { return; } - CommandExecutionHelper.executeScript(this, "mobile: unlock"); + CommandExecutionHelper.executeScript(this, extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, unlockDeviceCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), unlockDeviceCommand()); } } @@ -78,13 +80,16 @@ default void unlockDevice() { * @return true if the device is locked or false otherwise. */ default boolean isDeviceLocked() { + final String extName = "mobile: isLocked"; try { return checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: isLocked") + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName) ); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return checkNotNull(CommandExecutionHelper.execute(this, getIsDeviceLockedCommand())); + return checkNotNull( + CommandExecutionHelper.execute(markExtensionAbsence(extName), getIsDeviceLockedCommand()) + ); } } } diff --git a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java index a9ecf128f..178ec4206 100644 --- a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java +++ b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java @@ -1,13 +1,14 @@ package io.appium.java_client.android; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand; -public interface AuthenticatesByFinger extends ExecutesMethod { +public interface AuthenticatesByFinger extends ExecutesMethod, CanRememberExtensionPresence { /** * Authenticate users by using their finger print scans on supported emulators. @@ -15,13 +16,14 @@ public interface AuthenticatesByFinger extends ExecutesMethod { * @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10) */ default void fingerPrint(int fingerPrintId) { + final String extName = "mobile: fingerprint"; try { - CommandExecutionHelper.executeScript(this, "mobile: fingerprint", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "fingerprintId", fingerPrintId )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, fingerPrintCommand(fingerPrintId)); + CommandExecutionHelper.execute(markExtensionAbsence(extName), fingerPrintCommand(fingerPrintId)); } } } diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java index eb81ba417..2b48a9e29 100644 --- a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -1,13 +1,16 @@ package io.appium.java_client.android; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.MobileCommand; import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.remote.RemoteWebElement; -public interface CanReplaceElementValue extends ExecutesMethod { +import java.util.AbstractMap; + +public interface CanReplaceElementValue extends ExecutesMethod, CanRememberExtensionPresence { /** * Sends a text to the given element by replacing its previous content. * @@ -19,18 +22,22 @@ public interface CanReplaceElementValue extends ExecutesMethod { * off from the typed text). */ default void replaceElementValue(RemoteWebElement element, String value) { + final String extName = "mobile: replaceValue"; try { - CommandExecutionHelper.executeScript(this, "mobile: replaceValue", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "elementId", element.getId(), "text", value )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(MobileCommand.REPLACE_VALUE, ImmutableMap.of( - "id", element.getId(), - "text", value, - "value", value - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(MobileCommand.REPLACE_VALUE, ImmutableMap.of( + "id", element.getId(), + "text", value, + "value", value + )) + ); } } } diff --git a/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java b/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java index bcdcf1fd4..3e230b3a3 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidDeviceDetails.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; @@ -9,7 +10,7 @@ import static io.appium.java_client.android.AndroidMobileCommandHelper.getDisplayDensityCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.getSystemBarsCommand; -public interface HasAndroidDeviceDetails extends ExecutesMethod { +public interface HasAndroidDeviceDetails extends ExecutesMethod, CanRememberExtensionPresence { /** Retrieve the display density of the Android device. @@ -17,11 +18,12 @@ public interface HasAndroidDeviceDetails extends ExecutesMethod { @return The density value in dpi */ default Long getDisplayDensity() { + final String extName = "mobile: getDisplayDensity"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getDisplayDensity"); + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return CommandExecutionHelper.execute(this, getDisplayDensityCommand()); + return CommandExecutionHelper.execute(markExtensionAbsence(extName), getDisplayDensityCommand()); } } @@ -31,11 +33,12 @@ default Long getDisplayDensity() { @return The map where keys are bar types and values are mappings of bar properties. */ default Map> getSystemBars() { + final String extName = "mobile: getSystemBars"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getSystemBars"); + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return CommandExecutionHelper.execute(this, getSystemBarsCommand()); + return CommandExecutionHelper.execute(markExtensionAbsence(extName), getSystemBarsCommand()); } } diff --git a/src/main/java/io/appium/java_client/android/HasNotifications.java b/src/main/java/io/appium/java_client/android/HasNotifications.java index c2e870031..0b7f7365b 100644 --- a/src/main/java/io/appium/java_client/android/HasNotifications.java +++ b/src/main/java/io/appium/java_client/android/HasNotifications.java @@ -1,22 +1,24 @@ package io.appium.java_client.android; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; -public interface HasNotifications extends ExecutesMethod { +public interface HasNotifications extends ExecutesMethod, CanRememberExtensionPresence { /** * Opens notification drawer on the device under test. */ default void openNotifications() { + final String extName = "mobile: openNotifications"; try { - CommandExecutionHelper.executeScript(this, "mobile: openNotifications"); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, openNotificationsCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), openNotificationsCommand()); } } } 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 9291e5020..f1d538881 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -17,6 +17,7 @@ package io.appium.java_client.android; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; @@ -29,7 +30,7 @@ import static io.appium.java_client.MobileCommand.GET_CURRENT_PACKAGE; import static io.appium.java_client.android.AndroidMobileCommandHelper.startActivityCommand; -public interface StartsActivity extends ExecutesMethod { +public interface StartsActivity extends ExecutesMethod, CanRememberExtensionPresence { /** * 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. @@ -65,12 +66,14 @@ default void startActivity(Activity activity) { */ @Nullable default String currentActivity() { + final String extName = "mobile: getCurrentActivity"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getCurrentActivity"); + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback return CommandExecutionHelper.execute( - this, new AbstractMap.SimpleEntry<>(CURRENT_ACTIVITY, ImmutableMap.of()) + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(CURRENT_ACTIVITY, ImmutableMap.of()) ); } } @@ -82,12 +85,14 @@ default String currentActivity() { */ @Nullable default String getCurrentPackage() { + final String extName = "mobile: getCurrentPackage"; try { - return CommandExecutionHelper.executeScript(this, "mobile: getCurrentPackage"); + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback return CommandExecutionHelper.execute( - this, new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()) + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()) ); } } diff --git a/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java index 597c98193..14854412e 100644 --- a/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java +++ b/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; @@ -7,18 +8,19 @@ import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; -public interface SupportsGpsStateManagement extends ExecutesMethod { +public interface SupportsGpsStateManagement extends ExecutesMethod, CanRememberExtensionPresence { /** * Toggles GPS service state. * This method only works reliably since API 31 (Android 12). */ default void toggleLocationServices() { + final String extName = "mobile: toggleGps"; try { - CommandExecutionHelper.executeScript(this, "mobile: toggleGps"); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, toggleLocationServicesCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), toggleLocationServicesCommand()); } } diff --git a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java index 9fdbd23c9..8f4dfa246 100644 --- a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java +++ b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java @@ -1,6 +1,7 @@ package io.appium.java_client.android; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; @@ -12,22 +13,23 @@ import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleDataCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleWifiCommand; -public interface SupportsNetworkStateManagement extends ExecutesMethod { +public interface SupportsNetworkStateManagement extends ExecutesMethod, CanRememberExtensionPresence { /** * Toggles Wifi on and off. */ default void toggleWifi() { + final String extName = "mobile: setConnectivity"; try { Map result = checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: getConnectivity") ); - CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + CommandExecutionHelper.executeScript(this, extName, ImmutableMap.of( "wifi", !((Boolean) result.get("wifi")) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, toggleWifiCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), toggleWifiCommand()); } } @@ -36,16 +38,17 @@ default void toggleWifi() { * 6 and above 10. */ default void toggleAirplaneMode() { + final String extName = "mobile: setConnectivity"; try { Map result = checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: getConnectivity") ); - CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + CommandExecutionHelper.executeScript(this, extName, ImmutableMap.of( "airplaneMode", !((Boolean) result.get("airplaneMode")) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, toggleAirplaneCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), toggleAirplaneCommand()); } } @@ -54,16 +57,17 @@ default void toggleAirplaneMode() { * running Android version above 10. */ default void toggleData() { + final String extName = "mobile: setConnectivity"; try { Map result = checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: getConnectivity") ); - CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + CommandExecutionHelper.executeScript(this, extName, ImmutableMap.of( "data", !((Boolean) result.get("data")) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, toggleDataCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), toggleDataCommand()); } } } diff --git a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java index 29cd6415e..025f00b05 100644 --- a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java +++ b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java @@ -1,10 +1,13 @@ package io.appium.java_client.android; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; +import java.util.AbstractMap; + import static io.appium.java_client.MobileCommand.GSM_CALL; import static io.appium.java_client.MobileCommand.GSM_SIGNAL; import static io.appium.java_client.MobileCommand.GSM_VOICE; @@ -13,7 +16,7 @@ import static io.appium.java_client.MobileCommand.POWER_CAPACITY; import static io.appium.java_client.MobileCommand.SEND_SMS; -public interface SupportsSpecialEmulatorCommands extends ExecutesMethod { +public interface SupportsSpecialEmulatorCommands extends ExecutesMethod, CanRememberExtensionPresence { /** * Emulate send SMS event on the connected emulator. @@ -22,17 +25,21 @@ public interface SupportsSpecialEmulatorCommands extends ExecutesMethod { * @param message The message content. */ default void sendSMS(String phoneNumber, String message) { + final String extName = "mobile: sendSms"; try { - CommandExecutionHelper.executeScript(this, "mobile: sendSms", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "phoneNumber", phoneNumber, "message", message )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(SEND_SMS, ImmutableMap.of( - "phoneNumber", phoneNumber, - "message", message - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(SEND_SMS, ImmutableMap.of( + "phoneNumber", phoneNumber, + "message", message + )) + ); } } @@ -43,17 +50,21 @@ default void sendSMS(String phoneNumber, String message) { * @param gsmCallAction One of available {@link GsmCallActions} values. */ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { + final String extName = "mobile: gsmCall"; try { - CommandExecutionHelper.executeScript(this, "mobile: gsmCall", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "phoneNumber", phoneNumber, "action", gsmCallAction.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(GSM_CALL, ImmutableMap.of( - "phoneNumber", phoneNumber, - "action", gsmCallAction.toString().toLowerCase() - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(GSM_CALL, ImmutableMap.of( + "phoneNumber", phoneNumber, + "action", gsmCallAction.toString().toLowerCase() + )) + ); } } @@ -63,16 +74,20 @@ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { * @param gsmSignalStrength One of available {@link GsmSignalStrength} values. */ default void setGsmSignalStrength(GsmSignalStrength gsmSignalStrength) { + final String extName = "mobile: gsmSignal"; try { - CommandExecutionHelper.executeScript(this, "mobile: gsmSignal", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "strength", gsmSignalStrength.ordinal() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(GSM_SIGNAL, ImmutableMap.of( - "signalStrengh", gsmSignalStrength.ordinal(), - "signalStrength", gsmSignalStrength.ordinal() - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(GSM_SIGNAL, ImmutableMap.of( + "signalStrengh", gsmSignalStrength.ordinal(), + "signalStrength", gsmSignalStrength.ordinal() + )) + ); } } @@ -82,15 +97,19 @@ default void setGsmSignalStrength(GsmSignalStrength gsmSignalStrength) { * @param gsmVoiceState One of available {@link GsmVoiceState} values. */ default void setGsmVoice(GsmVoiceState gsmVoiceState) { + final String extName = "mobile: gsmVoice"; try { - CommandExecutionHelper.executeScript(this, "mobile: gsmVoice", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "state", gsmVoiceState.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(GSM_VOICE, ImmutableMap.of( - "state", gsmVoiceState.name().toLowerCase() - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(GSM_VOICE, ImmutableMap.of( + "state", gsmVoiceState.name().toLowerCase() + )) + ); } } @@ -100,15 +119,19 @@ default void setGsmVoice(GsmVoiceState gsmVoiceState) { * @param networkSpeed One of available {@link NetworkSpeed} values. */ default void setNetworkSpeed(NetworkSpeed networkSpeed) { + final String extName = "mobile: networkSpeed"; try { - CommandExecutionHelper.executeScript(this, "mobile: networkSpeed", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "speed", networkSpeed.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(NETWORK_SPEED, ImmutableMap.of( - "netspeed", networkSpeed.name().toLowerCase() - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(NETWORK_SPEED, ImmutableMap.of( + "netspeed", networkSpeed.name().toLowerCase() + )) + ); } } @@ -118,15 +141,19 @@ default void setNetworkSpeed(NetworkSpeed networkSpeed) { * @param percent Percentage value in range [0, 100]. */ default void setPowerCapacity(int percent) { + final String extName = "mobile: powerCapacity"; try { - CommandExecutionHelper.executeScript(this, "mobile: powerCapacity", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "percent", percent )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(POWER_CAPACITY, ImmutableMap.of( - "percent", percent - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(POWER_CAPACITY, ImmutableMap.of( + "percent", percent + )) + ); } } @@ -136,15 +163,19 @@ default void setPowerCapacity(int percent) { * @param powerACState One of available {@link PowerACState} values. */ default void setPowerAC(PowerACState powerACState) { + final String extName = "mobile: powerAC"; try { - CommandExecutionHelper.executeScript(this, "mobile: powerAC", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "state", powerACState.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - this.execute(POWER_AC_STATE, ImmutableMap.of( - "state", powerACState.name().toLowerCase() - )); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(POWER_AC_STATE, ImmutableMap.of( + "state", powerACState.name().toLowerCase() + )) + ); } } diff --git a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java index f77bf7d3a..0774c74a2 100644 --- a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java +++ b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java @@ -17,6 +17,7 @@ package io.appium.java_client.android.connection; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; @@ -27,7 +28,7 @@ import static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand; -public interface HasNetworkConnection extends ExecutesMethod { +public interface HasNetworkConnection extends ExecutesMethod, CanRememberExtensionPresence { /** * Set the network connection of the device. @@ -36,8 +37,9 @@ public interface HasNetworkConnection extends ExecutesMethod { * @return Connection object, which represents the resulting state */ default ConnectionState setConnection(ConnectionState connection) { + final String extName = "mobile: setConnectivity"; try { - CommandExecutionHelper.executeScript(this, "mobile: setConnectivity", ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( "wifi", connection.isWiFiEnabled(), "data", connection.isDataEnabled(), "airplaneMode", connection.isAirplaneModeEnabled() @@ -47,7 +49,10 @@ default ConnectionState setConnection(ConnectionState connection) { // TODO: Remove the fallback return new ConnectionState( checkNotNull( - CommandExecutionHelper.execute(this, setConnectionCommand(connection.getBitMask())) + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + setConnectionCommand(connection.getBitMask()) + ) ) ); } @@ -59,9 +64,10 @@ default ConnectionState setConnection(ConnectionState connection) { * @return Connection object, which lets you to inspect the current status */ default ConnectionState getConnection() { + final String extName = "mobile: getConnectivity"; try { Map result = checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: getConnectivity") + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName) ); return new ConnectionState( ((boolean) result.get("wifi") ? ConnectionState.WIFI_MASK : 0) @@ -72,7 +78,10 @@ default ConnectionState getConnection() { // TODO: Remove the fallback return new ConnectionState( checkNotNull( - CommandExecutionHelper.execute(this, getNetworkConnectionCommand()) + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + getNetworkConnectionCommand() + ) ) ); } diff --git a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java index 9584ff517..b262096c0 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java +++ b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java @@ -17,6 +17,7 @@ package io.appium.java_client.android.nativekey; import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; @@ -27,7 +28,7 @@ import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE; import static io.appium.java_client.MobileCommand.PRESS_KEY_CODE; -public interface PressesKey extends ExecutesMethod { +public interface PressesKey extends ExecutesMethod, CanRememberExtensionPresence { /** * Send a key event to the device under test. @@ -35,12 +36,15 @@ public interface PressesKey extends ExecutesMethod { * @param keyEvent The generated native key event */ default void pressKey(KeyEvent keyEvent) { + final String extName = "mobile: pressKey"; try { - CommandExecutionHelper.executeScript(this, "mobile: pressKey", keyEvent.build()); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, keyEvent.build()); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(PRESS_KEY_CODE, keyEvent.build())); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(PRESS_KEY_CODE, keyEvent.build()) + ); } } @@ -50,16 +54,19 @@ default void pressKey(KeyEvent keyEvent) { * @param keyEvent The generated native key event */ default void longPressKey(KeyEvent keyEvent) { + final String extName = "mobile: pressKey"; try { Map args = ImmutableMap.builder() .putAll(keyEvent.build()) .put("isLongPress", true) .build(); - CommandExecutionHelper.executeScript(this, "mobile: pressKey", args); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(LONG_PRESS_KEY_CODE, keyEvent.build())); + CommandExecutionHelper.execute( + markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(LONG_PRESS_KEY_CODE, keyEvent.build()) + ); } } } diff --git a/src/main/java/io/appium/java_client/ios/ShakesDevice.java b/src/main/java/io/appium/java_client/ios/ShakesDevice.java index 1f34ecbfa..57302ef8a 100644 --- a/src/main/java/io/appium/java_client/ios/ShakesDevice.java +++ b/src/main/java/io/appium/java_client/ios/ShakesDevice.java @@ -16,23 +16,25 @@ package io.appium.java_client.ios; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; import static io.appium.java_client.ios.IOSMobileCommandHelper.shakeCommand; -public interface ShakesDevice extends ExecutesMethod { +public interface ShakesDevice extends ExecutesMethod, CanRememberExtensionPresence { /** * Simulate shaking the Simulator. This API does not work for real devices. */ default void shake() { + final String extName = "mobile: shake"; try { - CommandExecutionHelper.executeScript(this, "mobile: shake"); + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - CommandExecutionHelper.execute(this, shakeCommand()); + CommandExecutionHelper.execute(markExtensionAbsence(extName), shakeCommand()); } } } From 2f62c0c025ecbc59fe957ee6e76a9cbc0974cdf8 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Sun, 7 May 2023 14:11:11 +0800 Subject: [PATCH 207/501] Release 8.4.0 and update release notes --- CHANGELOG.md | 48 +++++++++++++++++++++++++++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc957b07f..cdf57b46d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,54 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +*8.4.0* +- **[ENHANCEMENTS]** + - Added possibility to connect to a running session. [#1813](https://github.com/appium/java-client/pull/1813) + - deprecate tapWithShortPressDuration capability.[#1825](https://github.com/appium/java-client/pull/1825) + - Add SupportsEnforceAppInstallOption to XCUITestOptions.[#1895](https://github.com/appium/java-client/pull/1895) +- **[BUG FIX]** + - Use ipv4 address instead of localhost. [#1815](https://github.com/appium/java-client/pull/1815) + - Fix test broken by updates in `appium-xcuitest-driver`. [#1839](https://github.com/appium/java-client/pull/1839) + - Merge misc tests suite into unit tests suite. [#1850](https://github.com/appium/java-client/pull/1850) + - Avoid NPE in destroyProcess call. [#1878](https://github.com/appium/java-client/pull/1878) + - Send arguments for mobile methods depending on the target platform. [#1897](https://github.com/appium/java-client/pull/1897) +- **[REFACTOR]** + - Run Gradle wrapper validation only on Gradle files changes. [#1828](https://github.com/appium/java-client/pull/1828) + - Skip GH Actions build on changes in docs. [#1829](https://github.com/appium/java-client/pull/1829) + - Remove Checkstyle exclusion of removed Selenium package. [#1831](https://github.com/appium/java-client/pull/1831) + - Enable Checkstyle checks for test code. [#1843](https://github.com/appium/java-client/pull/1843) + - Configure `CODEOWNERS` to automate review requests. [#1846](https://github.com/appium/java-client/pull/1846) + - Enable execution of unit tests in CI. [#1845](https://github.com/appium/java-client/pull/1845) + - Add Simple SLF4J binding to unit tests runtime. [#1848](https://github.com/appium/java-client/pull/1848) + - Improve performance of proxy `Interceptor` logging. [#1849](https://github.com/appium/java-client/pull/1849) + - Make unit tests execution a part of Gradle build lifecycle. [#1853](https://github.com/appium/java-client/pull/1853) + - Replace non-W3C API calls with corresponding extension calls in app management. [#1883](https://github.com/appium/java-client/pull/1883) + - Switch the time getter to use mobile extensions. [#1884](https://github.com/appium/java-client/pull/1884) + - Switch file management APIs to use mobile: extensions. [#1886](https://github.com/appium/java-client/pull/1886) + - Use mobile extensions for app strings getters and keyboard commands. [#1890](https://github.com/appium/java-client/pull/1890) + - Finish replacing iOS extensions with their mobile alternatives. [#1892](https://github.com/appium/java-client/pull/1892) + - Change some Android APIs to use mobile extensions. [#1893](https://github.com/appium/java-client/pull/1893) + - Change backgroundApp command to use the corresponding mobile extension. [#1896](https://github.com/appium/java-client/pull/1896) + - Switch more Android helpers to use extensions. [#1898](https://github.com/appium/java-client/pull/1898) + - Perform xcuitest driver prebuild. [#1900](https://github.com/appium/java-client/pull/1900) + - Finish migrating Android helpers to mobile extensions. [#1901](https://github.com/appium/java-client/pull/1901) + - Avoid sending unnecessary requests if corresponding extensions are absent. [#1903](https://github.com/appium/java-client/pull/1903) +- **[DOCUMENTATION]** + - Describe transitive Selenium dependencies management. [#1827](https://github.com/appium/java-client/pull/1827) + - Fix build badge to point GH Actions CI. [#1844](https://github.com/appium/java-client/pull/1844) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.8.2. + - `org.slf4j:slf4j-api` was updated to 2.0.7. + - `org.owasp.dependencycheck` was updated to 8.2.1. + - `gradle` was updated to 8.1.0. + - `com.google.code.gson:gson` was updated to 2.10.1. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.2. + - `org.junit.jupiter:junit-jupiter` was updated to 5.9.2. + - `checkstyle` was updated to 10.0. + - `jacoco` was updated to 0.8.8. + - `org.projectlombok:lombok` was updated to 1.18.26. + - `com.github.johnrengelman.shadow` was updated to 8.1.1. + *8.3.0* - **[DOCUMENTATION]** - Added troubleshooting section. [#1808](https://github.com/appium/java-client/pull/1808) diff --git a/gradle.properties b/gradle.properties index e1a1cc258..78924349f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.8.2 # Please increment the value in a release -appiumClient.version=8.3.0 +appiumClient.version=8.4.0 From 50bb0ae80bbce23c3bd160aadce4da89a784aa50 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 7 May 2023 08:21:33 +0200 Subject: [PATCH 208/501] refactor: Replace performance data APIs with mobile extensions (#1905) --- .../HasSupportedPerformanceDataType.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java b/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java index 3afea7552..ee6a3bce8 100644 --- a/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java +++ b/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java @@ -1,14 +1,17 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; import java.util.List; import static io.appium.java_client.android.AndroidMobileCommandHelper.getPerformanceDataCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.getSupportedPerformanceDataTypesCommand; -public interface HasSupportedPerformanceDataType extends ExecutesMethod { +public interface HasSupportedPerformanceDataType extends ExecutesMethod, CanRememberExtensionPresence { /** * returns the information type of the system state which is supported to read @@ -18,7 +21,15 @@ public interface HasSupportedPerformanceDataType extends ExecutesMethod { * */ default List getSupportedPerformanceDataTypes() { - return CommandExecutionHelper.execute(this, getSupportedPerformanceDataTypesCommand()); + final String extName = "mobile: getPerformanceDataTypes"; + try { + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute( + markExtensionAbsence(extName), getSupportedPerformanceDataTypesCommand() + ); + } } /** @@ -50,7 +61,17 @@ default List getSupportedPerformanceDataTypes() { * in case of cpu info : [[user, kernel], [0.9, 1.3]] */ default List> getPerformanceData(String packageName, String dataType, int dataReadTimeout) { - return CommandExecutionHelper.execute(this, - getPerformanceDataCommand(packageName, dataType, dataReadTimeout)); + final String extName = "mobile: getPerformanceData"; + try { + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + "packageName", packageName, + "dataType", dataType + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute( + markExtensionAbsence(extName), getPerformanceDataCommand(packageName, dataType, dataReadTimeout) + ); + } } } From f2fb595a81cc8cfeca22fd7ff80847f277c2a2a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 May 2023 23:06:08 +0300 Subject: [PATCH 209/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.9.2 to 5.9.3 (#1902) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.9.2 to 5.9.3. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.2...r5.9.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 88070b21e..a9e9809e1 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.2') { exclude group: 'org.seleniumhq.selenium' From 9c18b2ff3c32867669d56921351d94bd5ce5ed15 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 9 May 2023 12:41:36 +0300 Subject: [PATCH 210/501] chore: Bump minimum Selenium client version to 4.9.1 (#1908) Selenium 4.9.1 introduced 2 breaking changes that cause compilation errors: - https://github.com/SeleniumHQ/selenium/commit/66e51be38cbd492c11605397e1b50c1cb786a579 - https://github.com/SeleniumHQ/selenium/commit/3d8c6fa7a950ce129f4bd8fb347c71a2cdd4bf07 --- gradle.properties | 2 +- src/main/java/io/appium/java_client/AppiumDriver.java | 4 ++-- .../java_client/service/local/AppiumServiceBuilder.java | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index 78924349f..51f30e7f9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.8.2 +selenium.version=4.9.1 # Please increment the value in a release appiumClient.version=8.4.0 diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 38c80bf6d..ead0a05d0 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -290,8 +290,8 @@ protected void startSession(Capabilities capabilities) { } @SuppressWarnings("unchecked") Map rawCapabilities = (Map) responseValue; - // A workaround for Selenium API enforcing some legacy capability values - rawCapabilities.remove(CapabilityType.PLATFORM); + // TODO: remove this workaround for Selenium API enforcing some legacy capability values in major version + rawCapabilities.remove("platform"); if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME) && isBlank((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { rawCapabilities.remove(CapabilityType.BROWSER_NAME); diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 0b795872d..9d3bce564 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -404,14 +404,13 @@ protected ImmutableList createArgs() { } @Override - public AppiumDriverLocalService build() { + protected void loadSystemProperties() { File driverExecutable = ReflectionHelpers.getPrivateFieldValue( DriverService.Builder.class, this, "exe", File.class ); if (driverExecutable == null) { usingDriverExecutable(findDefaultExecutable()); } - return super.build(); } /** From 1cc687fa3dc7830fe4e01b8d419cdb10edc09ca8 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 9 May 2023 17:26:03 +0300 Subject: [PATCH 211/501] fix: Restore Jitpack builds (#1911) --- build.gradle | 1 + jitpack.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a9e9809e1..7809cd92a 100644 --- a/build.gradle +++ b/build.gradle @@ -182,6 +182,7 @@ publishing { } signing { + required { !'true'.equalsIgnoreCase(project.findProperty('signingDisabled')) } def signingKey = System.getenv("PGP_SECRET") def signingPassword = System.getenv("PGP_PASSPHRASE") useInMemoryPgpKeys(signingKey, signingPassword) diff --git a/jitpack.yml b/jitpack.yml index f5edf063b..8e5135fbb 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,4 @@ jdk: - openjdk8 install: - - ./gradlew clean build publishToMavenLocal -x signMavenJavaPublication + - ./gradlew clean build publishToMavenLocal -PsigningDisabled=true From 5694912c739eb67ae6c05d8921927564fe073cc2 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 9 May 2023 18:16:27 +0300 Subject: [PATCH 212/501] fix: Add fallback commands for file management APIs (#1910) --- .../io/appium/java_client/PullsFiles.java | 47 ++++++++++++++----- .../io/appium/java_client/PushesFiles.java | 19 ++++++-- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/appium/java_client/PullsFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java index 0042b0997..4b60a5748 100644 --- a/src/main/java/io/appium/java_client/PullsFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -19,11 +19,14 @@ import com.google.common.collect.ImmutableMap; import java.nio.charset.StandardCharsets; +import java.util.AbstractMap; import java.util.Base64; import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.MobileCommand.PULL_FILE; +import static io.appium.java_client.MobileCommand.PULL_FOLDER; -public interface PullsFiles extends ExecutesMethod { +public interface PullsFiles extends ExecutesMethod, CanRememberExtensionPresence { /** * Pull a file from the remote system. @@ -38,11 +41,22 @@ public interface PullsFiles extends ExecutesMethod { * @return A byte array of Base64 encoded data. */ default byte[] pullFile(String remotePath) { - String base64String = checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: pullFile", ImmutableMap.of( - "remotePath", remotePath - )) - ); + final String extName = "mobile: pullFile"; + String base64String; + try { + base64String = checkNotNull( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, + ImmutableMap.of("remotePath", remotePath) + ) + ); + } catch (UnsupportedOperationException e) { + // TODO: Remove the fallback + base64String = checkNotNull( + CommandExecutionHelper.execute(markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(PULL_FILE, ImmutableMap.of("path", remotePath)) + ) + ); + } return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } @@ -59,11 +73,22 @@ default byte[] pullFile(String remotePath) { * @return A byte array of Base64 encoded zip archive data. */ default byte[] pullFolder(String remotePath) { - String base64String = checkNotNull( - CommandExecutionHelper.executeScript(this, "mobile: pullFolder", ImmutableMap.of( - "remotePath", remotePath - )) - ); + final String extName = "mobile: pullFolder"; + String base64String; + try { + base64String = checkNotNull( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, + ImmutableMap.of("remotePath", remotePath) + ) + ); + } catch (UnsupportedOperationException e) { + // TODO: Remove the fallback + base64String = checkNotNull( + CommandExecutionHelper.execute(markExtensionAbsence(extName), + new AbstractMap.SimpleEntry<>(PULL_FOLDER, ImmutableMap.of("path", remotePath)) + ) + ); + } return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } diff --git a/src/main/java/io/appium/java_client/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java index 813dcb5b1..1bfd7f8eb 100644 --- a/src/main/java/io/appium/java_client/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -18,13 +18,16 @@ import com.google.common.collect.ImmutableMap; import org.apache.commons.io.FileUtils; +import org.openqa.selenium.UnsupportedCommandException; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; -public interface PushesFiles extends ExecutesMethod { +import static io.appium.java_client.MobileCommand.pushFileCommand; + +public interface PushesFiles extends ExecutesMethod, CanRememberExtensionPresence { /** * Saves base64-encoded data as a file on the remote system. @@ -36,10 +39,16 @@ public interface PushesFiles extends ExecutesMethod { * @param base64Data Base64 encoded byte array of media file data to write to remote device */ default void pushFile(String remotePath, byte[] base64Data) { - CommandExecutionHelper.executeScript(this, "mobile: pushFile", ImmutableMap.of( - "remotePath", remotePath, - "payload", new String(base64Data, StandardCharsets.UTF_8) - )); + final String extName = "mobile: pushFile"; + try { + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + "remotePath", remotePath, + "payload", new String(base64Data, StandardCharsets.UTF_8) + )); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(markExtensionAbsence(extName), pushFileCommand(remotePath, base64Data)); + } } /** From 53d0f68da4d784c8b48d9866e2dab6adc99ebe67 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Wed, 10 May 2023 00:08:25 +0800 Subject: [PATCH 213/501] Release 8.5.0 and update release notes --- CHANGELOG.md | 10 ++++++++++ gradle.properties | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdf57b46d..1b8089b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +*8.5.0* +- **[BUG FIX]** + - Restore Jitpack builds. [#1911](https://github.com/appium/java-client/pull/1911) + - Add fallback commands for file management APIs. [#1910](https://github.com/appium/java-client/pull/1910) +- **[REFACTOR]** + - Replace performance data APIs with mobile extensions. [#1905](https://github.com/appium/java-client/pull/1905) +- **[DEPENDENCY UPDATES]** + - `org.seleniumhq.selenium:selenium-java` was updated to 4.9.1. + - `org.junit.jupiter:junit-jupiter` was updated to 5.9.3. + *8.4.0* - **[ENHANCEMENTS]** - Added possibility to connect to a running session. [#1813](https://github.com/appium/java-client/pull/1813) diff --git a/gradle.properties b/gradle.properties index 51f30e7f9..fca46f2cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.9.1 # Please increment the value in a release -appiumClient.version=8.4.0 +appiumClient.version=8.5.0 From 79106ef59cd4892bf055a28df4672f4da4ff7251 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 10 May 2023 07:31:24 +0300 Subject: [PATCH 214/501] fix: Use correct exception type for fallback at file/folder pulling (#1912) --- src/main/java/io/appium/java_client/PullsFiles.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/PullsFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java index 4b60a5748..c6d4e0898 100644 --- a/src/main/java/io/appium/java_client/PullsFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -17,6 +17,7 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.UnsupportedCommandException; import java.nio.charset.StandardCharsets; import java.util.AbstractMap; @@ -49,7 +50,7 @@ default byte[] pullFile(String remotePath) { ImmutableMap.of("remotePath", remotePath) ) ); - } catch (UnsupportedOperationException e) { + } catch (UnsupportedCommandException e) { // TODO: Remove the fallback base64String = checkNotNull( CommandExecutionHelper.execute(markExtensionAbsence(extName), @@ -81,7 +82,7 @@ default byte[] pullFolder(String remotePath) { ImmutableMap.of("remotePath", remotePath) ) ); - } catch (UnsupportedOperationException e) { + } catch (UnsupportedCommandException e) { // TODO: Remove the fallback base64String = checkNotNull( CommandExecutionHelper.execute(markExtensionAbsence(extName), From 35ac97204be620e0b3cc291472ac7c9568d37262 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 11 May 2023 22:17:24 +0200 Subject: [PATCH 215/501] fix: Update autoWebview capability name (#1917) --- .../java_client/remote/options/SupportsAutoWebViewOption.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java index 8a5d7e9fd..3cd2d7e93 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsAutoWebViewOption.java @@ -24,7 +24,7 @@ public interface SupportsAutoWebViewOption> extends Capabilities, CanSetCapability { - String AUTO_WEB_VIEW_OPTION = "autoWebView"; + String AUTO_WEB_VIEW_OPTION = "autoWebview"; /** * Set the app to move directly into Webview context. From 4560e23fd8d893ab5c64b5eb36392cb34b030097 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sat, 13 May 2023 23:04:01 +0300 Subject: [PATCH 216/501] ci: Move execution of E2E tests to GitHub Actions (#1913) --- .azure-templates/bootstrap_steps.yml | 10 -- .github/workflows/gradle.yml | 97 ++++++++++++++++++- azure-pipelines.yml | 69 ------------- .../appium/java_client/ios/BaseIOSTest.java | 1 + 4 files changed, 94 insertions(+), 83 deletions(-) delete mode 100644 .azure-templates/bootstrap_steps.yml delete mode 100644 azure-pipelines.yml diff --git a/.azure-templates/bootstrap_steps.yml b/.azure-templates/bootstrap_steps.yml deleted file mode 100644 index baf4b6979..000000000 --- a/.azure-templates/bootstrap_steps.yml +++ /dev/null @@ -1,10 +0,0 @@ -steps: - - task: NodeTool@0 - inputs: - versionSpec: "$(NODE_VERSION)" - - script: | - npm config delete prefix - npm config set prefix $NVM_DIR/versions/node/`node --version` - node --version - - npm install -g appium@next diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index cd399065c..872468fad 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -14,23 +14,112 @@ on: - 'docs/**' - '*.md' +env: + ANDROID_SDK_VERSION: 28 + ANDROID_EMU_NAME: test + XCODE_VERSION: 14.2 + IOS_DEVICE_NAME: iPhone 12 + IOS_PLATFORM_VERSION: 16.2 + jobs: build: - runs-on: macOS-latest - strategy: matrix: - java: [ 8, 11, 17 ] + include: + # TODO: add new LTS Java ( 21 ) once it's released + - java: 8 + platform: macos-latest + e2e-tests: android + - java: 11 + # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available + platform: macos-12 + e2e-tests: ios + - java: 17 + platform: ubuntu-latest + fail-fast: false + + runs-on: ${{ matrix.platform }} - name: JDK ${{ matrix.java }} + name: JDK ${{ matrix.java }} - ${{ matrix.platform }} steps: - uses: actions/checkout@v3 + - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: ${{ matrix.java }} cache: 'gradle' + - name: Build with Gradle run: ./gradlew clean build + + - name: Install Node.js + if: ${{ matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' }} + uses: actions/setup-node@v3 + with: + node-version: 'lts/*' + + - name: Install Appium + if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' + run: npm install -g appium@next + + - name: Install UIA2 driver + if: matrix.e2e-tests == 'android' + run: appium driver install uiautomator2 + + - name: AVD cache + if: matrix.e2e-tests == 'android' + uses: actions/cache@v3 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ env.ANDROID_SDK_VERSION }} + + - name: Generate AVD snapshot for caching + if: matrix.e2e-tests == 'android' && steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ env.ANDROID_SDK_VERSION }} + avd-name: ${{ env.ANDROID_EMU_NAME }} + force-avd-creation: false + script: echo "Generated AVD snapshot for caching." + + - name: Run Android E2E tests + if: matrix.e2e-tests == 'android' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ env.ANDROID_SDK_VERSION }} + avd-name: ${{ env.ANDROID_EMU_NAME }} + force-avd-creation: false + emulator-options: -no-snapshot -delay-adb + script: ./gradlew uiAutomationTest + + - name: Select Xcode + if: matrix.e2e-tests == 'ios' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: "${{ env.XCODE_VERSION }}" + + - name: Install XCUITest driver + if: matrix.e2e-tests == 'ios' + run: appium driver install xcuitest + + - name: Prebuild XCUITest driver + if: matrix.e2e-tests == 'ios' + run: appium driver run xcuitest build-wda + + - name: Prepare iOS simulator + if: matrix.e2e-tests == 'ios' + run: | + xcrun simctl list + target_sim_id=$(xcrun simctl list devices available | grep "$IOS_DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) + open -Fn "/Applications/Xcode_$XCODE_VERSION.app/Contents/Developer/Applications/Simulator.app" + xcrun simctl bootstatus $target_sim_id -b + + - name: Run iOS E2E tests + if: matrix.e2e-tests == 'ios' + run: ./gradlew xcuiTest diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 4cea8df6d..000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,69 +0,0 @@ -# Gradle -# Build your Java project and run tests with Gradle using a Gradle wrapper script. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/java - -pool: - vmImage: 'macos-12' - -variables: - ANDROID_EMU_NAME: test - ANDROID_EMU_ABI: x86 - ANDROID_EMU_TARGET: android-28 - ANDROID_EMU_TAG: default - XCODE_VERSION: 14.2 - IOS_PLATFORM_VERSION: 16.2 - IOS_DEVICE_NAME: iPhone 12 - NODE_VERSION: 18.x - JDK_VERSION: 1.8 - -jobs: -- job: Android_E2E_Tests - steps: - - template: .azure-templates/bootstrap_steps.yml - - script: $NVM_DIR/versions/node/`node --version`/bin/appium driver install uiautomator2 - displayName: Install UIA2 driver - - script: | - echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;$(ANDROID_EMU_TARGET);$(ANDROID_EMU_TAG);$(ANDROID_EMU_ABI)' - echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n "$(ANDROID_EMU_NAME)" -k 'system-images;$(ANDROID_EMU_TARGET);$(ANDROID_EMU_TAG);$(ANDROID_EMU_ABI)' --force - echo $ANDROID_HOME/emulator/emulator -list-avds - - echo "Starting emulator" - nohup $ANDROID_HOME/emulator/emulator -avd "$(ANDROID_EMU_NAME)" -no-snapshot -delay-adb > /dev/null 2>&1 & - $ANDROID_HOME/platform-tools/adb wait-for-device - $ANDROID_HOME/platform-tools/adb devices -l - echo "Emulator started" - displayName: Emulator configuration - - task: Gradle@2 - inputs: - gradleWrapperFile: 'gradlew' - gradleOptions: '-Xmx3072m' - javaHomeOption: 'JDKVersion' - jdkVersionOption: "$(JDK_VERSION)" - jdkArchitectureOption: 'x64' - publishJUnitResults: true - tasks: 'build uiAutomationTest' -- job: iOS_E2E_Tests -# timeoutInMinutes: '90' - steps: - - template: .azure-templates/bootstrap_steps.yml - - script: | - sudo xcode-select -s /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer - xcrun simctl list - target_sim_id=$(xcrun simctl list devices available | grep "$IOS_DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) - open -Fn "/Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer/Applications/Simulator.app" - xcrun simctl bootstatus $target_sim_id -b - displayName: Prepare iOS Simulator - - script: $NVM_DIR/versions/node/$(node --version)/bin/appium driver install xcuitest - displayName: Install XCUITest driver - - script: $NVM_DIR/versions/node/$(node --version)/bin/appium driver run xcuitest build-wda - displayName: Prebuild XCUITest driver - - task: Gradle@2 - inputs: - gradleWrapperFile: 'gradlew' - gradleOptions: '-Xmx3072m' - javaHomeOption: 'JDKVersion' - jdkVersionOption: "$(JDK_VERSION)" - jdkArchitectureOption: 'x64' - publishJUnitResults: true - tasks: 'build xcuiTest' diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index dfdf3c4da..1661e19c9 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -44,6 +44,7 @@ public static AppiumDriverLocalService startAppiumServer() { service = new AppiumServiceBuilder() .withIPAddress("127.0.0.1") .usingPort(PORT) + .withTimeout(Duration.ofSeconds(40)) .build(); service.start(); return service; From 925bab75572d0ab2478f77d87e68e1bdb7526542 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 15 May 2023 11:25:51 +0300 Subject: [PATCH 217/501] docs: Initiate Selenium client compatibility matrix (#1918) --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6825ba82c..104c256e4 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,20 @@ dependencies { } ``` -### How to pin Selenium dependencies? +### Compatibility Matrix +| Appium Java Client | Selenium client | +|--------------------|---------------------------------------------| +| `8.5.0` | `4.9.1` | +| `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` | +| `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` | +| `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` | + +#### Why is it so complicated? + +Selenium client does not follow [Semantic Versioning](https://semver.org/), so breaking changes might be introduced +even in patches, which requires Appium team to update Java client in response. + +#### How to pin Selenium dependencies? Appium Java Client declares Selenium dependencies using open version range which is handled in differently by different build tools. Sometimes users may want to pin used Selenium dependencies for [various reasons](https://github.com/appium/java-client/issues/1823). From 9cd90ed45684ca6771b368601793e5d486c6d152 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 15:33:25 +0300 Subject: [PATCH 218/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#1919) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.3.2 to 5.3.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.3.2...webdrivermanager-5.3.3) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7809cd92a..f494aa4a7 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.2') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.3') { exclude group: 'org.seleniumhq.selenium' } testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { From f2ac9e5ce197e41d5c0bb9fdb55be1b9e2114a57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 15:36:36 +0300 Subject: [PATCH 219/501] build(deps): Bump commons-io:commons-io from 2.11.0 to 2.12.0 (#1922) Bumps commons-io:commons-io from 2.11.0 to 2.12.0. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f494aa4a7..52bf70f38 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ dependencies { implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'commons-io:commons-io:2.11.0' + implementation 'commons-io:commons-io:2.12.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3' From 6af53a0a4ad4d08f8d42396969be5753e6d1929a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 25 May 2023 20:37:56 +0200 Subject: [PATCH 220/501] refactor: Replace cglib with bytebuddy (#1923) --- build.gradle | 1 - .../AppiumElementLocatorFactory.java | 4 +- .../pagefactory/AppiumFieldDecorator.java | 43 +++--- .../pagefactory/DefaultElementByBuilder.java | 6 +- .../pagefactory/ElementInterceptor.java | 7 +- .../pagefactory/ElementListInterceptor.java | 8 +- .../pagefactory/ThrowableUtil.java | 8 +- .../pagefactory/WidgetInterceptor.java | 50 ++++--- .../pagefactory/WidgetListInterceptor.java | 30 ++-- .../InterceptorOfAListOfElements.java | 21 ++- .../InterceptorOfASingleElement.java | 23 ++- .../pagefactory/utils/ProxyFactory.java | 61 ++++++-- .../utils/WebDriverUnpackUtility.java | 9 +- .../io/appium/java_client/proxy/Helpers.java | 67 +++++++-- .../appium/java_client/proxy/Interceptor.java | 17 +-- .../proxy/ProxyListenersContainer.java | 140 ++++++++++++++++++ .../widget/tests/WidgetTest.java | 1 - .../tests/combined/CombinedAppTest.java | 8 +- .../tests/combined/CombinedWidgetTest.java | 9 +- .../tests/windows/AnnotatedWindowsWidget.java | 15 -- .../tests/windows/DefaultWindowsWidget.java | 35 ----- .../tests/windows/ExtendedWindowsWidget.java | 9 -- .../widget/tests/windows/WindowsApp.java | 125 ---------------- .../tests/windows/WindowsWidgetTest.java | 51 ------- .../java_client/proxy/ProxyHelpersTest.java | 1 - 25 files changed, 355 insertions(+), 394 deletions(-) create mode 100644 src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java delete mode 100644 src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java diff --git a/build.gradle b/build.gradle index 52bf70f38..2c2371e99 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,6 @@ dependencies { } } implementation 'com.google.code.gson:gson:2.10.1' - implementation 'cglib:cglib:3.3.0' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'commons-io:commons-io:2.12.0' diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java index 170cffa38..0fc8e3d38 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -53,7 +53,9 @@ public AppiumElementLocatorFactory(SearchContext searchContext, Duration duratio return this.createLocator((AnnotatedElement) field); } - @Override public @Nullable CacheableLocator createLocator(AnnotatedElement annotatedElement) { + @Override + @Nullable + public CacheableLocator createLocator(AnnotatedElement annotatedElement) { Duration customDuration; if (annotatedElement.isAnnotationPresent(WithTimeout.class)) { WithTimeout withTimeout = annotatedElement.getAnnotation(WithTimeout.class); diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 8bb282859..b1119f34e 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -32,6 +32,7 @@ import org.openqa.selenium.support.pagefactory.ElementLocator; import org.openqa.selenium.support.pagefactory.FieldDecorator; +import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; @@ -92,17 +93,17 @@ public AppiumFieldDecorator(SearchContext context, Duration duration) { this.duration = duration; defaultElementFieldDecoracor = new DefaultFieldDecorator( - new AppiumElementLocatorFactory(context, duration, - new DefaultElementByBuilder(platform, automation))) { + new AppiumElementLocatorFactory(context, duration, new DefaultElementByBuilder(platform, automation)) + ) { @Override protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator) { return proxyForAnElement(locator); } @Override - @SuppressWarnings("unchecked") protected List proxyForListLocator(ClassLoader ignored, ElementLocator locator) { ElementListInterceptor elementInterceptor = new ElementListInterceptor(locator); + //noinspection unchecked return getEnhancedProxy(ArrayList.class, elementInterceptor); } @@ -121,14 +122,14 @@ protected boolean isDecoratableList(Field field) { List bounds = (listType instanceof TypeVariable) ? Arrays.asList(((TypeVariable) listType).getBounds()) : Collections.emptyList(); - return availableElementClasses.stream() .anyMatch((webElClass) -> webElClass.equals(listType) || bounds.contains(webElClass)); } }; - widgetLocatorFactory = - new AppiumElementLocatorFactory(context, duration, new WidgetByBuilder(platform, automation)); + widgetLocatorFactory = new AppiumElementLocatorFactory( + context, duration, new WidgetByBuilder(platform, automation) + ); } public AppiumFieldDecorator(SearchContext context) { @@ -144,14 +145,10 @@ public AppiumFieldDecorator(SearchContext context) { */ public Object decorate(ClassLoader ignored, Field field) { Object result = defaultElementFieldDecoracor.decorate(ignored, field); - if (result != null) { - return result; - } - - return decorateWidget(field); + return result == null ? decorateWidget(field) : result; } - @SuppressWarnings("unchecked") + @Nullable private Object decorateWidget(Field field) { Class type = field.getType(); if (!Widget.class.isAssignableFrom(type) && !List.class.isAssignableFrom(type)) { @@ -177,30 +174,34 @@ private Object decorateWidget(Field field) { if (!Widget.class.isAssignableFrom((Class) listType)) { return null; } + //noinspection unchecked widgetType = (Class) listType; } else { return null; } } else { + //noinspection unchecked widgetType = (Class) field.getType(); } CacheableLocator locator = widgetLocatorFactory.createLocator(field); - Map> map = - OverrideWidgetReader.read(widgetType, field, platform); + Map> map = OverrideWidgetReader.read(widgetType, field, platform); if (isAlist) { - return getEnhancedProxy(ArrayList.class, - new WidgetListInterceptor(locator, webDriver, map, widgetType, - duration)); + return getEnhancedProxy( + ArrayList.class, + new WidgetListInterceptor(locator, webDriver, map, widgetType, duration) + ); } - Constructor constructor = - WidgetConstructorUtil.findConvenientConstructor(widgetType); - return getEnhancedProxy(widgetType, new Class[]{constructor.getParameterTypes()[0]}, + Constructor constructor = WidgetConstructorUtil.findConvenientConstructor(widgetType); + return getEnhancedProxy( + widgetType, + new Class[]{constructor.getParameterTypes()[0]}, new Object[]{proxyForAnElement(locator)}, - new WidgetInterceptor(locator, webDriver, null, map, duration)); + new WidgetInterceptor(locator, webDriver, null, map, duration) + ); } private WebElement proxyForAnElement(ElementLocator locator) { diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index 512c978cc..23195e5ce 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -206,15 +206,13 @@ public By buildBy() { String idOrName = ((Field) annotatedElementContainer.getAnnotated()).getName(); if (defaultBy == null && mobileNativeBy == null) { - defaultBy = - new ByIdOrName(((Field) annotatedElementContainer.getAnnotated()).getName()); + defaultBy = new ByIdOrName(((Field) annotatedElementContainer.getAnnotated()).getName()); mobileNativeBy = new By.ById(idOrName); return returnMappedBy(defaultBy, mobileNativeBy); } if (defaultBy == null) { - defaultBy = - new ByIdOrName(((Field) annotatedElementContainer.getAnnotated()).getName()); + defaultBy = new ByIdOrName(((Field) annotatedElementContainer.getAnnotated()).getName()); return returnMappedBy(defaultBy, mobileNativeBy); } diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java index efe7bd95f..5047fcc11 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java @@ -28,13 +28,14 @@ /** * Intercepts requests to {@link WebElement}. */ -class ElementInterceptor extends InterceptorOfASingleElement { +public class ElementInterceptor extends InterceptorOfASingleElement { - ElementInterceptor(ElementLocator locator, WebDriver driver) { + public ElementInterceptor(ElementLocator locator, WebDriver driver) { super(locator, driver); } - @Override protected Object getObject(WebElement element, Method method, Object[] args) + @Override + protected Object getObject(WebElement element, Method method, Object[] args) throws Throwable { try { return method.invoke(element, args); diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java index fc7164533..77e68a329 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java @@ -28,14 +28,14 @@ /** * Intercepts requests to the list of {@link WebElement}. */ -class ElementListInterceptor extends InterceptorOfAListOfElements { +public class ElementListInterceptor extends InterceptorOfAListOfElements { - ElementListInterceptor(ElementLocator locator) { + public ElementListInterceptor(ElementLocator locator) { super(locator); } - @Override protected Object getObject(List elements, Method method, Object[] args) - throws Throwable { + @Override + protected Object getObject(List elements, Method method, Object[] args) throws Throwable { try { return method.invoke(elements, args); } catch (Throwable t) { diff --git a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java index ca65e9e24..c025a53dd 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java +++ b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java @@ -33,8 +33,8 @@ protected static boolean isInvalidSelectorRootCause(Throwable e) { return true; } - if (String.valueOf(e.getMessage()).contains(INVALID_SELECTOR_PATTERN) || String - .valueOf(e.getMessage()).contains("Locator Strategy \\w+ is not supported")) { + if (String.valueOf(e.getMessage()).contains(INVALID_SELECTOR_PATTERN) + || String.valueOf(e.getMessage()).contains("Locator Strategy \\w+ is not supported")) { return true; } @@ -54,8 +54,8 @@ protected static boolean isStaleElementReferenceException(Throwable e) { } protected static Throwable extractReadableException(Throwable e) { - if (!RuntimeException.class.equals(e.getClass()) && !InvocationTargetException.class - .equals(e.getClass())) { + if (!RuntimeException.class.equals(e.getClass()) + && !InvocationTargetException.class.equals(e.getClass())) { return e; } diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java index 2c3296d35..9a9d1133d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java @@ -19,55 +19,62 @@ import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.interceptors.InterceptorOfASingleElement; import io.appium.java_client.pagefactory.locator.CacheableLocator; -import net.sf.cglib.proxy.MethodProxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.PageFactory; +import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.time.Duration; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Callable; import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; -class WidgetInterceptor extends InterceptorOfASingleElement { +public class WidgetInterceptor extends InterceptorOfASingleElement { private final Map> instantiationMap; private final Map cachedInstances = new HashMap<>(); private final Duration duration; private WebElement cachedElement; - WidgetInterceptor(CacheableLocator locator, WebDriver driver, WebElement cachedElement, - Map> instantiationMap, - Duration duration) { + /** + * Proxy interceptor class for widgets. + */ + public WidgetInterceptor( + CacheableLocator locator, + WebDriver driver, + @Nullable + WebElement cachedElement, + Map> instantiationMap, + Duration duration + ) { super(locator, driver); this.cachedElement = cachedElement; this.instantiationMap = instantiationMap; this.duration = duration; } - - @Override protected Object getObject(WebElement element, Method method, Object[] args) - throws Throwable { + @Override + protected Object getObject(WebElement element, Method method, Object[] args) throws Throwable { ContentType type = getCurrentContentType(element); if (cachedElement == null - || (locator != null && !((CacheableLocator) locator) - .isLookUpCached()) - || cachedInstances.size() == 0) { + || (locator != null && !((CacheableLocator) locator).isLookUpCached()) + || cachedInstances.isEmpty() + ) { cachedElement = element; Constructor constructor = instantiationMap.get(type); Class clazz = constructor.getDeclaringClass(); - int modifiers = clazz.getModifiers(); - if (Modifier.isAbstract(modifiers)) { - throw new InstantiationException(clazz.getName() - + " is abstract so " - + "it can't be instantiated"); + if (Modifier.isAbstract(clazz.getModifiers())) { + throw new InstantiationException( + String.format("%s is abstract so it cannot be instantiated", clazz.getName()) + ); } Widget widget = constructor.newInstance(cachedElement); @@ -82,11 +89,10 @@ class WidgetInterceptor extends InterceptorOfASingleElement { } } - public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) - throws Throwable { - if (locator != null) { - return super.intercept(obj, method, args, proxy); - } - return getObject(cachedElement, method, args); + @Override + public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { + return locator == null + ? getObject(cachedElement, method, args) + : super.call(obj, method, args, original); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java index 04115aaa9..136ce8e4d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java @@ -19,7 +19,6 @@ import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.interceptors.InterceptorOfAListOfElements; import io.appium.java_client.pagefactory.locator.CacheableLocator; -import io.appium.java_client.pagefactory.utils.ProxyFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -31,11 +30,11 @@ import java.util.Map; import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; +import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; import static java.util.Optional.ofNullable; -class WidgetListInterceptor extends InterceptorOfAListOfElements { - +public class WidgetListInterceptor extends InterceptorOfAListOfElements { private final Map> instantiationMap; private final List cachedWidgets = new ArrayList<>(); private final Class declaredType; @@ -43,7 +42,10 @@ class WidgetListInterceptor extends InterceptorOfAListOfElements { private final WebDriver driver; private List cachedElements; - WidgetListInterceptor(CacheableLocator locator, WebDriver driver, + /** + * Proxy interceptor class for lists of widgets. + */ + public WidgetListInterceptor(CacheableLocator locator, WebDriver driver, Map> instantiationMap, Class declaredType, Duration duration) { super(locator); @@ -53,22 +55,22 @@ class WidgetListInterceptor extends InterceptorOfAListOfElements { this.driver = driver; } - - @Override protected Object getObject(List elements, Method method, Object[] args) - throws Throwable { - if (cachedElements == null || (locator != null && !((CacheableLocator) locator) - .isLookUpCached())) { + @Override + protected Object getObject(List elements, Method method, Object[] args) throws Throwable { + if (cachedElements == null || (locator != null && !((CacheableLocator) locator).isLookUpCached())) { cachedElements = elements; cachedWidgets.clear(); ContentType type = null; for (WebElement element : cachedElements) { type = ofNullable(type).orElseGet(() -> getCurrentContentType(element)); - Class[] params = - new Class[] {instantiationMap.get(type).getParameterTypes()[0]}; - cachedWidgets.add(ProxyFactory - .getEnhancedProxy(declaredType, params, new Object[] {element}, - new WidgetInterceptor(null, driver, element, instantiationMap, duration))); + Class[] params = new Class[] {instantiationMap.get(type).getParameterTypes()[0]}; + cachedWidgets.add( + getEnhancedProxy( + declaredType, params, new Object[] {element}, + new WidgetInterceptor(null, driver, element, instantiationMap, duration) + ) + ); } } try { diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java index 8b96c6c68..d276ce616 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java @@ -16,33 +16,30 @@ package io.appium.java_client.pagefactory.interceptors; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; +import io.appium.java_client.proxy.MethodCallListener; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; -public abstract class InterceptorOfAListOfElements implements MethodInterceptor { +public abstract class InterceptorOfAListOfElements implements MethodCallListener { protected final ElementLocator locator; public InterceptorOfAListOfElements(ElementLocator locator) { this.locator = locator; } - protected abstract Object getObject(List elements, Method method, Object[] args) - throws InvocationTargetException, IllegalAccessException, InstantiationException, Throwable; + protected abstract Object getObject( + List elements, Method method, Object[] args + ) throws Throwable; - /** - * Look at {@link MethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}. - */ - public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) - throws Throwable { + @Override + public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { - return proxy.invokeSuper(obj, args); + return original.call(); } List realElements = new ArrayList<>(locator.findElements()); diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java index d06555eaf..7ac12b3d6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java @@ -16,16 +16,16 @@ package io.appium.java_client.pagefactory.interceptors; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; +import io.appium.java_client.proxy.MethodCallListener; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.WrapsDriver; import org.openqa.selenium.support.pagefactory.ElementLocator; import java.lang.reflect.Method; +import java.util.concurrent.Callable; -public abstract class InterceptorOfASingleElement implements MethodInterceptor { +public abstract class InterceptorOfASingleElement implements MethodCallListener { protected final ElementLocator locator; protected final WebDriver driver; @@ -34,25 +34,20 @@ public InterceptorOfASingleElement(ElementLocator locator, WebDriver driver) { this.driver = driver; } - protected abstract Object getObject(WebElement element, Method method, Object[] args) - throws Throwable; - - /** - * Look at {@link MethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}. - */ - public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) - throws Throwable { + protected abstract Object getObject(WebElement element, Method method, Object[] args) throws Throwable; + @Override + public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { if (method.getName().equals("toString") && args.length == 0) { return locator.toString(); } if (Object.class.equals(method.getDeclaringClass())) { - return proxy.invokeSuper(obj, args); + return original.call(); } - if (WrapsDriver.class.isAssignableFrom(method.getDeclaringClass()) && method.getName() - .equals("getWrappedDriver")) { + if (WrapsDriver.class.isAssignableFrom(method.getDeclaringClass()) + && method.getName().equals("getWrappedDriver")) { return driver; } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java index 390ebcd92..d0b8e4832 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java @@ -16,43 +16,76 @@ package io.appium.java_client.pagefactory.utils; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.MethodInterceptor; +import io.appium.java_client.proxy.MethodCallListener; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import static io.appium.java_client.proxy.Helpers.OBJECT_METHOD_NAMES; +import static io.appium.java_client.proxy.Helpers.createProxy; +import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; /** * Original class is a super class of a * proxy object here. */ public final class ProxyFactory { + private static final Set NON_PROXYABLE_METHODS = setWithout(OBJECT_METHOD_NAMES, "toString"); + + @SuppressWarnings("unchecked") + private static Set setWithout(@SuppressWarnings("SameParameterValue") Set source, T... items) { + Set result = new HashSet<>(source); + Arrays.asList(items).forEach(result::remove); + return Collections.unmodifiableSet(result); + } private ProxyFactory() { super(); } - public static T getEnhancedProxy(Class requiredClazz, MethodInterceptor interceptor) { - return getEnhancedProxy(requiredClazz, new Class[] {}, new Object[] {}, interceptor); + /** + * Creates a proxy instance for the given class with an empty constructor. + * + * @param The proxy object class. + * @param requiredClazz is a {@link java.lang.Class} whose instance should be created + * @param listener is the instance of a method listener class + * @return a proxied instance of the desired class + */ + public static T getEnhancedProxy(Class requiredClazz, MethodCallListener listener) { + return getEnhancedProxy(requiredClazz, new Class[] {}, new Object[] {}, listener); } /** - * It returns some proxies created by CGLIB. + * Creates a proxy instance for the given class. * * @param The proxy object class. - * @param requiredClazz is a {@link java.lang.Class} whose instance should be created + * @param cls is a {@link java.lang.Class} whose instance should be created * @param params is an array of @link java.lang.Class}. It should be convenient to * parameter types of some declared constructor which belongs to desired * class. * @param values is an array of @link java.lang.Object}. It should be convenient to * parameter types of some declared constructor which belongs to desired * class. - * @param interceptor is the instance of {@link net.sf.cglib.proxy.MethodInterceptor} + * @param listener is the instance of a method listener class * @return a proxied instance of the desired class */ - @SuppressWarnings("unchecked") - public static T getEnhancedProxy(Class requiredClazz, Class[] params, Object[] values, - MethodInterceptor interceptor) { - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(requiredClazz); - enhancer.setCallback(interceptor); - return (T) enhancer.create(params, values); + public static T getEnhancedProxy( + Class cls, Class[] params, Object[] values, MethodCallListener listener + ) { + ElementMatcher extraMatcher = ElementMatchers.not(namedOneOf( + NON_PROXYABLE_METHODS.toArray(new String[0]) + )); + return createProxy( + cls, + values, + params, + Collections.singletonList(listener), + extraMatcher + ); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index e6bb6f6d6..53ba1506c 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -24,6 +24,8 @@ import org.openqa.selenium.WrapsDriver; import org.openqa.selenium.WrapsElement; +import javax.annotation.Nullable; + import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; import static java.util.Optional.ofNullable; @@ -45,21 +47,20 @@ public final class WebDriverUnpackUtility { * {@link WrapsDriver} or {@link WrapsElement} then this method returns null. * */ + @Nullable public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchContext) { if (searchContext instanceof WebDriver) { return (WebDriver) searchContext; } if (searchContext instanceof WrapsDriver) { - return unpackWebDriverFromSearchContext( - ((WrapsDriver) searchContext).getWrappedDriver()); + return unpackWebDriverFromSearchContext(((WrapsDriver) searchContext).getWrappedDriver()); } // Search context it is not only WebDriver. WebElement is search context too. // RemoteWebElement implements WrapsDriver if (searchContext instanceof WrapsElement) { - return unpackWebDriverFromSearchContext( - ((WrapsElement) searchContext).getWrappedElement()); + return unpackWebDriverFromSearchContext(((WrapsElement) searchContext).getWrappedElement()); } return null; diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index 286d7fc31..2dd5912ca 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -18,14 +18,28 @@ import com.google.common.base.Preconditions; import net.bytebuddy.ByteBuddy; +import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; import net.bytebuddy.implementation.MethodDelegation; +import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatchers; +import javax.annotation.Nullable; +import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; public class Helpers { + + public static final Set OBJECT_METHOD_NAMES = Stream.of(Object.class.getMethods()) + .map(Method::getName) + .collect(Collectors.toSet()); + private Helpers() { } @@ -53,6 +67,40 @@ public static T createProxy( Object[] constructorArgs, Class[] constructorArgTypes, Collection listeners + ) { + ElementMatcher extraMatcher = ElementMatchers.not(namedOneOf( + OBJECT_METHOD_NAMES.toArray(new String[0]) + )); + return createProxy(cls, constructorArgs, constructorArgTypes, listeners, extraMatcher); + } + + /** + * Creates a transparent proxy instance for the given class. + * It is possible to provide one or more method execution listeners + * or replace particular method calls completely. Callbacks + * defined in these listeners are going to be called when any + * **public** method of the given class is invoked. Overridden callbacks + * are expected to be skipped if they throw + * {@link io.appium.java_client.proxy.NotImplementedException}. + * !!! This API is designed for private usage. + * + * @param cls The class to which the proxy should be created. + * Must not be an interface. + * @param constructorArgs Array of constructor arguments. Could be an + * empty array if the class provides a constructor without arguments. + * @param constructorArgTypes Array of constructor argument types. Must + * represent types of constructorArgs. + * @param listeners One or more method invocation listeners. + * @param extraMethodMatcher Optional additional method proxy conditions + * @param Any class derived from Object + * @return Proxy instance + */ + public static T createProxy( + Class cls, + Object[] constructorArgs, + Class[] constructorArgTypes, + Collection listeners, + @Nullable ElementMatcher extraMethodMatcher ) { Preconditions.checkArgument(constructorArgs.length == constructorArgTypes.length, String.format( @@ -64,27 +112,22 @@ public static T createProxy( Preconditions.checkArgument(cls != null, "Class must not be null"); Preconditions.checkArgument(!cls.isInterface(), "Class must not be an interface"); + ElementMatcher.Junction matcher = ElementMatchers.isPublic(); //noinspection resource Class proxy = new ByteBuddy() .subclass(cls) - .method(ElementMatchers.isPublic() - .and(ElementMatchers.not( - ElementMatchers.isDeclaredBy(Object.class) - .or(ElementMatchers.isOverriddenFrom(Object.class)) - ))) + .method(extraMethodMatcher == null ? matcher : matcher.and(extraMethodMatcher)) .intercept(MethodDelegation.to(Interceptor.class)) .make() - .load(cls.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) + .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded() .asSubclass(cls); try { - //noinspection unchecked - T instance = (T) proxy - .getConstructor(constructorArgTypes) - .newInstance(constructorArgs); - Interceptor.LISTENERS.put(instance, listeners); - return instance; + return ProxyListenersContainer.getInstance().setListeners( + cls.cast(proxy.getConstructor(constructorArgTypes).newInstance(constructorArgs)), + listeners + ); } catch (SecurityException | ReflectiveOperationException e) { throw new IllegalStateException(String.format("Unable to create a proxy of %s", cls.getName()), e); } diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java index d343fc9c1..dce2fd807 100644 --- a/src/main/java/io/appium/java_client/proxy/Interceptor.java +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -26,20 +26,11 @@ import java.lang.reflect.Method; import java.util.Collection; -import java.util.Map; -import java.util.Set; import java.util.UUID; -import java.util.WeakHashMap; import java.util.concurrent.Callable; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class Interceptor { private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); - public static final Map> LISTENERS = new WeakHashMap<>(); - private static final Set OBJECT_METHOD_NAMES = Stream.of(Object.class.getMethods()) - .map(Method::getName) - .collect(Collectors.toSet()); /** * A magic method used to wrap public method calls in classes @@ -51,6 +42,7 @@ public class Interceptor { * @param callable The reference to the non-patched callable to avoid call recursion. * @return Either the original method result or the patched one. */ + @SuppressWarnings("unused") @RuntimeType public static Object intercept( @This Object self, @@ -58,11 +50,8 @@ public static Object intercept( @AllArguments Object[] args, @SuperCall Callable callable ) throws Throwable { - if (OBJECT_METHOD_NAMES.contains(method.getName())) { - return callable.call(); - } - Collection listeners = LISTENERS.get(self); - if (listeners == null || listeners.isEmpty()) { + Collection listeners = ProxyListenersContainer.getInstance().getListeners(self); + if (listeners.isEmpty()) { return callable.call(); } diff --git a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java new file mode 100644 index 000000000..4b314b02b --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java @@ -0,0 +1,140 @@ +/* + * 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.proxy; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Semaphore; + +class ProxyListenersContainer { + private static ProxyListenersContainer INSTANCE; + + public static synchronized ProxyListenersContainer getInstance() { + if (INSTANCE == null) { + INSTANCE = new ProxyListenersContainer(); + } + return INSTANCE; + } + + private final Semaphore listenersGuard = new Semaphore(1); + // Previously WeakHashMap has been used because of O(1) lookup performance, although + // we had to change it to a list, which has O(N). The reason for that is that + // maps implicitly call `hashCode` API on instances, which might not always + // work as expected for arbitrary proxies + private final List, Collection>> listeners = new LinkedList<>(); + + private static class Pair { + private final K key; + private final V value; + + public Pair(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + } + + private ProxyListenersContainer() { + } + + /** + * Assign listeners for the particular proxied instance. + * + * @param proxyInstance The proxied instance. + * @param listeners Collection of listeners. + * @return The same given instance. + */ + public T setListeners(T proxyInstance, Collection listeners) { + try { + listenersGuard.acquire(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + try { + int i = 0; + boolean wasInstancePresent = false; + while (i < this.listeners.size()) { + Pair, Collection> pair = this.listeners.get(i); + Object key = pair.getKey().get(); + if (key == null) { + // The instance has been garbage-collected + this.listeners.remove(i); + continue; + } + + if (key == proxyInstance) { + pair.getValue().clear(); + pair.getValue().addAll(listeners); + wasInstancePresent = true; + } + i++; + } + if (!wasInstancePresent) { + this.listeners.add(new Pair<>(new WeakReference<>(proxyInstance), new HashSet<>(listeners))); + } + } finally { + listenersGuard.release(); + } + return proxyInstance; + } + + /** + * Fetches listeners for the particular proxied instance. + * + * @param proxyInstance The proxied instance. + */ + public Collection getListeners(Object proxyInstance) { + try { + listenersGuard.acquire(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + try { + int i = 0; + Collection result = Collections.emptySet(); + while (i < listeners.size()) { + Pair, Collection> pair = listeners.get(i); + Object key = pair.getKey().get(); + if (key == null) { + // The instance has been garbage-collected + listeners.remove(i); + continue; + } + + if (key == proxyInstance) { + result = pair.getValue(); + } + i++; + } + return result; + } finally { + listenersGuard.release(); + } + } + +} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java index 6e1f4ab2b..2f8e2d60d 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/WidgetTest.java @@ -37,7 +37,6 @@ protected WidgetTest(AbstractApp app, WebDriver driver) { protected static void checkThatLocatorsAreCreatedCorrectly(DefaultStubWidget single, List multiple, By rootLocator, By subLocator) { - assertThat(single.toString(), containsString(rootLocator.toString())); assertThat(multiple.stream().map(DefaultStubWidget::toString).collect(toList()), contains(containsString(rootLocator.toString()), diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index 2a453c2d9..c3ee905fb 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -6,7 +6,6 @@ import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; -import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -35,7 +34,6 @@ public static Stream data() { arguments(new CombinedApp(), new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), arguments(new CombinedApp(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultIosXCUITWidget.class), - arguments(new CombinedApp(), new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), arguments(new CombinedApp(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), arguments(new CombinedApp(), new AbstractStubWebDriver.StubAndroidBrowserOrWebViewDriver(), DefaultFindByWidget.class), @@ -72,14 +70,12 @@ public static class CombinedApp implements AbstractApp { @OverrideWidget(html = DefaultFindByWidget.class, androidUIAutomator = DefaultAndroidWidget.class, - iOSXCUITAutomation = DefaultIosXCUITWidget.class, - windowsAutomation = DefaultWindowsWidget.class) + iOSXCUITAutomation = DefaultIosXCUITWidget.class) private DefaultStubWidget singleWidget; @OverrideWidget(html = DefaultFindByWidget.class, androidUIAutomator = DefaultAndroidWidget.class, - iOSXCUITAutomation = DefaultIosXCUITWidget.class, - windowsAutomation = DefaultWindowsWidget.class) + iOSXCUITAutomation = DefaultIosXCUITWidget.class) private List multipleWidget; @Override diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java index d54e3618c..3c1c9145d 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java @@ -6,7 +6,6 @@ import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; -import io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -38,8 +37,6 @@ public static Stream data() { new AbstractStubWebDriver.StubAndroidDriver(), DefaultAndroidWidget.class), Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubIOSXCUITDriver(), DefaultIosXCUITWidget.class), - Arguments.of(new AppWithCombinedWidgets(), - new AbstractStubWebDriver.StubWindowsDriver(), DefaultWindowsWidget.class), Arguments.of(new AppWithCombinedWidgets(), new AbstractStubWebDriver.StubBrowserDriver(), DefaultFindByWidget.class), Arguments.of(new AppWithCombinedWidgets(), @@ -79,15 +76,13 @@ public static class CombinedWidget extends DefaultStubWidget { @OverrideWidget(html = DefaultFindByWidget.class, androidUIAutomator = DefaultAndroidWidget.class, - iOSXCUITAutomation = DefaultIosXCUITWidget.class, - windowsAutomation = DefaultWindowsWidget.class + iOSXCUITAutomation = DefaultIosXCUITWidget.class ) private DefaultStubWidget singleWidget; @OverrideWidget(html = DefaultFindByWidget.class, androidUIAutomator = DefaultAndroidWidget.class, - iOSXCUITAutomation = DefaultIosXCUITWidget.class, - windowsAutomation = DefaultWindowsWidget.class + iOSXCUITAutomation = DefaultIosXCUITWidget.class ) private List multipleWidget; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java deleted file mode 100644 index 733d0db95..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/AnnotatedWindowsWidget.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.appium.java_client.pagefactory_tests.widget.tests.windows; - -import io.appium.java_client.pagefactory.WindowsFindBy; -import io.appium.java_client.pagefactory.iOSXCUITFindBy; -import org.openqa.selenium.WebElement; - -@WindowsFindBy(windowsAutomation = "SOME_ROOT_LOCATOR") -@iOSXCUITFindBy(iOSNsPredicate = "XCUIT_SOME_ROOT_LOCATOR") -public class AnnotatedWindowsWidget extends DefaultWindowsWidget { - public static String WINDOWS_ROOT_WIDGET_LOCATOR = "SOME_ROOT_LOCATOR"; - - protected AnnotatedWindowsWidget(WebElement element) { - super(element); - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java deleted file mode 100644 index ab7b81a41..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/DefaultWindowsWidget.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.appium.java_client.pagefactory_tests.widget.tests.windows; - -import io.appium.java_client.pagefactory.WindowsFindBy; -import io.appium.java_client.pagefactory.iOSXCUITFindBy; -import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; -import org.openqa.selenium.WebElement; - -import java.util.List; - -public class DefaultWindowsWidget extends DefaultStubWidget { - - public static String WINDOWS_SUB_WIDGET_LOCATOR = "SOME_SUB_LOCATOR"; - - @WindowsFindBy(windowsAutomation = "SOME_SUB_LOCATOR") - @iOSXCUITFindBy(iOSNsPredicate = "XCUIT_SOME_SUB_LOCATOR") - private DefaultWindowsWidget singleWidget; - - @WindowsFindBy(windowsAutomation = "SOME_SUB_LOCATOR") - @iOSXCUITFindBy(iOSNsPredicate = "XCUIT_SOME_SUB_LOCATOR") - private List multipleWidgets; - - protected DefaultWindowsWidget(WebElement element) { - super(element); - } - - @Override - public DefaultWindowsWidget getSubWidget() { - return singleWidget; - } - - @Override - public List getSubWidgets() { - return multipleWidgets; - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java deleted file mode 100644 index 14cc95f65..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/ExtendedWindowsWidget.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.appium.java_client.pagefactory_tests.widget.tests.windows; - -import org.openqa.selenium.WebElement; - -public class ExtendedWindowsWidget extends AnnotatedWindowsWidget { - protected ExtendedWindowsWidget(WebElement element) { - super(element); - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java deleted file mode 100644 index 07eb5784d..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsApp.java +++ /dev/null @@ -1,125 +0,0 @@ -package io.appium.java_client.pagefactory_tests.widget.tests.windows; - -import io.appium.java_client.AppiumBy; -import io.appium.java_client.pagefactory.WindowsFindBy; -import io.appium.java_client.pagefactory.iOSXCUITFindBy; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; - -import java.util.List; - -public class WindowsApp implements ExtendedApp { - - public static String WINDOWS_DEFAULT_WIDGET_LOCATOR = "SOME_WINDOWS_DEFAULT_LOCATOR"; - - public static String WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR"; - - @WindowsFindBy(windowsAutomation = "SOME_WINDOWS_DEFAULT_LOCATOR") - @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_DEFAULT_LOCATOR") - private DefaultWindowsWidget singleIosWidget; - - @WindowsFindBy(windowsAutomation = "SOME_WINDOWS_DEFAULT_LOCATOR") - @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_DEFAULT_LOCATOR") - private List multipleIosWidgets; - - /** - * This class is annotated by {@link WindowsFindBy} and - * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. - * This field was added to check that locator is created correctly according to current platform. - * It is expected that the root element and sub-elements are found using - * {@link AppiumBy#windowsAutomation(String)} - */ - private AnnotatedWindowsWidget singleAnnotatedIosWidget; - - /** - * This class is annotated by {@link WindowsFindBy} and - * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. - * This field was added to check that locator is created correctly according to current platform. - * It is expected that the root element and sub-elements are found using - * {@link AppiumBy#windowsAutomation(String)}. - */ - private List multipleIosIosWidgets; - - /** - * This class is not annotated by {@link WindowsFindBy} and - * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. - * But the superclass is annotated by these annotations. This field was added to check that locator is - * created correctly according to current platform. - * It is expected that the root element and sub-elements are found using - * {@link AppiumBy#windowsAutomation(String)}. - */ - private ExtendedWindowsWidget singleExtendedIosWidget; - - /** - * This class is not annotated by {@link WindowsFindBy} and - * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. - * But the superclass is annotated by these annotations. This field was added to check that locator is - * created correctly according to current platform. - * It is expected that the root element and sub-elements are found using - * {@link AppiumBy#windowsAutomation(String)}. - */ - private List multipleExtendedIosWidgets; - - /** - * This class is not annotated by {@link WindowsFindBy} and - * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. - * But the superclass is annotated by these annotations. This field was added to check that locator is - * created correctly according to current platform. - * It is expected that the root element and sub-elements are found using - * {@link AppiumBy#windowsAutomation(String)}. - */ - @WindowsFindBy(windowsAutomation = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR") - @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_EXTERNALLY_DEFINED_LOCATOR") - private ExtendedWindowsWidget singleOverriddenIosWidget; - - /** - * This class is not annotated by {@link WindowsFindBy} and - * {@link io.appium.java_client.pagefactory.iOSXCUITFindBy}. - * But the superclass is annotated by these annotations. This field was added to check that locator is - * created correctly according to current platform. - * It is expected that the root element and sub-elements are found using - * {@link AppiumBy#windowsAutomation(String)}. - */ - @WindowsFindBy(windowsAutomation = "WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR") - @iOSXCUITFindBy(iOSNsPredicate = "SOME_XCUIT_EXTERNALLY_DEFINED_LOCATOR") - private List multipleOverriddenIosWidgets; - - @Override - public DefaultWindowsWidget getWidget() { - return singleIosWidget; - } - - @Override - public List getWidgets() { - return multipleIosWidgets; - } - - @Override - public DefaultWindowsWidget getAnnotatedWidget() { - return singleAnnotatedIosWidget; - } - - @Override - public List getAnnotatedWidgets() { - return multipleIosIosWidgets; - } - - @Override - public DefaultWindowsWidget getExtendedWidget() { - return singleExtendedIosWidget; - } - - @Override - public List getExtendedWidgets() { - return multipleExtendedIosWidgets; - } - - @Override - public DefaultWindowsWidget getExtendedWidgetWithOverriddenLocators() { - return singleOverriddenIosWidget; - } - - @Override - public List getExtendedWidgetsWithOverriddenLocators() { - return multipleOverriddenIosWidgets; - } -} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java deleted file mode 100644 index 023b24819..000000000 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/windows/WindowsWidgetTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.appium.java_client.pagefactory_tests.widget.tests.windows; - -import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; -import io.appium.java_client.pagefactory_tests.widget.tests.ExtendedApp; -import io.appium.java_client.pagefactory_tests.widget.tests.WidgetTest; -import org.junit.jupiter.api.Test; - -import static io.appium.java_client.MobileBy.windowsAutomation; -import static io.appium.java_client.pagefactory_tests.widget.tests.windows.AnnotatedWindowsWidget.WINDOWS_ROOT_WIDGET_LOCATOR; -import static io.appium.java_client.pagefactory_tests.widget.tests.windows.DefaultWindowsWidget.WINDOWS_SUB_WIDGET_LOCATOR; -import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_DEFAULT_WIDGET_LOCATOR; -import static io.appium.java_client.pagefactory_tests.widget.tests.windows.WindowsApp.WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR; - -public class WindowsWidgetTest extends WidgetTest { - - public WindowsWidgetTest() { - super(new WindowsApp(), new AbstractStubWebDriver.StubWindowsDriver()); - } - - @Test - @Override - public void checkThatWidgetsAreCreatedCorrectly() { - checkThatLocatorsAreCreatedCorrectly(app.getWidget(), app.getWidgets(), - windowsAutomation(WINDOWS_DEFAULT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); - } - - @Test - @Override - public void checkCaseWhenWidgetClassHasDeclaredLocatorAnnotation() { - checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getAnnotatedWidget(), - ((ExtendedApp) app).getAnnotatedWidgets(), - windowsAutomation(WINDOWS_ROOT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); - } - - @Test - @Override - public void checkCaseWhenWidgetClassHasNoDeclaredAnnotationButItHasSuperclass() { - checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidget(), - ((ExtendedApp) app).getExtendedWidgets(), - windowsAutomation(WINDOWS_ROOT_WIDGET_LOCATOR), windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); - } - - @Test - @Override - public void checkCaseWhenBothWidgetFieldAndClassHaveDeclaredAnnotations() { - checkThatLocatorsAreCreatedCorrectly(((ExtendedApp) app).getExtendedWidgetWithOverriddenLocators(), - ((ExtendedApp) app).getExtendedWidgetsWithOverriddenLocators(), - windowsAutomation(WINDOWS_EXTERNALLY_DEFINED_WIDGET_LOCATOR), - windowsAutomation(WINDOWS_SUB_WIDGET_LOCATOR)); - } -} diff --git a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java index 218c56270..a8767629d 100644 --- a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java +++ b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java @@ -93,7 +93,6 @@ public Object onError(Object obj, Method method, Object[] args, Throwable e) { } }; RemoteWebDriver driver = createProxy(RemoteWebDriver.class, Collections.singletonList(listener)); - assertThrows( IllegalStateException.class, () -> driver.get("http://example.com/") From a42ba4d918a8a5b223b93391aee529fec0e72b73 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 29 May 2023 11:16:17 +0000 Subject: [PATCH 221/501] chore: Improve the error message on service startup (#1928) --- .../local/AppiumDriverLocalService.java | 57 +++++++++++++------ .../service/local/AppiumServiceBuilder.java | 15 ++--- .../service/local/ServerBuilderTest.java | 6 +- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index d2b4d37fc..08f289289 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -35,6 +35,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -46,7 +47,8 @@ import java.util.regex.Pattern; import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP_ADDRESS; +import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; +import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP6_ADDRESS; import static org.slf4j.event.Level.DEBUG; import static org.slf4j.event.Level.INFO; @@ -57,6 +59,7 @@ public final class AppiumDriverLocalService extends DriverService { private static final Pattern LOGGER_CONTEXT_PATTERN = Pattern.compile("^(\\[debug\\] )?\\[(.+?)\\]"); private static final String APPIUM_SERVICE_SLF4J_LOGGER_PREFIX = "appium.service"; private static final Duration DESTROY_TIMEOUT = Duration.ofSeconds(60); + private static final Duration IS_RUNNING_PING_TIMEOUT = Duration.ofMillis(1500); private final File nodeJSExec; private final List nodeJSArgs; @@ -106,7 +109,7 @@ private static URL addSuffix(URL url, String suffix) { @SneakyThrows @SuppressWarnings("SameParameterValue") private static URL replaceHost(URL source, String oldHost, String newHost) { - return new URL(source.toString().replace(oldHost, newHost)); + return new URL(source.toString().replaceFirst(oldHost, newHost)); } /** @@ -128,7 +131,7 @@ public boolean isRunning() { } try { - ping(Duration.ofMillis(1500)); + ping(IS_RUNNING_PING_TIMEOUT); return true; } catch (UrlChecker.TimeoutException e) { return false; @@ -142,8 +145,15 @@ public boolean isRunning() { } private void ping(Duration timeout) throws UrlChecker.TimeoutException, MalformedURLException { - // The operating system might block direct access to the universal broadcast IP address - URL status = addSuffix(replaceHost(getUrl(), BROADCAST_IP_ADDRESS, "127.0.0.1"), "/status"); + URL url = getUrl(); + String host = url.getHost(); + // The operating system will block direct access to the universal broadcast IP address + if (host.equals(BROADCAST_IP4_ADDRESS)) { + url = replaceHost(url, BROADCAST_IP4_ADDRESS, "127.0.0.1"); + } else if (host.equals(BROADCAST_IP6_ADDRESS)) { + url = replaceHost(url, BROADCAST_IP6_ADDRESS, "::1"); + } + URL status = addSuffix(url, "/status"); new UrlChecker().waitUntilAvailable(timeout.toMillis(), TimeUnit.MILLISECONDS, status); } @@ -161,25 +171,36 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { } try { - process = new CommandLine(this.nodeJSExec.getCanonicalPath(), - nodeJSArgs.toArray(new String[]{})); + process = new CommandLine( + this.nodeJSExec.getCanonicalPath(), + nodeJSArgs.toArray(new String[]{}) + ); process.setEnvironmentVariables(nodeJSEnvironment); process.copyOutputTo(stream); process.executeAsync(); ping(startupTimeout); - } catch (Throwable e) { + } catch (Exception e) { + final Optional output = Optional.ofNullable(process) + .map(CommandLine::getStdOut) + .filter((o) -> !StringUtils.isBlank(o)); destroyProcess(); - String msgTxt = "The local appium server has not been started. " - + "The given Node.js executable: " + this.nodeJSExec.getAbsolutePath() - + " Arguments: " + nodeJSArgs.toString() + " " + "\n"; - if (process != null) { - String processStream = process.getStdOut(); - if (!StringUtils.isBlank(processStream)) { - msgTxt = msgTxt + "Process output: " + processStream + "\n"; - } + List errorLines = new ArrayList<>(); + errorLines.add("The local appium server has not been started"); + errorLines.add(String.format("Reason: %s", e.getMessage())); + if (e instanceof UrlChecker.TimeoutException) { + errorLines.add(String.format( + "Consider increasing the server startup timeout value (currently %sms)", + startupTimeout.toMillis() + )); } - - throw new AppiumServerHasNotBeenStartedLocallyException(msgTxt, e); + errorLines.add( + String.format("Node.js executable path: %s", nodeJSExec.getAbsolutePath()) + ); + errorLines.add(String.format("Arguments: %s", nodeJSArgs)); + output.ifPresent((o) -> errorLines.add(String.format("Output: %s", o))); + throw new AppiumServerHasNotBeenStartedLocallyException( + StringUtils.joinWith("\n", errorLines), e + ); } } finally { lock.unlock(); diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 9d3bce564..0e354d441 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -29,7 +29,6 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; -import org.apache.commons.validator.routines.InetAddressValidator; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.os.ExecutableFinder; @@ -72,13 +71,14 @@ public final class AppiumServiceBuilder */ private static final String NODE_PATH = "NODE_BINARY_PATH"; - public static final String BROADCAST_IP_ADDRESS = "0.0.0.0"; + public static final String BROADCAST_IP4_ADDRESS = "0.0.0.0"; + public static final String BROADCAST_IP6_ADDRESS = "::"; private static final Path APPIUM_PATH_SUFFIX = Paths.get("appium", "build", "lib", "main.js"); public static final int DEFAULT_APPIUM_PORT = 4723; private final Map serverArguments = new HashMap<>(); private File appiumJS; private File node; - private String ipAddress = BROADCAST_IP_ADDRESS; + private String ipAddress = BROADCAST_IP4_ADDRESS; private Capabilities capabilities; private boolean autoQuoteCapabilitiesOnWindows = false; private static final Function APPIUM_JS_NOT_EXIST_ERROR = (fullPath) -> String.format( @@ -363,14 +363,7 @@ protected ImmutableList createArgs() { argList.add(String.valueOf(getPort())); if (StringUtils.isBlank(ipAddress)) { - ipAddress = BROADCAST_IP_ADDRESS; - } else { - InetAddressValidator validator = InetAddressValidator.getInstance(); - if (!validator.isValid(ipAddress) && !validator.isValidInet4Address(ipAddress) - && !validator.isValidInet6Address(ipAddress)) { - throw new IllegalArgumentException( - "The invalid IP address " + ipAddress + " is defined"); - } + ipAddress = BROADCAST_IP4_ADDRESS; } argList.add("--address"); argList.add(ipAddress); diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index 5d4fd5715..c8d9dd0f9 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -19,7 +19,7 @@ import static io.appium.java_client.TestUtils.getLocalIp4Address; import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; import static io.appium.java_client.service.local.AppiumServiceBuilder.APPIUM_PATH; -import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP_ADDRESS; +import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; import static io.appium.java_client.service.local.flags.GeneralServerFlag.BASEPATH; import static io.appium.java_client.service.local.flags.GeneralServerFlag.CALLBACK_ADDRESS; @@ -323,7 +323,7 @@ void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() { service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); service.start(); assertTrue(service.isRunning()); - String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); + String baseUrl = String.format("http://%s:%d/", BROADCAST_IP4_ADDRESS, DEFAULT_APPIUM_PORT); assertEquals(baseUrl + basePath + "/", service.getUrl().toString()); } @@ -333,7 +333,7 @@ void checkAbilityToStartServiceUsingValidBasePathWithSinglePathParams() { service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); service.start(); assertTrue(service.isRunning()); - String baseUrl = String.format("http://%s:%d/", BROADCAST_IP_ADDRESS, DEFAULT_APPIUM_PORT); + String baseUrl = String.format("http://%s:%d/", BROADCAST_IP4_ADDRESS, DEFAULT_APPIUM_PORT); assertEquals(baseUrl + basePath.substring(1), service.getUrl().toString()); } From 8ebb5c320a1b98fbc14ac2f2c9cec1447db76c34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 21:42:48 +0300 Subject: [PATCH 222/501] build(deps): Bump org.projectlombok:lombok from 1.18.26 to 1.18.28 (#1929) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.26 to 1.18.28. - [Release notes](https://github.com/projectlombok/lombok/releases) - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.26...v1.18.28) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2c2371e99..7b5532915 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.26' - annotationProcessor 'org.projectlombok:lombok:1.18.26' + compileOnly 'org.projectlombok:lombok:1.18.28' + annotationProcessor 'org.projectlombok:lombok:1.18.28' api ('org.seleniumhq.selenium:selenium-api') { version { From 9176e8ead6ae19116713d8eb4fd15958bca4f4ca Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Fri, 2 Jun 2023 20:18:53 +0800 Subject: [PATCH 223/501] Release 8.5.1 and update release notes --- CHANGELOG.md | 15 +++++++++++++++ gradle.properties | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b8089b6c..cf1920ce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +*8.5.1* +- **[BUG FIX]** + - Use correct exception type for fallback at file/folder pulling. [#1912](https://github.com/appium/java-client/pull/1912) + - Update autoWebview capability name. [#1917](https://github.com/appium/java-client/pull/1917) +- **[REFACTOR]** + - Move execution of E2E tests to GitHub Actions. [#1913](https://github.com/appium/java-client/pull/1913) + - Replace cglib with bytebuddy. [#1923](https://github.com/appium/java-client/pull/1923) + - Improve the error message on service startup. [#1928](https://github.com/appium/java-client/pull/1928) +- **[DOCUMENTATION]** + - Initiate Selenium client compatibility matrix. [#1918](https://github.com/appium/java-client/pull/1918) +- **[DEPENDENCY UPDATES]** + - `io.github.bonigarcia:webdrivermanager` was updated to 5.3.3. + - `org.projectlombok:lombok` was updated to 1.18.28. + - `commons-io:commons-io` was updated to 2.12.0. + *8.5.0* - **[BUG FIX]** - Restore Jitpack builds. [#1911](https://github.com/appium/java-client/pull/1911) diff --git a/gradle.properties b/gradle.properties index fca46f2cd..e7f91060b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.9.1 # Please increment the value in a release -appiumClient.version=8.5.0 +appiumClient.version=8.5.1 From 28adafa4cc9e8ac570732cf7c095cf30a3bf4093 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 8 Jun 2023 11:37:28 +0300 Subject: [PATCH 224/501] docs: Add the latest versions of clients to the compatibility matrix (#1935) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 104c256e4..5a7c669a4 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ dependencies { ### Compatibility Matrix | Appium Java Client | Selenium client | |--------------------|---------------------------------------------| -| `8.5.0` | `4.9.1` | +| `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0` | | `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` | | `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` | | `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` | From 431edd3d89531414c0af7553a10fcf648e32a18a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 8 Jun 2023 13:10:50 +0000 Subject: [PATCH 225/501] fix: Exclude abstract methods from proxy matching (#1937) --- .../java_client/pagefactory/utils/ProxyFactory.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java index d0b8e4832..7cec1ad07 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java @@ -19,7 +19,6 @@ import io.appium.java_client.proxy.MethodCallListener; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; import java.util.Arrays; import java.util.Collections; @@ -28,7 +27,9 @@ import static io.appium.java_client.proxy.Helpers.OBJECT_METHOD_NAMES; import static io.appium.java_client.proxy.Helpers.createProxy; +import static net.bytebuddy.matcher.ElementMatchers.isAbstract; import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; +import static net.bytebuddy.matcher.ElementMatchers.not; /** * Original class is a super class of a @@ -77,9 +78,11 @@ public static T getEnhancedProxy(Class requiredClazz, MethodCallListener public static T getEnhancedProxy( Class cls, Class[] params, Object[] values, MethodCallListener listener ) { - ElementMatcher extraMatcher = ElementMatchers.not(namedOneOf( - NON_PROXYABLE_METHODS.toArray(new String[0]) - )); + ElementMatcher extraMatcher = not( + namedOneOf(NON_PROXYABLE_METHODS.toArray(new String[0])) + ).and( + not(isAbstract()) + ); return createProxy( cls, values, From 0c7086fd19b830ac6c7548842f185a4b969b3e64 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 8 Jun 2023 19:31:54 +0000 Subject: [PATCH 226/501] chore: Mark Windows page object annotations as deprecated (#1938) --- src/main/java/io/appium/java_client/pagefactory/WindowsBy.java | 2 ++ .../java/io/appium/java_client/pagefactory/WindowsFindAll.java | 2 ++ .../java/io/appium/java_client/pagefactory/WindowsFindBy.java | 2 ++ .../io/appium/java_client/pagefactory/WindowsFindByAllSet.java | 2 ++ .../appium/java_client/pagefactory/WindowsFindByChainSet.java | 2 ++ .../io/appium/java_client/pagefactory/WindowsFindBySet.java | 2 ++ .../java/io/appium/java_client/pagefactory/WindowsFindBys.java | 2 ++ 7 files changed, 14 insertions(+) diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java b/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java index e953db2fc..3c599c326 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java @@ -18,7 +18,9 @@ /** * Used to build a complex Windows automation locator. + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated public @interface WindowsBy { /** diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java index 206c1dd08..ac1d0d0a5 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java @@ -29,7 +29,9 @@ * of {@link WindowsBy} tags * It will then search for all elements that match any criteria. Note that elements * are not guaranteed to be in document order. + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated @Retention(RUNTIME) @Target({FIELD, TYPE}) @Repeatable(WindowsFindByAllSet.class) public @interface WindowsFindAll { diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java index 2222d0312..f1c67be98 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java @@ -30,7 +30,9 @@ * {@link org.openqa.selenium.support.PageFactory} * this allows users to quickly and easily create PageObjects. * using Windows automation selectors, accessibility, id, name, class name, tag and xpath + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated @Retention(RUNTIME) @Target({FIELD, TYPE}) @Repeatable(WindowsFindBySet.class) public @interface WindowsFindBy { diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java index 31caf953d..f93e00d92 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java @@ -10,7 +10,9 @@ /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link WindowsFindAll} + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated @Target(value = {TYPE, FIELD}) @Retention(value = RUNTIME) public @interface WindowsFindByAllSet { diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java index b6518ba6a..b8a3e9f23 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java @@ -10,7 +10,9 @@ /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link WindowsFindBys} + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated @Target(value = {TYPE, FIELD}) @Retention(value = RUNTIME) public @interface WindowsFindByChainSet { diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java index 2f7cda9f4..e953d63a1 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java @@ -26,7 +26,9 @@ /** * Defines set of chained/possible locators. Each one locator * should be defined with {@link WindowsFindBy} + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated @Target(value = {TYPE, FIELD}) @Retention(value = RUNTIME) public @interface WindowsFindBySet { diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java index 9120a41d6..358a77ae8 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java +++ b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java @@ -27,7 +27,9 @@ /** * Used to mark a field on a Page Object to indicate that lookup should use * a series of {@link WindowsBy} tags. + * @deprecated This annotation is deprecated and will be removed. */ +@Deprecated @Retention(RUNTIME) @Target({FIELD, TYPE}) @Repeatable(WindowsFindByChainSet.class) public @interface WindowsFindBys { From 22719abb8ab7fdd37d302d37f9673669d09e0d35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:03:56 +0300 Subject: [PATCH 227/501] build(deps): Bump commons-io:commons-io from 2.12.0 to 2.13.0 (#1942) Bumps commons-io:commons-io from 2.12.0 to 2.13.0. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7b5532915..f46ed8024 100644 --- a/build.gradle +++ b/build.gradle @@ -53,7 +53,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'commons-io:commons-io:2.12.0' + implementation 'commons-io:commons-io:2.13.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3' From 41177668fa16b67df94528350c007b160357ddb3 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 26 Jun 2023 17:20:21 +0300 Subject: [PATCH 228/501] test: Increase server start timeout for iOS tests (#1951) --- src/test/java/io/appium/java_client/ios/BaseIOSTest.java | 3 ++- .../java_client/service/local/StartingAppLocallyIosTest.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index 1661e19c9..2790465a6 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -34,6 +34,7 @@ public class BaseIOSTest { ? System.getenv("IOS_PLATFORM_VERSION") : "14.5"; public static final Duration WDA_LAUNCH_TIMEOUT = Duration.ofSeconds(240); + public static final Duration SERVER_START_TIMEOUT = Duration.ofSeconds(40); /** * Starts a local server. @@ -44,7 +45,7 @@ public static AppiumDriverLocalService startAppiumServer() { service = new AppiumServiceBuilder() .withIPAddress("127.0.0.1") .usingPort(PORT) - .withTimeout(Duration.ofSeconds(40)) + .withTimeout(SERVER_START_TIMEOUT) .build(); service.start(); return service; diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index 6baf77701..3ce6bd9af 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -66,7 +66,8 @@ void startingIOSAppWithCapabilitiesAndServiceTest() { AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) - .withArgument(GeneralServerFlag.STRICT_CAPS); + .withArgument(GeneralServerFlag.STRICT_CAPS) + .withTimeout(BaseIOSTest.SERVER_START_TIMEOUT); IOSDriver driver = new IOSDriver(builder, options); try { @@ -92,6 +93,7 @@ void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.STRICT_CAPS) + .withTimeout(BaseIOSTest.SERVER_START_TIMEOUT) .withCapabilities(serverOptions); IOSDriver driver = new IOSDriver(builder, clientOptions); From 305ce1a0c1eee4cca4897629df835cb964ec64b8 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 26 Jun 2023 18:41:40 +0300 Subject: [PATCH 229/501] build: Bump Checkstyle from `10.6.0` to `10.12.1` (#1948) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f46ed8024..3cf178884 100644 --- a/build.gradle +++ b/build.gradle @@ -99,7 +99,7 @@ if (JavaVersion.current().isJava11Compatible()) { apply plugin: 'checkstyle' checkstyle { - toolVersion = '10.6.0' + toolVersion = '10.12.1' configFile = configDirectory.file('appium-style.xml').get().getAsFile() showViolations = true ignoreFailures = false From a574d3f83fb22ae9fd92c86669275752c749a0e9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 26 Jun 2023 21:21:36 +0300 Subject: [PATCH 230/501] test: Fix Android test: `--base-path` arg must start with `/` (#1952) --- .../appium/java_client/service/local/ServerBuilderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index c8d9dd0f9..aae940553 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -319,11 +319,11 @@ void checkAbilityToStartServiceWithLogFileUsingShortFlag() { @Test void checkAbilityToStartServiceUsingValidBasePathWithMultiplePathParams() { - String basePath = "wd/hub"; + String basePath = "/wd/hub"; service = new AppiumServiceBuilder().withArgument(BASEPATH, basePath).build(); service.start(); assertTrue(service.isRunning()); - String baseUrl = String.format("http://%s:%d/", BROADCAST_IP4_ADDRESS, DEFAULT_APPIUM_PORT); + String baseUrl = String.format("http://%s:%d", BROADCAST_IP4_ADDRESS, DEFAULT_APPIUM_PORT); assertEquals(baseUrl + basePath + "/", service.getUrl().toString()); } From 3643b01358e053a93a4962cb7583c5e16557d277 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 10:25:39 +0300 Subject: [PATCH 231/501] build(deps): Bump org.owasp.dependencycheck from 8.2.1 to 8.3.1 (#1950) Bumps org.owasp.dependencycheck from 8.2.1 to 8.3.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3cf178884..8753cab22 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.2.1' + id 'org.owasp.dependencycheck' version '8.3.1' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 8177613ed3485bf30cd3600b587deacf79c7db83 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 11 Jul 2023 16:51:34 -0700 Subject: [PATCH 232/501] fix: AppiumClientConfig#readTimeout to call super.readTimeout (#1959) --- src/main/java/io/appium/java_client/AppiumClientConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java index 317d85314..b25a3032d 100644 --- a/src/main/java/io/appium/java_client/AppiumClientConfig.java +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -129,7 +129,7 @@ public AppiumClientConfig connectionTimeout(Duration timeout) { @Override public AppiumClientConfig readTimeout(Duration timeout) { - ClientConfig clientConfig = super.connectionTimeout(timeout); + ClientConfig clientConfig = super.readTimeout(timeout); return buildAppiumClientConfig(clientConfig, directConnect); } From 70da13c312ab128281dfce32f54193a292682521 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 12 Jul 2023 09:49:23 +0000 Subject: [PATCH 233/501] chore: Deprecate obsolete capabilities constants (#1961) --- .../appium/java_client/remote/AndroidMobileCapabilityType.java | 3 +++ .../io/appium/java_client/remote/IOSMobileCapabilityType.java | 3 +++ .../io/appium/java_client/remote/MobileCapabilityType.java | 3 +++ .../io/appium/java_client/remote/YouiEngineCapabilityType.java | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java index 9ec293fa5..6b698d004 100644 --- a/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java @@ -23,7 +23,10 @@ * Read:
* * https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md#android-only + * + * @deprecated This interface will be removed. Use Options instead. */ +@Deprecated public interface AndroidMobileCapabilityType extends CapabilityType { /** diff --git a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java index 046dd4952..162353dc1 100644 --- a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java @@ -27,7 +27,10 @@ * and
* * https://github.com/appium/appium-xcuitest-driver#desired-capabilities + * + * @deprecated This interface will be removed. Use Options instead. */ +@Deprecated public interface IOSMobileCapabilityType extends CapabilityType { /** diff --git a/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java index f1aba4b9c..eeaa44405 100644 --- a/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java @@ -23,7 +23,10 @@ * Read:
* * https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md#general-capabilities + * + * @deprecated This interface will be removed. Use Options instead. */ +@Deprecated public interface MobileCapabilityType extends CapabilityType { /** diff --git a/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java b/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java index 80301762d..1657103a6 100644 --- a/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java @@ -4,7 +4,10 @@ /** * The list of youiengine-specific capabilities. + * + * @deprecated This interface will be removed. Use Options instead. */ +@Deprecated public interface YouiEngineCapabilityType extends CapabilityType { /** * IP address of the app to execute commands against. From e337d12f426ec5955af1fef54b92fcef0ac8bb08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 15:22:14 +0300 Subject: [PATCH 234/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.9.3 to 5.10.0 (#1965) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.9.3 to 5.10.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.10.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8753cab22..819154260 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'commons-io:commons-io:2.13.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.3') { exclude group: 'org.seleniumhq.selenium' From 8bf7d8f70dda1cf70b5ab759001b0511568c9839 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:56:21 +0300 Subject: [PATCH 235/501] build(deps): Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.13.0 (#1973) Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.13.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 819154260..7a8607c08 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ dependencies { } implementation 'com.google.code.gson:gson:2.10.1' implementation 'commons-validator:commons-validator:1.7' - implementation 'org.apache.commons:commons-lang3:3.12.0' + implementation 'org.apache.commons:commons-lang3:3.13.0' implementation 'commons-io:commons-io:2.13.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" From 1f8d893856265b71859ae91496ffe56af6fe0c52 Mon Sep 17 00:00:00 2001 From: Brett Fisher <32568586+fishey2@users.noreply.github.com> Date: Tue, 1 Aug 2023 07:11:15 +0100 Subject: [PATCH 236/501] fix: Correct spelling and semantic mistakes in method naming (#1967) (#1970) --- .../SupportsShowChromedriverLogOption.java | 25 +++++++++++++++++-- .../SupportsCustomSslCertOption.java | 12 ++++++++- .../SupportsSimulatorTracePointerOption.java | 12 ++++++++- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java index d201069e5..bd86a041e 100644 --- a/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java @@ -45,18 +45,39 @@ default T showChromedriverLog() { * @param value Whether to forward chromedriver output to the Appium server log. * @return self instance for chaining. */ - default T setDhowChromedriverLog(boolean value) { + default T setShowChromedriverLog(boolean value) { return amend(SHOW_CHROMEDRIVER_LOG_OPTION, value); } + /** + * If set to true then all the output from chromedriver binary will be + * forwarded to the Appium server log. false by default. + * + * @deprecated Use {@link SupportsShowChromedriverLogOption#setShowChromedriverLog(boolean)} instead. + */ + @Deprecated + default T setDhowChromedriverLog(boolean value) { + return setShowChromedriverLog(value); + } + /** * Get whether to forward chromedriver output to the Appium server log. * * @return True or false. */ - default Optional doesDhowChromedriverLog() { + default Optional doesShowChromedriverLog() { return Optional.ofNullable( toSafeBoolean(getCapability(SHOW_CHROMEDRIVER_LOG_OPTION)) ); } + + /** + * Get whether to forward chromedriver output to the Appium server log. + * + * @deprecated Use {@link SupportsShowChromedriverLogOption#doesShowChromedriverLog()} (boolean)} instead. + */ + @Deprecated + default Optional doesDhowChromedriverLog() { + return doesShowChromedriverLog(); + } } diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java index 93611eec1..e5ceefef2 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java @@ -40,9 +40,19 @@ default T setCustomSSLCert(String cert) { /** * Get the SSL certificate content. * - * @return Certificate content. + * @deprecated use {@link SupportsCustomSslCertOption#getCustomSSLCert()} instead */ + @Deprecated default Optional setCustomSSLCert() { + return getCustomSSLCert(); + } + + /** + * Get the SSL certificate content. + * + * @return Certificate content. + */ + default Optional getCustomSSLCert() { return Optional.ofNullable((String) getCapability(CUSTOM_SSLCERT_OPTION)); } } diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java index a0341725a..3958de502 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java @@ -55,7 +55,17 @@ default T setSimulatorTracePointer(boolean value) { * * @return True or false. */ - default Optional doesSimulatorTracePointerd() { + default Optional doesSimulatorTracePointer() { return Optional.ofNullable(toSafeBoolean(getCapability(SIMULATOR_TRACE_POINTER_OPTION))); } + + /** + * Get whether to highlight pointer moves in the Simulator window. + * + * @deprecated use {@link SupportsSimulatorTracePointerOption#doesSimulatorTracePointer()} instead + */ + @Deprecated + default Optional doesSimulatorTracePointerd() { + return doesSimulatorTracePointer(); + } } From 8636dac0e850f1597c1b56246795958d12d19d23 Mon Sep 17 00:00:00 2001 From: Bipin Kumar Chaurasia Date: Wed, 2 Aug 2023 00:07:52 +0530 Subject: [PATCH 237/501] docs(java-client): Added correct url path for the latest appium documentation (#1974) --- src/main/java/io/appium/java_client/AppiumBy.java | 2 +- .../java_client/remote/IOSMobileCapabilityType.java | 4 ++-- .../appium/java_client/remote/MobileCapabilityType.java | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 10a8c5b76..297e9a9b3 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -147,7 +147,7 @@ public static By custom(final String selector) { /** * This locator strategy is available only if OpenCV libraries and - * NodeJS bindings are installed on the server machine. + * Node.js bindings are installed on the server machine. * * @see * The documentation on Image Comparison Features diff --git a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java index 162353dc1..b8b517132 100644 --- a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java @@ -25,8 +25,8 @@ * https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md#ios-only *
* and
- * - * https://github.com/appium/appium-xcuitest-driver#desired-capabilities + * + * https://appium.github.io/appium-xcuitest-driver/latest/capabilities/ * * @deprecated This interface will be removed. Use Options instead. */ diff --git a/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java index eeaa44405..44cc27214 100644 --- a/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java +++ b/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java @@ -21,8 +21,8 @@ /** * The list of common capabilities.
* Read:
- * - * https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md#general-capabilities + * + * https://appium.io/docs/en/latest/guides/caps/#appium-capabilities * * @deprecated This interface will be removed. Use Options instead. */ @@ -117,8 +117,8 @@ public interface MobileCapabilityType extends CapabilityType { * (e.g., the start and end of each command, etc.). Defaults to {@code false}. * To enable, use {@code true}. The timings are then reported as {@code events} property on response * to querying the current session. See the - * - * event timing docs for the the structure of this response. + * + * event timing docs for the structure of this response. */ String EVENT_TIMINGS = "eventTimings"; From aa103a161b0a875f630f32adeb435b485ad67f59 Mon Sep 17 00:00:00 2001 From: Bipin Kumar Chaurasia Date: Wed, 2 Aug 2023 17:19:16 +0530 Subject: [PATCH 238/501] fix: Added fixes for No service provider found for `io.appium.java_client.events.api.Listener` (#1975) --- .../services/io.appium.java_client.events.api.Listener | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/test/resources/META-INF/services/io.appium.java_client.events.api.Listener diff --git a/src/test/resources/META-INF/services/io.appium.java_client.events.api.Listener b/src/test/resources/META-INF/services/io.appium.java_client.events.api.Listener deleted file mode 100644 index 6faceb0d0..000000000 --- a/src/test/resources/META-INF/services/io.appium.java_client.events.api.Listener +++ /dev/null @@ -1,10 +0,0 @@ -io.appium.java_client.events.listeners.AlertListener -io.appium.java_client.events.listeners.RotationListener -io.appium.java_client.events.listeners.WindowListener -io.appium.java_client.events.listeners.ContextListener -io.appium.java_client.events.listeners.ElementListener -io.appium.java_client.events.listeners.ExceptionListener -io.appium.java_client.events.listeners.JavaScriptListener -io.appium.java_client.events.listeners.NavigationListener -io.appium.java_client.events.listeners.SearchingListener -io.appium.java_client.events.listeners.AppiumListener From d415493b17894c6b11eb8420120c851395f349c8 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 18 Aug 2023 14:49:54 +0300 Subject: [PATCH 239/501] chore: Bump Gradle from `8.1` to `8.3` (#1982) --- build.gradle | 3 ++- gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 8 ++++++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 7a8607c08..f98fe8319 100644 --- a/build.gradle +++ b/build.gradle @@ -57,6 +57,7 @@ dependencies { implementation "org.slf4j:slf4j-api:${slf4jVersion}" testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.3') { exclude group: 'org.seleniumhq.selenium' @@ -189,7 +190,7 @@ signing { } wrapper { - gradleVersion = '8.1' + gradleVersion = '8.3' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 37652 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 delta 36122 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 Ac-xW1# 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 Q>rd#Eb%7 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a21c6ebe2..d11cdd907 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb4..0adc8e1a5 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. From 547e0630f184300bd5d39f28c4bb0fd5309d95f9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 18 Aug 2023 15:19:58 +0300 Subject: [PATCH 240/501] test: Run tests against latest Selenium release (#1978) --- build.gradle | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index f98fe8319..4c2e414b7 100644 --- a/build.gradle +++ b/build.gradle @@ -62,12 +62,11 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.3') { exclude group: 'org.seleniumhq.selenium' } - testImplementation ('org.seleniumhq.selenium:selenium-chrome-driver') { - version { - strictly "[${seleniumVersion}, 5.0)" - prefer "${seleniumVersion}" - } - } + testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.11.0') + testImplementation 'org.seleniumhq.selenium:selenium-api' + testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' + testImplementation 'org.seleniumhq.selenium:selenium-support' + testImplementation 'org.seleniumhq.selenium:selenium-chrome-driver' testRuntimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" } From 263fb8cba7bc4645a34fa7e50f6200d827170c5b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 18 Aug 2023 15:03:42 +0200 Subject: [PATCH 241/501] fix: Use weak references to elements inside of interceptor objects (#1981) --- .../pagefactory/AppiumElementLocator.java | 92 +++++++++++++------ .../AppiumElementLocatorFactory.java | 47 +++++++--- .../pagefactory/AppiumFieldDecorator.java | 83 ++++++++++++----- .../pagefactory/ElementInterceptor.java | 3 +- .../pagefactory/WidgetInterceptor.java | 30 +++--- .../pagefactory/WidgetListInterceptor.java | 34 +++++-- .../InterceptorOfAListOfElements.java | 5 +- .../InterceptorOfASingleElement.java | 18 +++- 8 files changed, 223 insertions(+), 89 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java index 5208add47..3aba5bcdc 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java @@ -27,9 +27,11 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.FluentWait; +import java.lang.ref.WeakReference; import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; @@ -46,10 +48,36 @@ class AppiumElementLocator implements CacheableLocator { private final boolean shouldCache; private final By by; private final Duration duration; + private final WeakReference searchContextReference; private final SearchContext searchContext; + private WebElement cachedElement; private List cachedElementList; + /** + * Creates a new mobile element locator. It instantiates {@link WebElement} + * using @AndroidFindBy (-s), @iOSFindBy (-s) and @FindBy (-s) annotation + * sets + * + * @param searchContextReference The context reference to use when finding the element + * @param by a By locator strategy + * @param shouldCache is the flag that signalizes that elements which + * are found once should be cached + * @param duration timeout parameter for the element to be found + */ + AppiumElementLocator( + WeakReference searchContextReference, + By by, + boolean shouldCache, + Duration duration + ) { + this.searchContextReference = searchContextReference; + this.searchContext = null; + this.shouldCache = shouldCache; + this.duration = duration; + this.by = by; + } + /** * Creates a new mobile element locator. It instantiates {@link WebElement} * using @AndroidFindBy (-s), @iOSFindBy (-s) and @FindBy (-s) annotation @@ -61,15 +89,25 @@ class AppiumElementLocator implements CacheableLocator { * are found once should be cached * @param duration timeout parameter for the element to be found */ - - public AppiumElementLocator(SearchContext searchContext, By by, boolean shouldCache, - Duration duration) { + public AppiumElementLocator( + SearchContext searchContext, + By by, + boolean shouldCache, + Duration duration + ) { + this.searchContextReference = null; this.searchContext = searchContext; this.shouldCache = shouldCache; this.duration = duration; this.by = by; } + private Optional getSearchContext() { + return searchContext == null + ? Optional.ofNullable(searchContextReference).map(WeakReference::get) + : Optional.of(searchContext); + } + /** * This methods makes sets some settings of the {@link By} according to * the given instance of {@link SearchContext}. If there is some {@link ContentMappedBy} @@ -85,8 +123,7 @@ private static By getBy(By currentBy, SearchContext currentContent) { return currentBy; } - return ContentMappedBy.class.cast(currentBy) - .useContent(getCurrentContentType(currentContent)); + return ((ContentMappedBy) currentBy).useContent(getCurrentContentType(currentContent)); } private T waitFor(Supplier supplier) { @@ -98,8 +135,7 @@ private T waitFor(Supplier supplier) { return wait.until(function); } catch (TimeoutException e) { if (function.foundStaleElementReferenceException != null) { - throw StaleElementReferenceException - .class.cast(function.foundStaleElementReferenceException); + throw (StaleElementReferenceException) function.foundStaleElementReferenceException; } throw e; } @@ -113,10 +149,15 @@ public WebElement findElement() { return cachedElement; } + SearchContext searchContext = getSearchContext() + .orElseThrow(() -> new IllegalStateException( + String.format("The element %s is not locatable anymore " + + "because its context has been garbage collected", by) + )); + By bySearching = getBy(this.by, searchContext); try { - WebElement result = waitFor(() -> - searchContext.findElement(bySearching)); + WebElement result = waitFor(() -> searchContext.findElement(bySearching)); if (shouldCache) { cachedElement = result; } @@ -134,12 +175,17 @@ public List findElements() { return cachedElementList; } + SearchContext searchContext = getSearchContext() + .orElseThrow(() -> new IllegalStateException( + String.format("Elements %s are not locatable anymore " + + "because their context has been garbage collected", by) + )); + List result; try { result = waitFor(() -> { - List list = searchContext - .findElements(getBy(by, searchContext)); - return list.size() > 0 ? list : null; + List list = searchContext.findElements(getBy(by, searchContext)); + return list.isEmpty() ? null : list; }); } catch (TimeoutException | StaleElementReferenceException e) { result = new ArrayList<>(); @@ -171,30 +217,22 @@ public T apply(Supplier supplier) { return supplier.get(); } catch (Throwable e) { boolean isRootCauseStaleElementReferenceException = false; - Throwable shouldBeThrown; boolean isRootCauseInvalidSelector = isInvalidSelectorRootCause(e); - if (!isRootCauseInvalidSelector) { isRootCauseStaleElementReferenceException = isStaleElementReferenceException(e); } - if (isRootCauseStaleElementReferenceException) { foundStaleElementReferenceException = extractReadableException(e); } + if (isRootCauseInvalidSelector || isRootCauseStaleElementReferenceException) { + return null; + } - if (!isRootCauseInvalidSelector & !isRootCauseStaleElementReferenceException) { - shouldBeThrown = extractReadableException(e); - if (shouldBeThrown != null) { - if (NoSuchElementException.class.equals(shouldBeThrown.getClass())) { - throw NoSuchElementException.class.cast(shouldBeThrown); - } else { - throw new WebDriverException(shouldBeThrown); - } - } else { - throw new WebDriverException(e); - } + Throwable excToThrow = extractReadableException(e); + if (excToThrow instanceof WebDriverException) { + throw (WebDriverException) excToThrow; } else { - return null; + throw new WebDriverException(excToThrow); } } } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java index 0fc8e3d38..787e34e9e 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -23,6 +23,7 @@ import org.openqa.selenium.SearchContext; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.time.Duration; @@ -32,6 +33,7 @@ public class AppiumElementLocatorFactory implements CacheableElementLocatorFactory { private final SearchContext searchContext; + private final WeakReference searchContextReference; private final Duration duration; private final AppiumByBuilder builder; @@ -39,22 +41,46 @@ public class AppiumElementLocatorFactory implements CacheableElementLocatorFacto * Creates a new mobile element locator factory. * * @param searchContext The context to use when finding the element - * @param duration timeout parameters for the elements to be found - * @param builder is handler of Appium-specific page object annotations + * @param duration timeout parameters for the elements to be found + * @param builder is handler of Appium-specific page object annotations */ - public AppiumElementLocatorFactory(SearchContext searchContext, Duration duration, - AppiumByBuilder builder) { + public AppiumElementLocatorFactory( + SearchContext searchContext, + Duration duration, + AppiumByBuilder builder + ) { this.searchContext = searchContext; + this.searchContextReference = null; this.duration = duration; this.builder = builder; } - public @Nullable CacheableLocator createLocator(Field field) { - return this.createLocator((AnnotatedElement) field); + /** + * Creates a new mobile element locator factory. + * + * @param searchContextReference The context reference to use when finding the element + * @param duration timeout parameters for the elements to be found + * @param builder is handler of Appium-specific page object annotations + */ + AppiumElementLocatorFactory( + WeakReference searchContextReference, + Duration duration, + AppiumByBuilder builder + ) { + this.searchContextReference = searchContextReference; + this.searchContext = null; + this.duration = duration; + this.builder = builder; } + @Nullable @Override + public CacheableLocator createLocator(Field field) { + return this.createLocator((AnnotatedElement) field); + } + @Nullable + @Override public CacheableLocator createLocator(AnnotatedElement annotatedElement) { Duration customDuration; if (annotatedElement.isAnnotationPresent(WithTimeout.class)) { @@ -63,14 +89,13 @@ public CacheableLocator createLocator(AnnotatedElement annotatedElement) { } else { customDuration = duration; } - builder.setAnnotated(annotatedElement); By byResult = builder.buildBy(); - return ofNullable(byResult) - .map(by -> new AppiumElementLocator(searchContext, by, builder.isLookupCached(), customDuration)) + .map(by -> searchContextReference != null + ? new AppiumElementLocator(searchContextReference, by, builder.isLookupCached(), customDuration) + : new AppiumElementLocator(searchContext, by, builder.isLookupCached(), customDuration) + ) .orElse(null); } - - } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index b1119f34e..c2f11f473 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -30,9 +30,11 @@ import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.pagefactory.DefaultFieldDecorator; import org.openqa.selenium.support.pagefactory.ElementLocator; +import org.openqa.selenium.support.pagefactory.ElementLocatorFactory; import org.openqa.selenium.support.pagefactory.FieldDecorator; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; @@ -60,11 +62,13 @@ */ public class AppiumFieldDecorator implements FieldDecorator { - private static final List> availableElementClasses = ImmutableList.of(WebElement.class, - RemoteWebElement.class); + private static final List> availableElementClasses = ImmutableList.of( + WebElement.class, + RemoteWebElement.class + ); public static final Duration DEFAULT_WAITING_TIMEOUT = ofSeconds(1); - private final WebDriver webDriver; - private final DefaultFieldDecorator defaultElementFieldDecoracor; + private final WeakReference webDriverReference; + private final DefaultFieldDecorator defaultElementFieldDecorator; private final AppiumElementLocatorFactory widgetLocatorFactory; private final String platform; private final String automation; @@ -79,10 +83,45 @@ public class AppiumFieldDecorator implements FieldDecorator { * @param duration is a desired duration of the waiting for an element presence. */ public AppiumFieldDecorator(SearchContext context, Duration duration) { - this.webDriver = unpackWebDriverFromSearchContext(context); + WebDriver wd = unpackWebDriverFromSearchContext(context); + this.webDriverReference = wd == null ? null : new WeakReference<>(wd); + if (wd instanceof HasCapabilities) { + Capabilities caps = ((HasCapabilities) wd).getCapabilities(); + this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); + this.automation = CapabilityHelpers.getCapability(caps, MobileCapabilityType.AUTOMATION_NAME, String.class); + } else { + this.platform = null; + this.automation = null; + } + + this.duration = duration; + + defaultElementFieldDecorator = createFieldDecorator(new AppiumElementLocatorFactory( + context, duration, new DefaultElementByBuilder(platform, automation) + )); + + widgetLocatorFactory = new AppiumElementLocatorFactory( + context, duration, new WidgetByBuilder(platform, automation) + ); + } + + public AppiumFieldDecorator(SearchContext context) { + this(context, DEFAULT_WAITING_TIMEOUT); + } - if (this.webDriver instanceof HasCapabilities) { - Capabilities caps = ((HasCapabilities) this.webDriver).getCapabilities(); + /** + * Creates field decorator based on {@link SearchContext} and timeout {@code duration}. + * + * @param contextReference reference to {@link SearchContext} + * It may be the instance of {@link WebDriver} or {@link WebElement} or + * {@link Widget} or some other user's extension/implementation. + * @param duration is a desired duration of the waiting for an element presence. + */ + AppiumFieldDecorator(WeakReference contextReference, Duration duration) { + WebDriver wd = unpackWebDriverFromSearchContext(contextReference.get()); + this.webDriverReference = wd == null ? null : new WeakReference<>(wd); + if (wd instanceof HasCapabilities) { + Capabilities caps = ((HasCapabilities) wd).getCapabilities(); this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); this.automation = CapabilityHelpers.getCapability(caps, MobileCapabilityType.AUTOMATION_NAME, String.class); } else { @@ -92,9 +131,17 @@ public AppiumFieldDecorator(SearchContext context, Duration duration) { this.duration = duration; - defaultElementFieldDecoracor = new DefaultFieldDecorator( - new AppiumElementLocatorFactory(context, duration, new DefaultElementByBuilder(platform, automation)) - ) { + defaultElementFieldDecorator = createFieldDecorator(new AppiumElementLocatorFactory( + contextReference, duration, new DefaultElementByBuilder(platform, automation) + )); + + widgetLocatorFactory = new AppiumElementLocatorFactory( + contextReference, duration, new WidgetByBuilder(platform, automation) + ); + } + + private DefaultFieldDecorator createFieldDecorator(ElementLocatorFactory factory) { + return new DefaultFieldDecorator(factory) { @Override protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator) { return proxyForAnElement(locator); @@ -126,14 +173,6 @@ protected boolean isDecoratableList(Field field) { .anyMatch((webElClass) -> webElClass.equals(listType) || bounds.contains(webElClass)); } }; - - widgetLocatorFactory = new AppiumElementLocatorFactory( - context, duration, new WidgetByBuilder(platform, automation) - ); - } - - public AppiumFieldDecorator(SearchContext context) { - this(context, DEFAULT_WAITING_TIMEOUT); } /** @@ -144,7 +183,7 @@ public AppiumFieldDecorator(SearchContext context) { * @return a field value or null. */ public Object decorate(ClassLoader ignored, Field field) { - Object result = defaultElementFieldDecoracor.decorate(ignored, field); + Object result = defaultElementFieldDecorator.decorate(ignored, field); return result == null ? decorateWidget(field) : result; } @@ -191,7 +230,7 @@ private Object decorateWidget(Field field) { if (isAlist) { return getEnhancedProxy( ArrayList.class, - new WidgetListInterceptor(locator, webDriver, map, widgetType, duration) + new WidgetListInterceptor(locator, webDriverReference, map, widgetType, duration) ); } @@ -200,12 +239,12 @@ private Object decorateWidget(Field field) { widgetType, new Class[]{constructor.getParameterTypes()[0]}, new Object[]{proxyForAnElement(locator)}, - new WidgetInterceptor(locator, webDriver, null, map, duration) + new WidgetInterceptor(locator, webDriverReference, null, map, duration) ); } private WebElement proxyForAnElement(ElementLocator locator) { - ElementInterceptor elementInterceptor = new ElementInterceptor(locator, webDriver); + ElementInterceptor elementInterceptor = new ElementInterceptor(locator, webDriverReference); return getEnhancedProxy(RemoteWebElement.class, elementInterceptor); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java index 5047fcc11..82b61990b 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java @@ -21,6 +21,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; +import java.lang.ref.WeakReference; import java.lang.reflect.Method; import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; @@ -30,7 +31,7 @@ */ public class ElementInterceptor extends InterceptorOfASingleElement { - public ElementInterceptor(ElementLocator locator, WebDriver driver) { + public ElementInterceptor(ElementLocator locator, WeakReference driver) { super(locator, driver); } diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java index 9a9d1133d..d00c6e3c9 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java @@ -24,6 +24,7 @@ import org.openqa.selenium.support.PageFactory; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -34,27 +35,29 @@ import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; +import static java.util.Optional.ofNullable; public class WidgetInterceptor extends InterceptorOfASingleElement { private final Map> instantiationMap; private final Map cachedInstances = new HashMap<>(); private final Duration duration; - private WebElement cachedElement; + private WeakReference cachedElementReference; /** * Proxy interceptor class for widgets. */ public WidgetInterceptor( + @Nullable CacheableLocator locator, - WebDriver driver, + WeakReference driverReference, @Nullable - WebElement cachedElement, + WeakReference cachedElementReference, Map> instantiationMap, Duration duration ) { - super(locator, driver); - this.cachedElement = cachedElement; + super(locator, driverReference); + this.cachedElementReference = cachedElementReference; this.instantiationMap = instantiationMap; this.duration = duration; } @@ -62,24 +65,24 @@ public WidgetInterceptor( @Override protected Object getObject(WebElement element, Method method, Object[] args) throws Throwable { ContentType type = getCurrentContentType(element); - if (cachedElement == null + WebElement cachedElement = cachedElementReference == null ? null : cachedElementReference.get(); + if (cachedElement == null || !cachedInstances.containsKey(type) || (locator != null && !((CacheableLocator) locator).isLookUpCached()) - || cachedInstances.isEmpty() ) { - cachedElement = element; + cachedElementReference = new WeakReference<>(element); Constructor constructor = instantiationMap.get(type); Class clazz = constructor.getDeclaringClass(); if (Modifier.isAbstract(clazz.getModifiers())) { throw new InstantiationException( - String.format("%s is abstract so it cannot be instantiated", clazz.getName()) + String.format("%s is abstract so it cannot be instantiated", clazz.getName()) ); } - Widget widget = constructor.newInstance(cachedElement); + Widget widget = constructor.newInstance(element); cachedInstances.put(type, widget); - PageFactory.initElements(new AppiumFieldDecorator(widget, duration), widget); + PageFactory.initElements(new AppiumFieldDecorator(new WeakReference<>(widget), duration), widget); } try { method.setAccessible(true); @@ -91,8 +94,9 @@ protected Object getObject(WebElement element, Method method, Object[] args) thr @Override public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { - return locator == null - ? getObject(cachedElement, method, args) + WebElement element = ofNullable(cachedElementReference).map(WeakReference::get).orElse(null); + return locator == null && element != null + ? getObject(element, method, args) : super.call(obj, method, args, original); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java index 136ce8e4d..031a0e624 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java @@ -22,12 +22,16 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import static io.appium.java_client.pagefactory.ThrowableUtil.extractReadableException; import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; @@ -39,15 +43,20 @@ public class WidgetListInterceptor extends InterceptorOfAListOfElements { private final List cachedWidgets = new ArrayList<>(); private final Class declaredType; private final Duration duration; - private final WebDriver driver; - private List cachedElements; + private final WeakReference driver; + private final List> cachedElementReferences = new ArrayList<>(); /** * Proxy interceptor class for lists of widgets. */ - public WidgetListInterceptor(CacheableLocator locator, WebDriver driver, - Map> instantiationMap, - Class declaredType, Duration duration) { + public WidgetListInterceptor( + @Nullable + CacheableLocator locator, + WeakReference driver, + Map> instantiationMap, + Class declaredType, + Duration duration + ) { super(locator); this.instantiationMap = instantiationMap; this.declaredType = declaredType; @@ -57,20 +66,27 @@ public WidgetListInterceptor(CacheableLocator locator, WebDriver driver, @Override protected Object getObject(List elements, Method method, Object[] args) throws Throwable { - if (cachedElements == null || (locator != null && !((CacheableLocator) locator).isLookUpCached())) { - cachedElements = elements; + List cachedElements = cachedElementReferences.stream() + .map(WeakReference::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (cachedElements.size() != cachedWidgets.size() + || (locator != null && !((CacheableLocator) locator).isLookUpCached())) { cachedWidgets.clear(); + cachedElementReferences.clear(); ContentType type = null; - for (WebElement element : cachedElements) { + for (WebElement element : elements) { type = ofNullable(type).orElseGet(() -> getCurrentContentType(element)); Class[] params = new Class[] {instantiationMap.get(type).getParameterTypes()[0]}; + WeakReference elementReference = new WeakReference<>(element); cachedWidgets.add( getEnhancedProxy( declaredType, params, new Object[] {element}, - new WidgetInterceptor(null, driver, element, instantiationMap, duration) + new WidgetInterceptor(null, driver, elementReference, instantiationMap, duration) ) ); + cachedElementReferences.add(elementReference); } } try { diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java index d276ce616..62e1442aa 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java @@ -20,6 +20,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; +import javax.annotation.Nullable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @@ -28,7 +29,7 @@ public abstract class InterceptorOfAListOfElements implements MethodCallListener { protected final ElementLocator locator; - public InterceptorOfAListOfElements(ElementLocator locator) { + public InterceptorOfAListOfElements(@Nullable ElementLocator locator) { this.locator = locator; } @@ -38,7 +39,7 @@ protected abstract Object getObject( @Override public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { - if (Object.class.equals(method.getDeclaringClass())) { + if (locator == null || Object.class.equals(method.getDeclaringClass())) { return original.call(); } diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java index 7ac12b3d6..7eea82233 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java @@ -22,22 +22,32 @@ import org.openqa.selenium.WrapsDriver; import org.openqa.selenium.support.pagefactory.ElementLocator; +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.concurrent.Callable; public abstract class InterceptorOfASingleElement implements MethodCallListener { protected final ElementLocator locator; - protected final WebDriver driver; + private final WeakReference driverReference; - public InterceptorOfASingleElement(ElementLocator locator, WebDriver driver) { + public InterceptorOfASingleElement( + @Nullable + ElementLocator locator, + WeakReference driverReference + ) { this.locator = locator; - this.driver = driver; + this.driverReference = driverReference; } protected abstract Object getObject(WebElement element, Method method, Object[] args) throws Throwable; @Override public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { + if (locator == null) { + return original.call(); + } + if (method.getName().equals("toString") && args.length == 0) { return locator.toString(); } @@ -48,7 +58,7 @@ public Object call(Object obj, Method method, Object[] args, Callable origina if (WrapsDriver.class.isAssignableFrom(method.getDeclaringClass()) && method.getName().equals("getWrappedDriver")) { - return driver; + return driverReference.get(); } WebElement realElement = locator.findElement(); From 16763424b5f8f729739ce8a2bf8c8eed9c6177d6 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 18 Aug 2023 17:17:51 +0200 Subject: [PATCH 242/501] ci: Increase the server startup timeout (#1983) --- src/test/java/io/appium/java_client/ios/BaseIOSTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index 2790465a6..fe5764e7b 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -33,8 +33,8 @@ public class BaseIOSTest { public static final String PLATFORM_VERSION = System.getenv("IOS_PLATFORM_VERSION") != null ? System.getenv("IOS_PLATFORM_VERSION") : "14.5"; - public static final Duration WDA_LAUNCH_TIMEOUT = Duration.ofSeconds(240); - public static final Duration SERVER_START_TIMEOUT = Duration.ofSeconds(40); + public static final Duration WDA_LAUNCH_TIMEOUT = Duration.ofMinutes(4); + public static final Duration SERVER_START_TIMEOUT = Duration.ofMinutes(3); /** * Starts a local server. From 09d3ac0f8cff055eccf35b65fd1c5b45e1a66996 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:14:48 +0300 Subject: [PATCH 243/501] build(deps): Bump org.owasp.dependencycheck from 8.3.1 to 8.4.0 (#1984) Bumps org.owasp.dependencycheck from 8.3.1 to 8.4.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4c2e414b7..674612f83 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.3.1' + id 'org.owasp.dependencycheck' version '8.4.0' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 2217c705a01ff9729f6305caddb2187f18d681c9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 22 Aug 2023 11:53:05 +0300 Subject: [PATCH 244/501] docs: Add Selenium `4.11.0` to compatibility matrix (#1986) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a7c669a4..560610b0d 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ dependencies { ### Compatibility Matrix | Appium Java Client | Selenium client | |--------------------|---------------------------------------------| -| `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0` | +| `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0` | | `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` | | `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` | | `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` | From d3b304660983ff27ad469f3d3e3c926e33d26c96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:55:24 +0300 Subject: [PATCH 245/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#1987) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.3.3 to 5.5.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.3.3...webdrivermanager-5.5.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 674612f83..7ff7df443 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.3.3') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.0') { exclude group: 'org.seleniumhq.selenium' } testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.11.0') From 149fd0ce75fe7ae5b8a052970109a3f3d4e81dd1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:41:13 +0300 Subject: [PATCH 246/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#1988) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.5.0 to 5.5.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.5.0...webdrivermanager-5.5.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7ff7df443..17880238c 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.0') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.2') { exclude group: 'org.seleniumhq.selenium' } testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.11.0') From 8af67b4373be70f50bedaddcf525f4f73e29e2da Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 31 Aug 2023 19:43:48 +0200 Subject: [PATCH 247/501] tests: Use server releases from the main branch for testing (#1994) --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 872468fad..a76a31d52 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -63,7 +63,7 @@ jobs: - name: Install Appium if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' - run: npm install -g appium@next + run: npm install --location=global appium - name: Install UIA2 driver if: matrix.e2e-tests == 'android' From 85e60962ff37c2d290e1cd4f3aa7df0a0d5176a9 Mon Sep 17 00:00:00 2001 From: AlessandroMiccoli <57630383+AlessandroMiccoli@users.noreply.github.com> Date: Fri, 1 Sep 2023 06:23:46 +0100 Subject: [PATCH 248/501] chore: patch AutomationName with Chromium (#1993) --- src/main/java/io/appium/java_client/remote/AutomationName.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/io/appium/java_client/remote/AutomationName.java b/src/main/java/io/appium/java_client/remote/AutomationName.java index e38474dbc..4ee53ea1a 100644 --- a/src/main/java/io/appium/java_client/remote/AutomationName.java +++ b/src/main/java/io/appium/java_client/remote/AutomationName.java @@ -34,6 +34,8 @@ public interface AutomationName { String SAFARI = "Safari"; // https://github.com/appium/appium-geckodriver String GECKO = "Gecko"; + // https://github.com/appium/appium-chromium-driver + String CHROMIUM = "Chromium"; // Third-party drivers // https://github.com/YOU-i-Labs/appium-youiengine-driver From 0e3238188dd6f9e0d6ffa057a9288705f1229e5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 17:38:47 +0300 Subject: [PATCH 249/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#1996) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.5.2 to 5.5.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.5.2...webdrivermanager-5.5.3) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 17880238c..8a91c7d73 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.2') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { exclude group: 'org.seleniumhq.selenium' } testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.11.0') From a52aa43d376c2e531ebc8c310e3f0ed662c18ede Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 17:39:09 +0300 Subject: [PATCH 250/501] build(deps): Bump org.seleniumhq.selenium:selenium-bom (#1998) Bumps [org.seleniumhq.selenium:selenium-bom](https://github.com/SeleniumHQ/selenium) from 4.11.0 to 4.12.0. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.11.0...selenium-4.12.0) --- updated-dependencies: - dependency-name: org.seleniumhq.selenium:selenium-bom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8a91c7d73..0bc9176ca 100644 --- a/build.gradle +++ b/build.gradle @@ -62,7 +62,7 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { exclude group: 'org.seleniumhq.selenium' } - testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.11.0') + testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.12.0') testImplementation 'org.seleniumhq.selenium:selenium-api' testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' testImplementation 'org.seleniumhq.selenium:selenium-support' From 892b3ef20ff74a06c635c7e46f3d3f4924e2efc5 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 4 Sep 2023 17:53:11 +0300 Subject: [PATCH 251/501] docs: Add Selenium `4.12.0` to compatibility matrix (#1999) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 560610b0d..d15590125 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ dependencies { ### Compatibility Matrix | Appium Java Client | Selenium client | |--------------------|---------------------------------------------| -| `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0` | +| `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0` | | `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` | | `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` | | `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` | From 7975e57055026f6008f35eb4739b861dd723d496 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:12:07 +0300 Subject: [PATCH 252/501] build(deps): Bump slf4jVersion from 2.0.7 to 2.0.9 (#1997) Bumps `slf4jVersion` from 2.0.7 to 2.0.9. Updates `org.slf4j:slf4j-api` from 2.0.7 to 2.0.9 Updates `org.slf4j:slf4j-simple` from 2.0.7 to 2.0.9 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0bc9176ca..dcafd5e65 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.7' + slf4jVersion = '2.0.9' } dependencies { From 3e0daa2c403a9b6ad478ac72cc171bb2083e298f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 01:28:14 +0300 Subject: [PATCH 253/501] build(deps): Bump actions/checkout from 3 to 4 (#2000) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/gradle.yml | 2 +- .github/workflows/publish.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index a0d1170f2..f6851f4b1 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -23,5 +23,5 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a76a31d52..d427bec19 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -43,7 +43,7 @@ jobs: name: JDK ${{ matrix.java }} - ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8196bf5ff..7e95af207 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,7 +6,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Java uses: actions/setup-java@v3 with: From 18c61f271647922365d1931edcb6a41533a50c0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:40:50 +0300 Subject: [PATCH 254/501] build(deps): Bump org.seleniumhq.selenium:selenium-bom (#2001) Bumps [org.seleniumhq.selenium:selenium-bom](https://github.com/SeleniumHQ/selenium) from 4.12.0 to 4.12.1. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Commits](https://github.com/SeleniumHQ/selenium/commits) --- updated-dependencies: - dependency-name: org.seleniumhq.selenium:selenium-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dcafd5e65..ea1602d18 100644 --- a/build.gradle +++ b/build.gradle @@ -62,7 +62,7 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { exclude group: 'org.seleniumhq.selenium' } - testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.12.0') + testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.12.1') testImplementation 'org.seleniumhq.selenium:selenium-api' testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' testImplementation 'org.seleniumhq.selenium:selenium-support' From 2fd8c0cadce1a97a8a73e6ede893499f3d80414b Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 5 Sep 2023 23:22:10 +0300 Subject: [PATCH 255/501] docs: Add Selenium 4.12.1 to compatibility matrix (#2002) --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d15590125..7fd7a96ee 100644 --- a/README.md +++ b/README.md @@ -88,12 +88,12 @@ dependencies { ``` ### Compatibility Matrix -| Appium Java Client | Selenium client | -|--------------------|---------------------------------------------| -| `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0` | -| `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` | -| `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` | -| `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` | + Appium Java Client | Selenium client +--------------------|----------------- + `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` + `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` + `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` + `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` #### Why is it so complicated? From d8cf93c79df1b33a3aef3ac98ef8ba09733715ca Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 7 Sep 2023 18:33:02 +0200 Subject: [PATCH 256/501] tests: Remove obsolete API calls from tests (#2006) --- .../AndroidAbilityToUseSupplierTest.java | 7 +- .../android/AndroidActivityTest.java | 74 ------------------ .../android/AndroidContextTest.java | 3 +- .../android/AndroidDriverTest.java | 16 ++-- .../android/AndroidElementTest.java | 9 +-- .../android/AndroidFunctionTest.java | 3 +- .../android/AndroidScreenRecordTest.java | 3 +- .../android/AndroidSearchingTest.java | 3 +- .../java_client/android/AndroidTouchTest.java | 34 ++++----- .../java_client/android/BaseAndroidTest.java | 10 +++ .../java_client/android/ClipboardTest.java | 4 +- .../java_client/android/IntentTest.java | 75 ------------------- .../java_client/android/KeyCodeTest.java | 3 +- .../android/OpenNotificationsTest.java | 5 +- .../java_client/android/UIAutomator2Test.java | 3 +- .../appium/java_client/ios/IOSDriverTest.java | 23 ++---- 16 files changed, 55 insertions(+), 220 deletions(-) delete mode 100644 src/test/java/io/appium/java_client/android/AndroidActivityTest.java delete mode 100644 src/test/java/io/appium/java_client/android/IntentTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index 1a0cd129e..21389d54a 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; @@ -46,8 +47,7 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { .release(); @Test public void horizontalSwipingWithSupplier() { - Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); - driver.startActivity(activity); + startActivity(".view.Gallery1"); WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); int originalImageCount = images.size(); @@ -59,7 +59,8 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { } @Test public void verticalSwipingWithSupplier() throws Exception { - driver.resetApp(); + driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); driver.findElement(AppiumBy.accessibilityId("Views")).click(); Point originalLocation = driver.findElement(AppiumBy.accessibilityId("Gallery")).getLocation(); diff --git a/src/test/java/io/appium/java_client/android/AndroidActivityTest.java b/src/test/java/io/appium/java_client/android/AndroidActivityTest.java deleted file mode 100644 index 149a393c4..000000000 --- a/src/test/java/io/appium/java_client/android/AndroidActivityTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 io.appium.java_client.android.nativekey.AndroidKey; -import io.appium.java_client.android.nativekey.KeyEvent; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class AndroidActivityTest extends BaseAndroidTest { - - @BeforeEach public void setUp() { - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - driver.startActivity(activity); - } - - @Test public void startActivityInThisAppTestCase() { - Activity activity = new Activity("io.appium.android.apis", - ".accessibility.AccessibilityNodeProviderActivity"); - driver.startActivity(activity); - assertEquals(driver.currentActivity(), - ".accessibility.AccessibilityNodeProviderActivity"); - } - - @Test public void startActivityWithWaitingAppTestCase() { - final Activity activity = new Activity("io.appium.android.apis", - ".accessibility.AccessibilityNodeProviderActivity") - .setAppWaitPackage("io.appium.android.apis") - .setAppWaitActivity(".accessibility.AccessibilityNodeProviderActivity"); - driver.startActivity(activity); - assertEquals(driver.currentActivity(), - ".accessibility.AccessibilityNodeProviderActivity"); - } - - @Test public void startActivityInNewAppTestCase() { - Activity activity = new Activity("com.android.settings", ".Settings"); - driver.startActivity(activity); - assertEquals(driver.currentActivity(), ".Settings"); - driver.pressKey(new KeyEvent(AndroidKey.BACK)); - assertEquals(driver.currentActivity(), ".ApiDemos"); - } - - @Test public void startActivityInNewAppTestCaseWithoutClosingApp() { - Activity activity = new Activity("io.appium.android.apis", - ".accessibility.AccessibilityNodeProviderActivity"); - driver.startActivity(activity); - assertEquals(driver.currentActivity(), ".accessibility.AccessibilityNodeProviderActivity"); - - Activity newActivity = new Activity("com.android.settings", ".Settings") - .setAppWaitPackage("com.android.settings") - .setAppWaitActivity(".Settings") - .setStopApp(false); - driver.startActivity(newActivity); - assertEquals(driver.currentActivity(), ".Settings"); - driver.pressKey(new KeyEvent(AndroidKey.BACK)); - assertEquals(driver.currentActivity(), ".accessibility.AccessibilityNodeProviderActivity"); - } -} diff --git a/src/test/java/io/appium/java_client/android/AndroidContextTest.java b/src/test/java/io/appium/java_client/android/AndroidContextTest.java index 53a90f1dd..fdc47664b 100644 --- a/src/test/java/io/appium/java_client/android/AndroidContextTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidContextTest.java @@ -26,8 +26,7 @@ public class AndroidContextTest extends BaseAndroidTest { @BeforeAll public static void beforeClass2() throws Exception { - Activity activity = new Activity("io.appium.android.apis", ".view.WebView1"); - driver.startActivity(activity); + startActivity(".view.WebView1"); Thread.sleep(20000); } diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index 246951d8a..45f048272 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; import org.apache.commons.io.FileUtils; import org.hamcrest.Matchers; @@ -148,8 +149,8 @@ public void isAppNotInstalledTest() { @Test public void closeAppTest() { - driver.closeApp(); - driver.launchApp(); + driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); assertEquals(".ApiDemos", driver.currentActivity()); } @@ -241,11 +242,6 @@ public void pullFileTest() { assert (data.length > 0); } - @Test - public void resetTest() { - driver.resetApp(); - } - @Test public void deviceDetailsAndKeyboardTest() { assertFalse(driver.isKeyboardShown()); @@ -255,7 +251,7 @@ public void deviceDetailsAndKeyboardTest() { @Test public void getSupportedPerformanceDataTypesTest() { - driver.startActivity(new Activity(APP_ID, ".ApiDemos")); + startActivity(".ApiDemos"); List dataTypes = new ArrayList<>(); dataTypes.add("cpuinfo"); @@ -270,13 +266,11 @@ public void getSupportedPerformanceDataTypesTest() { for (int i = 0; i < supportedPerformanceDataTypes.size(); ++i) { assertEquals(dataTypes.get(i), supportedPerformanceDataTypes.get(i)); } - - } @Test public void getPerformanceDataTest() { - driver.startActivity(new Activity(APP_ID, ".ApiDemos")); + startActivity(".ApiDemos"); List supportedPerformanceDataTypes = driver.getSupportedPerformanceDataTypes(); diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/test/java/io/appium/java_client/android/AndroidElementTest.java index acb4d4dd2..44c8473d6 100644 --- a/src/test/java/io/appium/java_client/android/AndroidElementTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidElementTest.java @@ -30,8 +30,7 @@ public class AndroidElementTest extends BaseAndroidTest { @BeforeEach public void setup() { - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - driver.startActivity(activity); + startActivity(".ApiDemos"); } @@ -57,8 +56,7 @@ public class AndroidElementTest extends BaseAndroidTest { @Test public void replaceValueTest() { String originalValue = "original value"; - Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); - driver.startActivity(activity); + startActivity(".view.Controls1"); WebElement editElement = driver .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); editElement.sendKeys(originalValue); @@ -81,8 +79,7 @@ public class AndroidElementTest extends BaseAndroidTest { @Test public void setValueTest() { String value = "new value"; - Activity activity = new Activity("io.appium.android.apis", ".view.Controls1"); - driver.startActivity(activity); + startActivity(".view.Controls1"); WebElement editElement = driver .findElement(AppiumBy.androidUIAutomator("resourceId(\"io.appium.android.apis:id/edit\")")); editElement.sendKeys(value); diff --git a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java index 79a0d8870..79d327ae1 100644 --- a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java @@ -68,8 +68,7 @@ public class AndroidFunctionTest extends BaseAndroidTest { @BeforeAll public static void startWebViewActivity() { if (driver != null) { - Activity activity = new Activity("io.appium.android.apis", ".view.WebView1"); - driver.startActivity(activity); + startActivity(".view.WebView1"); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java b/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java index b0ec3a1e7..b9abd9ff6 100644 --- a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java @@ -15,8 +15,7 @@ public class AndroidScreenRecordTest extends BaseAndroidTest { @BeforeEach public void setUp() { - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - driver.startActivity(activity); + startActivity(".ApiDemos"); } @Test diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index c9b06c49f..64390962d 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -30,8 +30,7 @@ public class AndroidSearchingTest extends BaseAndroidTest { @BeforeEach public void setup() { - Activity activity = new Activity("io.appium.android.apis", ".ApiDemos"); - driver.startActivity(activity); + startActivity(".ApiDemos"); } @Test public void findByAccessibilityIdTest() { diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index f3c9c0394..84cb15753 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; @@ -25,12 +26,12 @@ public class AndroidTouchTest extends BaseAndroidTest { @BeforeEach public void setUp() { - driver.resetApp(); + driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); } @Test public void dragNDropByElementTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); - driver.startActivity(activity); + startActivity(".view.DragAndDropDemo"); WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); @@ -46,8 +47,7 @@ public void setUp() { } @Test public void dragNDropByElementAndDurationTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); - driver.startActivity(activity); + startActivity(".view.DragAndDropDemo"); WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); @@ -65,8 +65,7 @@ public void setUp() { } @Test public void dragNDropByCoordinatesTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); - driver.startActivity(activity); + startActivity(".view.DragAndDropDemo"); WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); @@ -85,8 +84,7 @@ public void setUp() { } @Test public void dragNDropByCoordinatesAndDurationTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.DragAndDropDemo"); - driver.startActivity(activity); + startActivity(".view.DragAndDropDemo"); WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); @@ -107,8 +105,7 @@ public void setUp() { } @Test public void pressByCoordinatesTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.Buttons1"); - driver.startActivity(activity); + startActivity(".view.Buttons1"); Point point = driver.findElement(By.id("io.appium.android.apis:id/button_toggle")).getLocation(); new TouchAction(driver) .press(point(point.x + 20, point.y + 30)) @@ -119,8 +116,7 @@ public void setUp() { } @Test public void pressByElementTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.Buttons1"); - driver.startActivity(activity); + startActivity(".view.Buttons1"); new TouchAction(driver) .press(element(driver.findElement(By.id("io.appium.android.apis:id/button_toggle")))) .waitAction(waitOptions(ofSeconds(1))) @@ -130,8 +126,7 @@ public void setUp() { } @Test public void tapActionTestByElement() throws Exception { - Activity activity = new Activity("io.appium.android.apis", ".view.ChronometerDemo"); - driver.startActivity(activity); + startActivity(".view.ChronometerDemo"); WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); TouchAction startStop = new TouchAction(driver) @@ -148,8 +143,7 @@ public void setUp() { } @Test public void tapActionTestByCoordinates() throws Exception { - Activity activity = new Activity("io.appium.android.apis", ".view.ChronometerDemo"); - driver.startActivity(activity); + startActivity(".view.ChronometerDemo"); WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); Point center1 = getCenter(driver.findElement(By.id("io.appium.android.apis:id/start"))); @@ -166,8 +160,7 @@ public void setUp() { } @Test public void horizontalSwipingTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.Gallery1"); - driver.startActivity(activity); + startActivity(".view.Gallery1"); WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); @@ -186,8 +179,7 @@ public void setUp() { } @Test public void multiTouchTest() { - Activity activity = new Activity("io.appium.android.apis", ".view.Buttons1"); - driver.startActivity(activity); + startActivity(".view.Buttons1"); TouchAction press = new TouchAction(driver) .press(element(driver.findElement(By.id("io.appium.android.apis:id/button_toggle")))) .waitAction(waitOptions(ofSeconds(1))) diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index d5eb6840f..28c1c95f4 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; @@ -59,4 +60,13 @@ public class BaseAndroidTest { service.stop(); } } + + public static void startActivity(String name) { + driver.executeScript( + "mobile: startActivity", + ImmutableMap.of( + "component", String.format("%s/%s", APP_ID, name) + ) + ); + } } diff --git a/src/test/java/io/appium/java_client/android/ClipboardTest.java b/src/test/java/io/appium/java_client/android/ClipboardTest.java index 353d9a579..7b576bcc2 100644 --- a/src/test/java/io/appium/java_client/android/ClipboardTest.java +++ b/src/test/java/io/appium/java_client/android/ClipboardTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,7 +25,8 @@ public class ClipboardTest extends BaseAndroidTest { @BeforeEach public void setUp() { - driver.resetApp(); + driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); } @Test public void verifySetAndGetClipboardText() { diff --git a/src/test/java/io/appium/java_client/android/IntentTest.java b/src/test/java/io/appium/java_client/android/IntentTest.java deleted file mode 100644 index ba4888821..000000000 --- a/src/test/java/io/appium/java_client/android/IntentTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.appium.java_client.android; - -import io.appium.java_client.android.options.UiAutomator2Options; -import io.appium.java_client.service.local.AppiumDriverLocalService; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.By; - -import java.util.function.Predicate; - -import static io.appium.java_client.TestResources.intentExampleApk; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class IntentTest { - private static AppiumDriverLocalService service; - protected static AndroidDriver driver; - - /** - * initialization. - */ - @BeforeAll public static void beforeClass() { - service = AppiumDriverLocalService.buildDefaultService(); - service.start(); - - if (service == null || !service.isRunning()) { - throw new RuntimeException("An appium server node is not started!"); - } - - UiAutomator2Options options = new UiAutomator2Options() - .setDeviceName("Android Emulator") - .setApp(intentExampleApk().toAbsolutePath().toString()); - driver = new AndroidDriver(service.getUrl(), options); - } - - /** - * finishing. - */ - @AfterAll public static void afterClass() { - if (driver != null) { - driver.quit(); - } - if (service != null) { - service.stop(); - } - } - - - @Test public void startActivityWithIntent() { - Predicate predicate = driver -> { - Activity activity = new Activity("com.android.mms", - ".ui.ComposeMessageActivity") - .setIntentAction("android.intent.action.SEND") - .setIntentCategory("android.intent.category.DEFAULT") - .setIntentFlags("0x4000000") - .setOptionalIntentArguments("-d \"TestIntent\" -t \"text/plain\""); - driver.startActivity(activity); - return true; - }; - assertTrue(predicate.test(driver)); - - } - - @Test public void startActivityWithDefaultIntentAndDefaultCategoryWithOptionalArgs() { - final Activity activity = new Activity("com.prgguru.android", ".GreetingActivity") - .setIntentAction("android.intent.action.MAIN") - .setIntentCategory("android.intent.category.DEFAULT") - .setIntentFlags("0x4000000") - .setOptionalIntentArguments("--es \"USERNAME\" \"AppiumIntentTest\" -t \"text/plain\""); - driver.startActivity(activity); - assertEquals(driver.findElement(By.id("com.prgguru.android:id/textView1")).getText(), - "Welcome AppiumIntentTest"); - } -} diff --git a/src/test/java/io/appium/java_client/android/KeyCodeTest.java b/src/test/java/io/appium/java_client/android/KeyCodeTest.java index 7c50f4ceb..7ed431166 100644 --- a/src/test/java/io/appium/java_client/android/KeyCodeTest.java +++ b/src/test/java/io/appium/java_client/android/KeyCodeTest.java @@ -33,8 +33,7 @@ public class KeyCodeTest extends BaseAndroidTest { @BeforeEach public void setUp() { - final Activity activity = new Activity(driver.getCurrentPackage(), ".text.KeyEventText"); - driver.startActivity(activity); + startActivity(".text.KeyEventText"); } @Test diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index bfb4e576a..1c5848934 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -1,5 +1,6 @@ package io.appium.java_client.android; +import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; @@ -13,7 +14,9 @@ public class OpenNotificationsTest extends BaseAndroidTest { @Test public void openNotification() { - driver.closeApp(); + driver.executeScript("mobile: terminateApp", ImmutableMap.of( + "appId", APP_ID + )); driver.openNotifications(); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20)); assertNotEquals(0, wait.until(input -> { diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java index 0d9da052d..47ac3239b 100644 --- a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java +++ b/src/test/java/io/appium/java_client/android/UIAutomator2Test.java @@ -59,8 +59,7 @@ public void testPortraitUpsideDown() { @Test public void testToastMSGIsDisplayed() { final WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); - Activity activity = new Activity("io.appium.android.apis", ".view.PopupMenu1"); - driver.startActivity(activity); + startActivity(".view.PopupMenu1"); wait.until(ExpectedConditions.presenceOfElementLocated(AppiumBy .accessibilityId("Make a Popup!"))); diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index f977289c0..6ead922b8 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; -import io.appium.java_client.remote.HideKeyboardStrategy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -29,8 +28,6 @@ import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.http.HttpMethod; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; @@ -60,10 +57,10 @@ public void addCustomCommandTest() { @Test public void addCustomCommandWithSessionIdTest() { - driver.addCommand(HttpMethod.POST, "/session/" + driver.getSessionId() + "/appium/app/launch", - "launchApplication"); - final Response launchApplication = driver.execute("launchApplication"); - assertNotNull(launchApplication.getSessionId()); + driver.addCommand(HttpMethod.POST, "/session/" + driver.getSessionId() + "/appium/app/strings", + "getAppStrings"); + final Response getStrings = driver.execute("getAppStrings"); + assertNotNull(getStrings.getSessionId()); } @Test @@ -85,14 +82,8 @@ public void getDeviceTimeTest() { } @Test public void resetTest() { - driver.resetApp(); - } - - @Test public void hideKeyboardWithParametersTest() { - new WebDriverWait(driver, Duration.ofSeconds(30)) - .until(ExpectedConditions.presenceOfElementLocated(By.id("IntegerA"))) - .click(); - driver.hideKeyboard(HideKeyboardStrategy.PRESS_KEY, "Done"); + driver.executeScript("mobile: terminateApp", ImmutableMap.of("bundleId", BUNDLE_ID)); + driver.executeScript("mobile: activateApp", ImmutableMap.of("bundleId", BUNDLE_ID)); } @Disabled @@ -170,7 +161,7 @@ public void putAIntoBackgroundWithoutRestoreTest() { driver.toggleTouchIDEnrollment(true); driver.performTouchID(true); driver.performTouchID(false); - //noinspection SimplifiableAssertion + //noinspection SimplifiableAssertion,EqualsWithItself assertEquals(true, true); } } From 923806ab01da3e7e23f175529153277b6a1691ed Mon Sep 17 00:00:00 2001 From: AlessandroMiccoli <57630383+AlessandroMiccoli@users.noreply.github.com> Date: Fri, 8 Sep 2023 07:08:02 +0100 Subject: [PATCH 257/501] feat: Implementation of Chromium driver plus capabilities (#2003) --- .../java_client/chromium/ChromiumDriver.java | 140 ++++++++++++++++++ .../chromium/options/ChromiumOptions.java | 58 ++++++++ .../options/SupportsAutodownloadOption.java | 51 +++++++ .../options/SupportsBuildCheckOption.java | 51 +++++++ .../SupportsChromeDrivePortOption.java | 51 +++++++ .../options/SupportsExecutableDirOption.java | 49 ++++++ .../options/SupportsExecutableOption.java | 48 ++++++ .../options/SupportsLogPathOption.java | 48 ++++++ .../SupportsUseSystemExecutableOption.java | 53 +++++++ .../options/SupportsVerboseOption.java | 51 +++++++ .../drivers/options/OptionsBuildingTest.java | 34 ++++- 11 files changed, 632 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/appium/java_client/chromium/ChromiumDriver.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsAutodownloadOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsChromeDrivePortOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsExecutableDirOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsExecutableOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsLogPathOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsUseSystemExecutableOption.java create mode 100644 src/main/java/io/appium/java_client/chromium/options/SupportsVerboseOption.java diff --git a/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java b/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java new file mode 100644 index 000000000..e6366f708 --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java @@ -0,0 +1,140 @@ +/* + * 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.chromium; + +import io.appium.java_client.AppiumClientConfig; +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.HttpClient; + +import java.net.URL; + +/** + *

ChromiumDriver is an officially supported Appium driver created to automate Mobile browsers + * and web views based on the Chromium engine. The driver uses W3CWebDriver protocol and is built + * on top of chromium driver server.

+ *
+ *
+ */ +public class ChromiumDriver extends AppiumDriver { + private static final String AUTOMATION_NAME = AutomationName.CHROMIUM; + + public ChromiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { + super(executor, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, + Capabilities capabilities) { + super(service, httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, + Capabilities capabilities) { + super(builder, httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + /** + * This is a special constructor used to connect to a running driver instance. + * It does not do any necessary verifications, but rather assumes the given + * driver session is already running at `remoteSessionAddress`. + * The maintenance of driver state(s) is the caller's responsibility. + * !!! This API is supposed to be used for **debugging purposes only**. + * + * @param remoteSessionAddress The address of the **running** session including the session identifier. + * @param platformName The name of the target platform. + */ + public ChromiumDriver(URL remoteSessionAddress, String platformName) { + super(remoteSessionAddress, platformName, AUTOMATION_NAME); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * ClientConfig clientConfig = ClientConfig.defaultConfig()
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * ChromiumOptions options = new ChromiumOptions();
+     * ChromiumDriver driver = new ChromiumDriver(clientConfig, options);
+     *
+     * 
+ * + * @param clientConfig take a look at {@link ClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public ChromiumDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(AppiumClientConfig.fromClientConfig(clientConfig), ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + /** + * Creates a new instance based on the given ClientConfig and {@code capabilities}. + * The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}. + * For example: + * + *
+     *
+     * AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
+     *     .directConnect(true)
+     *     .baseUri(URI.create("WebDriver URL"))
+     *     .readTimeout(Duration.ofMinutes(5));
+     * ChromiumOptions options = new ChromiumOptions();
+     * ChromiumDriver driver = new ChromiumDriver(options, appiumClientConfig);
+     *
+     * 
+ * + * @param appiumClientConfig take a look at {@link AppiumClientConfig} + * @param capabilities take a look at {@link Capabilities} + * + */ + public ChromiumDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, ensureAutomationName(capabilities, AUTOMATION_NAME)); + } + + public ChromiumDriver(Capabilities capabilities) { + super(ensureAutomationName(capabilities, AUTOMATION_NAME)); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java b/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java new file mode 100644 index 000000000..dfc5d7d02 --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java @@ -0,0 +1,58 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsBrowserNameOption; +import org.openqa.selenium.Capabilities; + +import java.util.Map; + +/** + *

Options class that sets options for Chromium when testing websites.

+ *
+ * @see appium-chromium-driver usage section + */ +public class ChromiumOptions extends BaseOptions implements + SupportsBrowserNameOption, + SupportsChromeDrivePortOption, + SupportsExecutableOption, + SupportsExecutableDirOption, + SupportsVerboseOption, + SupportsLogPathOption, + SupportsBuildCheckOption, + SupportsAutodownloadOption, + SupportsUseSystemExecutableOption { + public ChromiumOptions() { + setCommonOptions(); + } + + public ChromiumOptions(Capabilities source) { + super(source); + setCommonOptions(); + } + + public ChromiumOptions(Map source) { + super(source); + setCommonOptions(); + } + + private void setCommonOptions() { + setAutomationName(AutomationName.CHROMIUM); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsAutodownloadOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsAutodownloadOption.java new file mode 100644 index 000000000..a1cefdffe --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsAutodownloadOption.java @@ -0,0 +1,51 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsAutodownloadOption> extends + Capabilities, CanSetCapability { + String AUTODOWNLOAD_ENABLED = "autodownloadEnabled"; + + /** + * Set to false for disabling automatic downloading of Chrome drivers. + * Unless disable build check preference has been user-set, the capability + * is present because the default value is true. + * + * @param autodownloadEnabled flag. + * @return self instance for chaining. + */ + default T setAutodownloadEnabled(boolean autodownloadEnabled) { + return amend(AUTODOWNLOAD_ENABLED, autodownloadEnabled); + } + + /** + * Get the auto download flag. + * + * @return auto download flag. + */ + default Optional isAutodownloadEnabled() { + return Optional.ofNullable(toSafeBoolean(getCapability(AUTODOWNLOAD_ENABLED))); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java new file mode 100644 index 000000000..d9e95f065 --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java @@ -0,0 +1,51 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsBuildCheckOption> extends + Capabilities, CanSetCapability { + String DISABLE_BUILD_CHECK = "disableBuildCheck"; + + /** + * Set to true to add the --disable-build-check flag when starting WebDriver. + * Unless disable build check preference has been user-set, the capability + * is not present because the default value is false. + * + * @param BuildCheckDisabled flag for --disable-build-check. + * @return self instance for chaining. + */ + default T setBuildCheckDisabled(boolean BuildCheckDisabled) { + return amend(DISABLE_BUILD_CHECK, BuildCheckDisabled); + } + + /** + * Get disable build check flag. + * + * @return disable build check flag. + */ + default Optional isBuildCheckDisabled() { + return Optional.ofNullable(toSafeBoolean(getCapability(DISABLE_BUILD_CHECK))); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsChromeDrivePortOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsChromeDrivePortOption.java new file mode 100644 index 000000000..68cace279 --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsChromeDrivePortOption.java @@ -0,0 +1,51 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsChromeDrivePortOption> extends + Capabilities, CanSetCapability { + String CHROME_DRIVER_PORT = "chromedriverPort"; + + /** + * The port to start WebDriver processes on. Unless the chrome drive port preference + * has been user-set, it will listen on port 9515, which is the default + * value for this capability. + * + * @param port port number in range 0..65535. + * @return self instance for chaining. + */ + default T setChromeDriverPort(int port) { + return amend(CHROME_DRIVER_PORT, port); + } + + /** + * Get the number of the port for the chrome driver to listen on. + * + * @return Chrome driver port value. + */ + default Optional getChromeDriverPort() { + return Optional.ofNullable(toInteger(getCapability(CHROME_DRIVER_PORT))); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsExecutableDirOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsExecutableDirOption.java new file mode 100644 index 000000000..c525ab7ad --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsExecutableDirOption.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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsExecutableDirOption> extends + Capabilities, CanSetCapability { + String EXECUTABLE_DIR = "executableDir"; + + /** + * A directory within which is found any number of WebDriver binaries. + * If set, the driver will search this directory for WebDrivers of the + * appropriate version to use for your browser. + * + * @param directory of WebDriver binaries. + * @return self instance for chaining. + */ + default T setExecutableDir(String directory) { + return amend(EXECUTABLE_DIR, directory); + } + + /** + * Get a directory within which is found any number of WebDriver binaries. + * + * @return executable directory of a Driver binary. + */ + default Optional getExecutableDir() { + return Optional.ofNullable((String) getCapability(EXECUTABLE_DIR)); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsExecutableOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsExecutableOption.java new file mode 100644 index 000000000..84e730e62 --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsExecutableOption.java @@ -0,0 +1,48 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsExecutableOption> extends + Capabilities, CanSetCapability { + String EXECUTABLE = "executable"; + + /** + * The absolute path to a WebDriver binary executable. + * If set, the driver will use that path instead of its own WebDriver. + * + * @param path absolute of a WebDriver. + * @return self instance for chaining. + */ + default T setExecutable(String path) { + return amend(EXECUTABLE, path); + } + + /** + * Get the absolute path to a WebDriver binary executable. + * + * @return executable absolute path. + */ + default Optional getExecutable() { + return Optional.ofNullable((String) getCapability(EXECUTABLE)); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsLogPathOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsLogPathOption.java new file mode 100644 index 000000000..cf1b8713d --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsLogPathOption.java @@ -0,0 +1,48 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsLogPathOption> extends + Capabilities, CanSetCapability { + String LOG_PATH = "logPath"; + + /** + * If set, the path to use with the --log-path parameter directing + * WebDriver to write its log to that path. + * + * @param logPath where to write the logs. + * @return self instance for chaining. + */ + default T setLogPath(String logPath) { + return amend(LOG_PATH, logPath); + } + + /** + * Get the log path where the WebDrive writes the logs. + * + * @return the log path. + */ + default Optional getLogPath() { + return Optional.ofNullable((String) getCapability(LOG_PATH)); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsUseSystemExecutableOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsUseSystemExecutableOption.java new file mode 100644 index 000000000..6d51b332b --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsUseSystemExecutableOption.java @@ -0,0 +1,53 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUseSystemExecutableOption> extends + Capabilities, CanSetCapability { + String USE_SYSTEM_EXECUTABLE = "useSystemExecutable"; + + /** + * Set to true to use the version of WebDriver bundled with this driver, + * rather than attempting to download a new one based on the version of the + * browser under test. + * Unless disable build check preference has been user-set, the capability + * is not present because the default value is false. + * + * @param useSystemExecutable flag. + * @return self instance for chaining. + */ + default T setUseSystemExecutable(boolean useSystemExecutable) { + return amend(USE_SYSTEM_EXECUTABLE, useSystemExecutable); + } + + /** + * Get the use system executable flag. + * + * @return use system executable flag. + */ + default Optional isUseSystemExecutable() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_SYSTEM_EXECUTABLE))); + } +} diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsVerboseOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsVerboseOption.java new file mode 100644 index 000000000..14aa571d2 --- /dev/null +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsVerboseOption.java @@ -0,0 +1,51 @@ +/* + * 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.chromium.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsVerboseOption> extends + Capabilities, CanSetCapability { + String VERBOSE = "verbose"; + + /** + * Set to true to add the --verbose flag when starting WebDriver. + * Unless the verbose preference has been user-set, the capability + * is not present because the default value is false. + * + * @param verbose flag for --verbose. + * @return self instance for chaining. + */ + default T setVerbose(boolean verbose) { + return amend(VERBOSE, verbose); + } + + /** + * Get the verbose flag. + * + * @return verbose flag. + */ + default Optional isVerbose() { + return Optional.ofNullable(toSafeBoolean(getCapability(VERBOSE))); + } +} diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java index 908ff709e..04574448c 100644 --- a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -23,6 +23,7 @@ import io.appium.java_client.android.options.localization.AppLocale; import io.appium.java_client.android.options.server.EspressoBuildConfig; import io.appium.java_client.android.options.signing.KeystoreConfig; +import io.appium.java_client.chromium.options.ChromiumOptions; import io.appium.java_client.gecko.options.GeckoOptions; import io.appium.java_client.gecko.options.Verbosity; import io.appium.java_client.ios.options.XCUITestOptions; @@ -112,7 +113,7 @@ public void canBuildEspressoOptions() { assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); assertEquals("CN", options.getAppLocale().orElse(null).getCountry().orElse(null)); assertEquals(2, options.getEspressoBuildConfig().orElse(null) - .left().getAdditionalAppDependencies().orElse(null).size()); + .left().getAdditionalAppDependencies().orElse(null).size()); assertTrue(options.doesForceEspressoRebuild().orElse(false)); } @@ -154,7 +155,7 @@ public void canBuildGeckoOptions() { options.setNewCommandTimeout(Duration.ofSeconds(10)) .setVerbosity(Verbosity.TRACE) .setMozFirefoxOptions(ImmutableMap.of( - "profile", "yolo" + "profile", "yolo" )); assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); assertEquals(Verbosity.TRACE, options.getVerbosity().orElse(null)); @@ -180,4 +181,33 @@ public void canBuildSafariOptions() { assertTrue(options.getWebkitWebrtc().orElse(null) .doesDisableInsecureMediaCapture().orElse(false)); } + + @Test + public void canBuildChromiumOptions() { + // Given + // When + ChromiumOptions options = new ChromiumOptions(); + + options.setNewCommandTimeout(Duration.ofSeconds(10)) + .setPlatformName(Platform.MAC.name()) + .withBrowserName("Chrome") + .setAutodownloadEnabled(true) + .setBuildCheckDisabled(true) + .setChromeDriverPort(5485) + .setExecutable("/absolute/executable/path") + .setLogPath("/wonderful/log/path") + .setVerbose(true); + + // Then + assertEquals(AutomationName.CHROMIUM, options.getAutomationName().orElse(null)); + assertEquals("Chrome", options.getBrowserName()); + assertTrue(options.isAutodownloadEnabled().orElse(null)); + assertTrue(options.isBuildCheckDisabled().orElse(null)); + assertEquals(5485, options.getChromeDriverPort().orElse(null)); + assertFalse(options.getExecutableDir().isPresent()); + assertEquals("/absolute/executable/path", options.getExecutable().orElse(null)); + assertEquals("/wonderful/log/path", options.getLogPath().orElse(null)); + assertFalse(options.isUseSystemExecutable().isPresent()); + assertTrue(options.isVerbose().orElse(null)); + } } From 692e3a0311c39f47d9d6687eb6bec09f32f95e6b Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sun, 10 Sep 2023 08:14:13 +0300 Subject: [PATCH 258/501] docs: Add known compatibility issue for Selenium `4.12.1` (#2008) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fd7a96ee..dacbe1340 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client --------------------|----------------- - `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` + `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004) `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` From 4e3b23bb9077bb932f890ed6706e5f7339091d7d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 20 Sep 2023 14:58:59 +0300 Subject: [PATCH 259/501] fix: Change scope of `selenium-support` dependency to `compile` (#2019) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ea1602d18..1021b18b2 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ dependencies { prefer "${seleniumVersion}" } } - implementation ('org.seleniumhq.selenium:selenium-support') { + api ('org.seleniumhq.selenium:selenium-support') { version { strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" From 01b9e16127dfcd60ce73d2fd1bd0f2602010f909 Mon Sep 17 00:00:00 2001 From: ashwithpoojary98 <61794427+ashwithpoojary98@users.noreply.github.com> Date: Sat, 23 Sep 2023 23:31:30 +0530 Subject: [PATCH 260/501] fix: Fix Code style issues to match Java standards (#2017) --- .../java/io/appium/java_client/AppiumBy.java | 22 +++++++ .../java_client/CommandExecutionHelper.java | 3 + .../appium/java_client/ErrorCodesMobile.java | 3 + .../appium/java_client/InteractsWithApps.java | 8 +-- .../appium/java_client/ScreenshotState.java | 4 +- .../java/io/appium/java_client/Setting.java | 1 + .../android/options/app/IntentOptions.java | 10 ++-- .../app/SupportsActivityOptionsOption.java | 2 +- .../app/SupportsIntentOptionsOption.java | 2 +- .../options/avd/SupportsAvdArgsOption.java | 2 +- .../options/avd/SupportsAvdEnvOption.java | 2 +- .../localization/SupportsAppLocaleOption.java | 2 +- .../options/server/EspressoBuildConfig.java | 2 +- .../SupportsEspressoBuildConfigOption.java | 2 +- .../options/SupportsBuildCheckOption.java | 6 +- .../OccurrenceMatchingResult.java | 2 +- .../internal/CapabilityHelpers.java | 3 + .../appium/java_client/internal/Config.java | 2 +- .../internal/ReflectionHelpers.java | 13 ++-- .../java_client/internal/SessionHelpers.java | 3 + .../other/SupportsCommandTimeoutsOption.java | 2 +- .../simulator/SupportsPermissionsOption.java | 2 +- ...imulatorPasteboardAutomaticSyncOption.java | 2 +- .../ios/options/wda/ProcessArguments.java | 4 +- .../wda/SupportsWaitForIdleTimeoutOption.java | 2 +- .../SupportsWdaEventloopIdleDelayOption.java | 2 +- .../wda/SupportsXcodeCertificateOptions.java | 2 +- .../java_client/mac/options/Mac2Options.java | 4 +- .../pagefactory/AppiumElementLocator.java | 4 +- .../pagefactory/AppiumFieldDecorator.java | 2 +- .../pagefactory/OverrideWidgetReader.java | 35 ++++++----- .../pagefactory/ThrowableUtil.java | 3 + .../java_client/pagefactory/WithTimeout.java | 4 ++ .../pagefactory/bys/ContentMappedBy.java | 59 +++++++++++++------ .../bys/builder/AppiumByBuilder.java | 22 +++---- .../pagefactory/bys/builder/Strategies.java | 2 +- .../utils/WebDriverUnpackUtility.java | 3 + .../appium/java_client/proxy/Interceptor.java | 3 + .../remote/AppiumCommandExecutor.java | 2 +- .../options/SupportsOrientationOption.java | 2 +- .../remote/options/SupportsProxyOption.java | 2 +- .../options/UnhandledPromptBehavior.java | 2 +- .../local/AppiumDriverLocalService.java | 19 +++--- .../service/local/AppiumServiceBuilder.java | 4 +- .../service/local/ListOutputStream.java | 2 + .../windows/options/WindowsOptions.java | 10 ++-- 46 files changed, 188 insertions(+), 106 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 297e9a9b3..7e067287d 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -25,6 +25,7 @@ import java.io.Serializable; import java.util.List; +import java.util.Objects; public abstract class AppiumBy extends By implements Remotable { @@ -253,6 +254,27 @@ protected ByIosNsPredicate(String locatorString) { super("-ios predicate string", locatorString, "iOSNsPredicate"); } } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AppiumBy appiumBy = (AppiumBy) o; + return Objects.equals(remoteParameters, appiumBy.remoteParameters) + && Objects.equals(locatorName, appiumBy.locatorName); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), remoteParameters, locatorName); + } } diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 0a41f17b6..7abfef612 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -17,6 +17,8 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; @@ -26,6 +28,7 @@ import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class CommandExecutionHelper { @Nullable diff --git a/src/main/java/io/appium/java_client/ErrorCodesMobile.java b/src/main/java/io/appium/java_client/ErrorCodesMobile.java index 6e7e66d69..473c014d9 100644 --- a/src/main/java/io/appium/java_client/ErrorCodesMobile.java +++ b/src/main/java/io/appium/java_client/ErrorCodesMobile.java @@ -43,6 +43,7 @@ public class ErrorCodesMobile extends ErrorCodes { * @param statusCode The status code to convert. * @return The exception type that corresponds to the provided status */ + @Override public Class getExceptionType(int statusCode) { switch (statusCode) { case NO_SUCH_CONTEXT: @@ -60,6 +61,7 @@ public Class getExceptionType(int statusCode) { * @return The exception type that corresponds to the provided error message or {@code null} if * there are no matching mobile exceptions. */ + @Override public Class getExceptionType(String message) { for (Map.Entry entry : statusToState.entrySet()) { if (message.contains(entry.getValue())) { @@ -75,6 +77,7 @@ public Class getExceptionType(String message) { * @param thrown The thrown error. * @return The corresponding status code for the given thrown error. */ + @Override public int toStatusCode(Throwable thrown) { if (thrown instanceof NoSuchContextException) { return NO_SUCH_CONTEXT; diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index 45f1c285d..d61f85b19 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -75,7 +75,7 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions Map args = ImmutableMap.builder() .put("appPath", appPath) .putAll(Optional.ofNullable(options).map( - (opts) -> ImmutableMap.of("options", opts.build()) + opts -> ImmutableMap.of("options", opts.build()) ).orElseGet(ImmutableMap::of)) .build(); CommandExecutionHelper.execute( @@ -169,7 +169,7 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption Map args = ImmutableMap.builder() .put("bundleId", bundleId) .putAll(Optional.ofNullable(options).map( - (opts) -> ImmutableMap.of("options", opts.build()) + opts -> ImmutableMap.of("options", opts.build()) ).orElseGet(ImmutableMap::of)) .build(); //noinspection RedundantCast @@ -214,7 +214,7 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio Map args = ImmutableMap.builder() .put("bundleId", bundleId) .putAll(Optional.ofNullable(options).map( - (opts) -> ImmutableMap.of("options", opts.build()) + opts -> ImmutableMap.of("options", opts.build()) ).orElseGet(ImmutableMap::of)) .build(); CommandExecutionHelper.execute( @@ -290,7 +290,7 @@ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplication Map args = ImmutableMap.builder() .put("bundleId", bundleId) .putAll(Optional.ofNullable(options).map( - (opts) -> ImmutableMap.of("options", opts.build()) + opts -> ImmutableMap.of("options", opts.build()) ).orElseGet(ImmutableMap::of)) .build(); //noinspection RedundantCast diff --git a/src/main/java/io/appium/java_client/ScreenshotState.java b/src/main/java/io/appium/java_client/ScreenshotState.java index 8c88397e5..1747a1e41 100644 --- a/src/main/java/io/appium/java_client/ScreenshotState.java +++ b/src/main/java/io/appium/java_client/ScreenshotState.java @@ -175,7 +175,7 @@ private ScreenshotState checkState(Function checkerFunc, Durati * @throws ScreenshotComparisonError if {@link #remember()} method has not been invoked yet */ public ScreenshotState verifyChanged(Duration timeout, double minScore) { - return checkState((x) -> x < minScore, timeout); + return checkState(x -> x < minScore, timeout); } /** @@ -190,7 +190,7 @@ public ScreenshotState verifyChanged(Duration timeout, double minScore) { * @throws ScreenshotComparisonError if {@link #remember()} method has not been invoked yet */ public ScreenshotState verifyNotChanged(Duration timeout, double minScore) { - return checkState((x) -> x >= minScore, timeout); + return checkState(x -> x >= minScore, timeout); } /** diff --git a/src/main/java/io/appium/java_client/Setting.java b/src/main/java/io/appium/java_client/Setting.java index b5b84ca16..cc1f44cd1 100644 --- a/src/main/java/io/appium/java_client/Setting.java +++ b/src/main/java/io/appium/java_client/Setting.java @@ -65,6 +65,7 @@ public enum Setting { this.name = name; } + @Override public String toString() { return this.name; } diff --git a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java index e651a4b91..67f09f2b5 100644 --- a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java +++ b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java @@ -261,7 +261,7 @@ public IntentOptions withEi(Map ei) { private Map convertMapValues(Map map, Function converter) { return map.entrySet().stream() .collect(Collectors.toMap( - Map.Entry::getKey, (entry) -> converter.apply(String.valueOf(entry.getValue()))) + Map.Entry::getKey, entry -> converter.apply(String.valueOf(entry.getValue()))) ); } @@ -272,7 +272,7 @@ private Map convertMapValues(Map map, Function> getEi() { Optional> value = getOptionValue("ei"); - return value.map((v) -> convertMapValues(v, Integer::parseInt)); + return value.map(v -> convertMapValues(v, Integer::parseInt)); } /** @@ -292,7 +292,7 @@ public IntentOptions withEl(Map el) { */ public Optional> getEl() { Optional> value = getOptionValue("el"); - return value.map((v) -> convertMapValues(v, Long::parseLong)); + return value.map(v -> convertMapValues(v, Long::parseLong)); } /** @@ -312,7 +312,7 @@ public IntentOptions withEf(Map ef) { */ public Optional> getEf() { Optional> value = getOptionValue("ef"); - return value.map((v) -> convertMapValues(v, Float::parseFloat)); + return value.map(v -> convertMapValues(v, Float::parseFloat)); } /** @@ -356,7 +356,7 @@ public Optional> getEcn() { private static Map mergeValues(Map map) { return map.entrySet().stream() .collect( - Collectors.toMap(Map.Entry::getKey, (entry) -> ((List) entry.getValue()).stream() + Collectors.toMap(Map.Entry::getKey, entry -> ((List) entry.getValue()).stream() .map(String::valueOf) .collect(Collectors.joining(","))) ); diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java index 393ee51c5..59d5fe520 100644 --- a/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsActivityOptionsOption.java @@ -48,6 +48,6 @@ default T setActivityOptions(ActivityOptions options) { default Optional getActivityOptions() { //noinspection unchecked return Optional.ofNullable(getCapability(ACTIVITY_OPTIONS_OPTION)) - .map((v) -> new ActivityOptions((Map) v)); + .map(v -> new ActivityOptions((Map) v)); } } diff --git a/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java index 91c2b49a2..3c0fab894 100644 --- a/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java +++ b/src/main/java/io/appium/java_client/android/options/app/SupportsIntentOptionsOption.java @@ -48,6 +48,6 @@ default T setIntentOptions(IntentOptions options) { default Optional getIntentOptions() { //noinspection unchecked return Optional.ofNullable(getCapability(INTENT_OPTIONS_OPTION)) - .map((v) -> new IntentOptions((Map) v)); + .map(v -> new IntentOptions((Map) v)); } } diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java index 7843393e4..bca9866c0 100644 --- a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdArgsOption.java @@ -56,7 +56,7 @@ default T setAvdArgs(String args) { default Optional, String>> getAvdArgs() { //noinspection unchecked return Optional.ofNullable(getCapability(AVD_ARGS_OPTION)) - .map((v) -> v instanceof List + .map(v -> v instanceof List ? Either.left((List) v) : Either.right(String.valueOf(v)) ); diff --git a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java index e6d083aee..9fadb6532 100644 --- a/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java +++ b/src/main/java/io/appium/java_client/android/options/avd/SupportsAvdEnvOption.java @@ -45,6 +45,6 @@ default T setAvdEnv(Map env) { default Optional> getAvdEnv() { //noinspection unchecked return Optional.ofNullable(getCapability(AVD_ENV_OPTION)) - .map((v) -> (Map) v); + .map(v -> (Map) v); } } diff --git a/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java b/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java index 40447d749..d8fafba02 100644 --- a/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java +++ b/src/main/java/io/appium/java_client/android/options/localization/SupportsAppLocaleOption.java @@ -51,6 +51,6 @@ default T setAppLocale(AppLocale locale) { default Optional getAppLocale() { //noinspection unchecked return Optional.ofNullable(getCapability(APP_LOCALE_OPTION)) - .map((v) -> new AppLocale((Map) v)); + .map(v -> new AppLocale((Map) v)); } } diff --git a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java index 2044f0bd1..24adc5675 100644 --- a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java +++ b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java @@ -51,7 +51,7 @@ private EspressoBuildConfig assignToolsVersionsField(String name, Object value) private Optional getToolsVersionsFieldValue(String name) { Optional> toolsVersionsOptional = getOptionValue(TOOLS_VERSION); //noinspection unchecked - return toolsVersionsOptional.map((v) -> (R) v.getOrDefault(name, null)); + return toolsVersionsOptional.map(v -> (R) v.getOrDefault(name, null)); } /** diff --git a/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java index 93eb19831..a916ec35b 100644 --- a/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java +++ b/src/main/java/io/appium/java_client/android/options/server/SupportsEspressoBuildConfigOption.java @@ -61,7 +61,7 @@ default T setEspressoBuildConfig(EspressoBuildConfig config) { default Optional> getEspressoBuildConfig() { return Optional.ofNullable(getCapability(ESPRESSO_BUILD_CONFIG_OPTION)) .map(String::valueOf) - .map((v) -> v.trim().startsWith("{") + .map(v -> v.trim().startsWith("{") ? Either.left(new EspressoBuildConfig(v)) : Either.right(v) ); diff --git a/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java b/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java index d9e95f065..204967bca 100644 --- a/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java +++ b/src/main/java/io/appium/java_client/chromium/options/SupportsBuildCheckOption.java @@ -33,11 +33,11 @@ public interface SupportsBuildCheckOption> extends * Unless disable build check preference has been user-set, the capability * is not present because the default value is false. * - * @param BuildCheckDisabled flag for --disable-build-check. + * @param buildCheckDisabled flag for --disable-build-check. * @return self instance for chaining. */ - default T setBuildCheckDisabled(boolean BuildCheckDisabled) { - return amend(DISABLE_BUILD_CHECK, BuildCheckDisabled); + default T setBuildCheckDisabled(boolean buildCheckDisabled) { + return amend(DISABLE_BUILD_CHECK, buildCheckDisabled); } /** diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java index 256a1636a..510f64b8e 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java @@ -65,7 +65,7 @@ public List getMultiple() { //noinspection unchecked List> multiple = (List>) getCommandResult().get(MULTIPLE); return multiple.stream() - .map((m) -> new OccurrenceMatchingResult(m, false)) + .map(m -> new OccurrenceMatchingResult(m, false)) .collect(Collectors.toList()); } } diff --git a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java index 3645a7520..5280b8e17 100644 --- a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java +++ b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java @@ -16,6 +16,8 @@ package io.appium.java_client.internal; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.openqa.selenium.Capabilities; import javax.annotation.Nullable; @@ -26,6 +28,7 @@ import java.util.List; import java.util.function.Function; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class CapabilityHelpers { public static final String APPIUM_PREFIX = "appium:"; diff --git a/src/main/java/io/appium/java_client/internal/Config.java b/src/main/java/io/appium/java_client/internal/Config.java index fd9ef73c1..83bfb7995 100644 --- a/src/main/java/io/appium/java_client/internal/Config.java +++ b/src/main/java/io/appium/java_client/internal/Config.java @@ -58,7 +58,7 @@ public T getValue(String key, Class valueType) { * @throws ClassCastException if the retrieved value cannot be cast to `valueType` type */ public Optional getOptionalValue(String key, Class valueType) { - final Properties cachedProps = cache.computeIfAbsent(configName, (k) -> { + final Properties cachedProps = cache.computeIfAbsent(configName, k -> { try (InputStream configFileStream = getClass().getClassLoader().getResourceAsStream(configName)) { final Properties p = new Properties(); p.load(configFileStream); diff --git a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java index cbaa7c796..abe16a170 100644 --- a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java +++ b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java @@ -16,19 +16,22 @@ package io.appium.java_client.internal; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.openqa.selenium.WebDriverException; import java.lang.reflect.Field; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class ReflectionHelpers { /** * Sets the given value to a private instance field. * - * @param cls The target class or a superclass. - * @param target Target instance. + * @param cls The target class or a superclass. + * @param target Target instance. * @param fieldName Target field name. - * @param newValue The value to be set. + * @param newValue The value to be set. * @return The same instance for chaining. */ public static T setPrivateFieldValue(Class cls, T target, String fieldName, Object newValue) { @@ -45,8 +48,8 @@ public static T setPrivateFieldValue(Class cls, T target, String fieldNam /** * Fetches the value of a private instance field. * - * @param cls The target class or a superclass. - * @param target Target instance. + * @param cls The target class or a superclass. + * @param target Target instance. * @param fieldName Target field name. * @param fieldType Field type. * @return The retrieved field value. diff --git a/src/main/java/io/appium/java_client/internal/SessionHelpers.java b/src/main/java/io/appium/java_client/internal/SessionHelpers.java index b3b9f0eca..c028bdfb5 100644 --- a/src/main/java/io/appium/java_client/internal/SessionHelpers.java +++ b/src/main/java/io/appium/java_client/internal/SessionHelpers.java @@ -16,7 +16,9 @@ package io.appium.java_client.internal; +import lombok.AccessLevel; import lombok.Data; +import lombok.NoArgsConstructor; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.WebDriverException; @@ -25,6 +27,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class SessionHelpers { private static final Pattern SESSION = Pattern.compile("/session/([^/]+)"); diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java index 0afd1a9a8..4461985c1 100644 --- a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java @@ -62,7 +62,7 @@ default T setCommandTimeouts(Duration timeout) { default Optional> getCommandTimeouts() { return Optional.ofNullable(getCapability(COMMAND_TIMEOUTS_OPTION)) .map(String::valueOf) - .map((v) -> v.trim().startsWith("{") + .map(v -> v.trim().startsWith("{") ? Either.left(new CommandTimeouts(v)) : Either.right(toDuration(v)) ); diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java index e3a4b36c2..3f55a335c 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsPermissionsOption.java @@ -44,6 +44,6 @@ default T setPermissions(Permissions permissions) { */ default Optional getPermissions() { return Optional.ofNullable(getCapability(PERMISSIONS_OPTION)) - .map((v) -> new Permissions(String.valueOf(v))); + .map(v -> new Permissions(String.valueOf(v))); } } diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java index 7f99af2e0..665c4d368 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java @@ -47,6 +47,6 @@ default T setSimulatorPasteboardAutomaticSync(PasteboardSyncState state) { */ default Optional getSimulatorPasteboardAutomaticSync() { return Optional.ofNullable(getCapability(SIMULATOR_PASTEBOARD_AUTOMATIC_SYNC)) - .map((v) -> PasteboardSyncState.valueOf(String.valueOf(v).toUpperCase())); + .map(v -> PasteboardSyncState.valueOf(String.valueOf(v).toUpperCase())); } } diff --git a/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java b/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java index c5ed74d22..08b06f9f8 100644 --- a/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java +++ b/src/main/java/io/appium/java_client/ios/options/wda/ProcessArguments.java @@ -49,8 +49,8 @@ public ProcessArguments(Map env) { */ public Map toMap() { Map result = new HashMap<>(); - Optional.ofNullable(args).ifPresent((v) -> result.put("args", v)); - Optional.ofNullable(env).ifPresent((v) -> result.put("env", v)); + Optional.ofNullable(args).ifPresent(v -> result.put("args", v)); + Optional.ofNullable(env).ifPresent(v -> result.put("env", v)); return Collections.unmodifiableMap(result); } } diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java index 0d9ffda35..f9dd2401a 100644 --- a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWaitForIdleTimeoutOption.java @@ -53,6 +53,6 @@ default T setWaitForIdleTimeout(Duration timeout) { default Optional getWaitForIdleTimeout() { return Optional.ofNullable(getCapability(WAIT_FOR_IDLE_TIMEOUT_OPTION)) .map(CapabilityHelpers::toDouble) - .map((d) -> toDuration((long) (d * 1000.0))); + .map(d -> toDuration((long) (d * 1000.0))); } } diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java index 4d35bb5c4..3d48703b5 100644 --- a/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsWdaEventloopIdleDelayOption.java @@ -54,6 +54,6 @@ default T setWdaEventloopIdleDelay(Duration duration) { default Optional getWdaEventloopIdleDelay() { return Optional.ofNullable(getCapability(WDA_EVENTLOOP_IDLE_DELAY_OPTION)) .map(CapabilityHelpers::toDouble) - .map((d) -> toDuration((long) (d * 1000.0))); + .map(d -> toDuration((long) (d * 1000.0))); } } diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java index fcecbab8c..45d437195 100644 --- a/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsXcodeCertificateOptions.java @@ -51,6 +51,6 @@ default Optional getXcodeCertificate() { String orgId = (String) getCapability(XCODE_ORG_ID_OPTION); String signingId = (String) getCapability(XCODE_SIGNING_ID_OPTION); return Optional.ofNullable(orgId) - .map((x) -> new XcodeCertificate(orgId, signingId)); + .map(x -> new XcodeCertificate(orgId, signingId)); } } diff --git a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java index 37e31575a..5325ee284 100644 --- a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java +++ b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java @@ -83,7 +83,7 @@ public Mac2Options setPrerun(AppleScriptData script) { public Optional getPrerun() { //noinspection unchecked return Optional.ofNullable(getCapability(PRERUN_OPTION)) - .map((v) -> new AppleScriptData((Map) v)); + .map(v -> new AppleScriptData((Map) v)); } /** @@ -108,6 +108,6 @@ public Mac2Options setPostrun(AppleScriptData script) { public Optional getPostrun() { //noinspection unchecked return Optional.ofNullable(getCapability(POSTRUN_OPTION)) - .map((v) -> new AppleScriptData((Map) v)); + .map(v -> new AppleScriptData((Map) v)); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java index 3aba5bcdc..9e148a2c7 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java @@ -43,7 +43,7 @@ class AppiumElementLocator implements CacheableLocator { - private static final String exceptionMessageIfElementNotFound = "Can't locate an element by this strategy: %s"; + private static final String EXCEPTION_MESSAGE_IF_ELEMENT_NOT_FOUND = "Can't locate an element by this strategy: %s"; private final boolean shouldCache; private final By by; @@ -163,7 +163,7 @@ public WebElement findElement() { } return result; } catch (TimeoutException | StaleElementReferenceException e) { - throw new NoSuchElementException(format(exceptionMessageIfElementNotFound, bySearching.toString()), e); + throw new NoSuchElementException(format(EXCEPTION_MESSAGE_IF_ELEMENT_NOT_FOUND, bySearching.toString()), e); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index c2f11f473..2d5daaa03 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -170,7 +170,7 @@ protected boolean isDecoratableList(Field field) { ? Arrays.asList(((TypeVariable) listType).getBounds()) : Collections.emptyList(); return availableElementClasses.stream() - .anyMatch((webElClass) -> webElClass.equals(listType) || bounds.contains(webElClass)); + .anyMatch(webElClass -> webElClass.equals(listType) || bounds.contains(webElClass)); } }; } diff --git a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java index be25f1c31..9f8b59c17 100644 --- a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java +++ b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java @@ -17,6 +17,8 @@ package io.appium.java_client.pagefactory; import io.appium.java_client.pagefactory.bys.ContentType; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; @@ -29,6 +31,7 @@ import static io.appium.java_client.remote.MobilePlatform.IOS; import static io.appium.java_client.remote.MobilePlatform.WINDOWS; +@NoArgsConstructor(access = AccessLevel.PRIVATE) class OverrideWidgetReader { private static final Class EMPTY = Widget.class; private static final String HTML = "html"; @@ -38,15 +41,15 @@ class OverrideWidgetReader { @SuppressWarnings("unchecked") private static Class getConvenientClass(Class declaredClass, - AnnotatedElement annotatedElement, String method) { + AnnotatedElement annotatedElement, String method) { Class convenientClass; OverrideWidget overrideWidget = annotatedElement.getAnnotation(OverrideWidget.class); try { if (overrideWidget == null || (convenientClass = - (Class) OverrideWidget.class - .getDeclaredMethod(method).invoke(overrideWidget)) - .equals(EMPTY)) { + (Class) OverrideWidget.class + .getDeclaredMethod(method).invoke(overrideWidget)) + .equals(EMPTY)) { convenientClass = declaredClass; } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { @@ -55,9 +58,9 @@ private static Class getConvenientClass(Class getConvenientClass(Class getDefaultOrHTMLWidgetClass( - Class declaredClass, AnnotatedElement annotatedElement) { + Class declaredClass, AnnotatedElement annotatedElement) { return getConvenientClass(declaredClass, annotatedElement, HTML); } static Class getMobileNativeWidgetClass(Class declaredClass, - AnnotatedElement annotatedElement, String platform) { + AnnotatedElement annotatedElement, String platform) { String transformedPlatform = String.valueOf(platform).toUpperCase().trim(); if (ANDROID.equalsIgnoreCase(transformedPlatform)) { @@ -89,26 +92,26 @@ static Class getMobileNativeWidgetClass(Class getConstructorOfADefaultOrHTMLWidget( - Class declaredClass, AnnotatedElement annotatedElement) { + Class declaredClass, AnnotatedElement annotatedElement) { Class clazz = - getDefaultOrHTMLWidgetClass(declaredClass, annotatedElement); + getDefaultOrHTMLWidgetClass(declaredClass, annotatedElement); return findConvenientConstructor(clazz); } private static Constructor getConstructorOfAMobileNativeWidgets( - Class declaredClass, AnnotatedElement annotatedElement, String platform) { + Class declaredClass, AnnotatedElement annotatedElement, String platform) { Class clazz = - getMobileNativeWidgetClass(declaredClass, annotatedElement, platform); + getMobileNativeWidgetClass(declaredClass, annotatedElement, platform); return findConvenientConstructor(clazz); } protected static Map> read( - Class declaredClass, AnnotatedElement annotatedElement, String platform) { + Class declaredClass, AnnotatedElement annotatedElement, String platform) { Map> result = new HashMap<>(); result.put(ContentType.HTML_OR_DEFAULT, - getConstructorOfADefaultOrHTMLWidget(declaredClass, annotatedElement)); + getConstructorOfADefaultOrHTMLWidget(declaredClass, annotatedElement)); result.put(ContentType.NATIVE_MOBILE_SPECIFIC, - getConstructorOfAMobileNativeWidgets(declaredClass, annotatedElement, platform)); + getConstructorOfAMobileNativeWidgets(declaredClass, annotatedElement, platform)); return result; } } diff --git a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java index c025a53dd..f5b310702 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java +++ b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java @@ -16,11 +16,14 @@ package io.appium.java_client.pagefactory; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.openqa.selenium.InvalidSelectorException; import org.openqa.selenium.StaleElementReferenceException; import java.lang.reflect.InvocationTargetException; +@NoArgsConstructor(access = AccessLevel.PRIVATE) class ThrowableUtil { private static final String INVALID_SELECTOR_PATTERN = "Invalid locator strategy:"; diff --git a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java index 0b95a50c1..0727bc2b3 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java +++ b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java @@ -16,6 +16,9 @@ package io.appium.java_client.pagefactory; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,6 +46,7 @@ */ ChronoUnit chronoUnit(); + @NoArgsConstructor(access = AccessLevel.PRIVATE) class DurationBuilder { static Duration build(WithTimeout withTimeout) { return Duration.of(withTimeout.time(), withTimeout.chronoUnit()); diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java index fe7edf9b9..30bf58456 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java @@ -1,18 +1,18 @@ /* -* 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. -*/ + * 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.pagefactory.bys; @@ -23,6 +23,7 @@ import javax.annotation.Nonnull; import java.util.List; import java.util.Map; +import java.util.Objects; import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; @@ -37,6 +38,7 @@ public ContentMappedBy(Map map) { /** * This method sets required content type for the further searching. + * * @param type required content type {@link ContentType} * @return self-reference. */ @@ -46,15 +48,38 @@ public By useContent(@Nonnull ContentType type) { return this; } - @Override public WebElement findElement(SearchContext context) { + @Override + public WebElement findElement(SearchContext context) { return context.findElement(map.get(currentContent)); } - @Override public List findElements(SearchContext context) { + @Override + public List findElements(SearchContext context) { return context.findElements(map.get(currentContent)); } - @Override public String toString() { + @Override + public String toString() { return map.get(currentContent).toString(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + ContentMappedBy that = (ContentMappedBy) o; + return Objects.equals(map, that.map) && currentContent == that.currentContent; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), map, currentContent); + } } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java index 330362140..0e7146a0c 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java @@ -39,10 +39,10 @@ import static io.appium.java_client.remote.MobilePlatform.WINDOWS; /** - * It is the basic handler of Appium-specific page object annotations + * It is the basic handler of Appium-specific page object annotations. * About the Page Object design pattern please read these documents: - * - https://code.google.com/p/selenium/wiki/PageObjects - * - https://code.google.com/p/selenium/wiki/PageFactory + * - Selenium Page Object models + * - Selenium Page Factory */ public abstract class AppiumByBuilder extends AbstractAnnotations { protected static final Class[] DEFAULT_ANNOTATION_METHOD_ARGUMENTS = new Class[]{}; @@ -76,7 +76,7 @@ private static Method[] prepareAnnotationMethods(Class ann List targetAnnotationMethodNamesList = getMethodNames(annotation.getDeclaredMethods()); targetAnnotationMethodNamesList.removeAll(METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ); return targetAnnotationMethodNamesList.stream() - .map((methodName) -> { + .map(methodName -> { try { return annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); } catch (NoSuchMethodException | SecurityException e) { @@ -87,13 +87,13 @@ private static Method[] prepareAnnotationMethods(Class ann private static String getFilledValue(Annotation mobileBy) { return Stream.of(prepareAnnotationMethods(mobileBy.getClass())) - .filter((method) -> String.class == method.getReturnType()) - .filter((method) -> { + .filter(method -> String.class == method.getReturnType()) + .filter(method -> { try { Object strategyParameter = method.invoke(mobileBy); return strategyParameter != null && !String.valueOf(strategyParameter).isEmpty(); } catch (IllegalAccessException | IllegalArgumentException - | InvocationTargetException e) { + | InvocationTargetException e) { throw new RuntimeException(e); } }) @@ -107,9 +107,9 @@ private static String getFilledValue(Annotation mobileBy) { private static By getMobileBy(Annotation annotation, String valueName) { return Stream.of(Strategies.values()) - .filter((strategy) -> strategy.returnValueName().equals(valueName)) + .filter(strategy -> strategy.returnValueName().equals(valueName)) .findFirst() - .map((strategy) -> strategy.getBy(annotation)) + .map(strategy -> strategy.getBy(annotation)) .orElseThrow(() -> new IllegalArgumentException( String.format("@%s: There is an unknown strategy %s", annotation.getClass().getSimpleName(), valueName) @@ -118,14 +118,14 @@ private static By getMobileBy(Annotation annotation, String valueName) { private static T getComplexMobileBy(Annotation[] annotations, Class requiredByClass) { By[] byArray = Stream.of(annotations) - .map((annotation) -> getMobileBy(annotation, getFilledValue(annotation))) + .map(annotation -> getMobileBy(annotation, getFilledValue(annotation))) .toArray(By[]::new); try { Constructor c = requiredByClass.getConstructor(By[].class); Object[] values = new Object[]{byArray}; return c.newInstance(values); } catch (InvocationTargetException | NoSuchMethodException | InstantiationException - | IllegalAccessException e) { + | IllegalAccessException e) { throw new RuntimeException(e); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index a353e0257..452a8cda0 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -135,7 +135,7 @@ enum Strategies { } static List strategiesNames() { - return Stream.of(values()).map((s) -> s.valueName).collect(Collectors.toList()); + return Stream.of(values()).map(s -> s.valueName).collect(Collectors.toList()); } private static String getValue(Annotation annotation, Strategies strategy) { diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 53ba1506c..9df129930 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -18,6 +18,8 @@ import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.openqa.selenium.ContextAware; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; @@ -31,6 +33,7 @@ import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class WebDriverUnpackUtility { private static final String NATIVE_APP_PATTERN = "NATIVE_APP"; diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java index dce2fd807..aca474044 100644 --- a/src/main/java/io/appium/java_client/proxy/Interceptor.java +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -16,6 +16,8 @@ package io.appium.java_client.proxy; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import net.bytebuddy.implementation.bind.annotation.AllArguments; import net.bytebuddy.implementation.bind.annotation.Origin; import net.bytebuddy.implementation.bind.annotation.RuntimeType; @@ -29,6 +31,7 @@ import java.util.UUID; import java.util.concurrent.Callable; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class Interceptor { private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 0085f457d..ee0e5a396 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -180,7 +180,7 @@ private Response createSession(Command command) throws IOException { } ProtocolHandshake.Result result = new AppiumProtocolHandshake().createSession( - getClient().with((httpHandler) -> (req) -> { + getClient().with(httpHandler -> req -> { req.setHeader(HttpHeaders.USER_AGENT, AppiumUserAgentFilter.buildUserAgent(req.getHeader(HttpHeaders.USER_AGENT))); req.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java index 3bc8b16e0..be2dd1a5d 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java @@ -42,7 +42,7 @@ default T setOrientation(ScreenOrientation orientation) { */ default Optional getOrientation() { return Optional.ofNullable(getCapability(ORIENTATION_OPTION)) - .map((v) -> v instanceof ScreenOrientation + .map(v -> v instanceof ScreenOrientation ? (ScreenOrientation) v : ScreenOrientation.valueOf((String.valueOf(v)).toUpperCase()) ); diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java index cb3de55e7..d69be4d2b 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsProxyOption.java @@ -45,7 +45,7 @@ default T setProxy(Proxy proxy) { default Optional getProxy() { return Optional.ofNullable(getCapability(PROXY_OPTION)) .map(String::valueOf) - .map((v) -> new Gson().fromJson(v, Map.class)) + .map(v -> new Gson().fromJson(v, Map.class)) .map(Proxy::new); } } diff --git a/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java b/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java index 0068dfe42..3aa5f4add 100644 --- a/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java +++ b/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java @@ -38,7 +38,7 @@ public String toString() { */ public static UnhandledPromptBehavior fromString(String value) { return Arrays.stream(values()) - .filter((v) -> v.toString().equals(value)) + .filter(v -> v.toString().equals(value)) .findFirst() .orElseThrow(() -> new IllegalArgumentException( String.format("Unhandled prompt behavior '%s' is not supported. " diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 08f289289..f37b89e29 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -145,15 +145,15 @@ public boolean isRunning() { } private void ping(Duration timeout) throws UrlChecker.TimeoutException, MalformedURLException { - URL url = getUrl(); - String host = url.getHost(); + URL baseURL = getUrl(); + String host = baseURL.getHost(); // The operating system will block direct access to the universal broadcast IP address if (host.equals(BROADCAST_IP4_ADDRESS)) { - url = replaceHost(url, BROADCAST_IP4_ADDRESS, "127.0.0.1"); + baseURL = replaceHost(baseURL, BROADCAST_IP4_ADDRESS, "127.0.0.1"); } else if (host.equals(BROADCAST_IP6_ADDRESS)) { - url = replaceHost(url, BROADCAST_IP6_ADDRESS, "::1"); + baseURL = replaceHost(baseURL, BROADCAST_IP6_ADDRESS, "::1"); } - URL status = addSuffix(url, "/status"); + URL status = addSuffix(baseURL, "/status"); new UrlChecker().waitUntilAvailable(timeout.toMillis(), TimeUnit.MILLISECONDS, status); } @@ -163,6 +163,7 @@ private void ping(Duration timeout) throws UrlChecker.TimeoutException, Malforme * @throws AppiumServerHasNotBeenStartedLocallyException If an error occurs while spawning the child process. * @see #stop() */ + @Override public void start() throws AppiumServerHasNotBeenStartedLocallyException { lock.lock(); try { @@ -182,7 +183,7 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { } catch (Exception e) { final Optional output = Optional.ofNullable(process) .map(CommandLine::getStdOut) - .filter((o) -> !StringUtils.isBlank(o)); + .filter(o -> !StringUtils.isBlank(o)); destroyProcess(); List errorLines = new ArrayList<>(); errorLines.add("The local appium server has not been started"); @@ -197,7 +198,7 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { String.format("Node.js executable path: %s", nodeJSExec.getAbsolutePath()) ); errorLines.add(String.format("Arguments: %s", nodeJSArgs)); - output.ifPresent((o) -> errorLines.add(String.format("Output: %s", o))); + output.ifPresent(o -> errorLines.add(String.format("Output: %s", o))); throw new AppiumServerHasNotBeenStartedLocallyException( StringUtils.joinWith("\n", errorLines), e ); @@ -302,8 +303,8 @@ public void addOutPutStream(OutputStream outputStream) { */ public void addOutPutStreams(List outputStreams) { checkNotNull(outputStreams, "outputStreams parameter is NULL!"); - for (OutputStream stream : outputStreams) { - addOutPutStream(stream); + for (OutputStream outputStream : outputStreams) { + addOutPutStream(outputStream); } } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 0e354d441..774399a9c 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -81,9 +81,9 @@ public final class AppiumServiceBuilder private String ipAddress = BROADCAST_IP4_ADDRESS; private Capabilities capabilities; private boolean autoQuoteCapabilitiesOnWindows = false; - private static final Function APPIUM_JS_NOT_EXIST_ERROR = (fullPath) -> String.format( + private static final Function APPIUM_JS_NOT_EXIST_ERROR = fullPath -> String.format( "The main Appium script does not exist at '%s'", fullPath.getAbsolutePath()); - private static final Function NODE_JS_NOT_EXIST_ERROR = (fullPath) -> + private static final Function NODE_JS_NOT_EXIST_ERROR = fullPath -> String.format("The main NodeJS executable does not exist at '%s'", fullPath.getAbsolutePath()); private static final List PATH_CAPABILITIES = ImmutableList.of(AndroidMobileCapabilityType.KEYSTORE_PATH, diff --git a/src/main/java/io/appium/java_client/service/local/ListOutputStream.java b/src/main/java/io/appium/java_client/service/local/ListOutputStream.java index 89820f70a..7173963ad 100644 --- a/src/main/java/io/appium/java_client/service/local/ListOutputStream.java +++ b/src/main/java/io/appium/java_client/service/local/ListOutputStream.java @@ -53,12 +53,14 @@ Optional remove(OutputStream stream) { } } + @Override public void flush() throws IOException { for (OutputStream stream : streams) { stream.flush(); } } + @Override public void close() throws IOException { for (OutputStream stream : streams) { stream.close(); diff --git a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java index 8a1f0eb8f..fd4d125b0 100644 --- a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java +++ b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java @@ -28,7 +28,7 @@ import java.util.Optional; /** - * https://github.com/appium/appium-windows-driver#usage + * https://github.com/appium/appium-windows-driver#usage */ public class WindowsOptions extends BaseOptions implements SupportsAppOption, @@ -65,7 +65,7 @@ private void setCommonOptions() { * each key must be a valid PowerShell script or command to be * executed prior to the WinAppDriver session startup. * See - * https://github.com/appium/appium-windows-driver#power-shell-commands-execution + * https://github.com/appium/appium-windows-driver#power-shell-commands-execution * for more details. * * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. @@ -83,7 +83,7 @@ public WindowsOptions setPrerun(PowerShellData script) { public Optional getPrerun() { //noinspection unchecked return Optional.ofNullable(getCapability(PRERUN_OPTION)) - .map((v) -> new PowerShellData((Map) v)); + .map(v -> new PowerShellData((Map) v)); } /** @@ -91,7 +91,7 @@ public Optional getPrerun() { * each key must be a valid PowerShell script or command to be * executed after an WinAppDriver session is finished. * See - * https://github.com/appium/appium-windows-driver#power-shell-commands-execution + * https://github.com/appium/appium-windows-driver#power-shell-commands-execution * for more details. * * @param script E.g. {script: 'Get-Process outlook -ErrorAction SilentlyContinue'}. @@ -109,6 +109,6 @@ public WindowsOptions setPostrun(PowerShellData script) { public Optional getPostrun() { //noinspection unchecked return Optional.ofNullable(getCapability(POSTRUN_OPTION)) - .map((v) -> new PowerShellData((Map) v)); + .map(v -> new PowerShellData((Map) v)); } } From 7157251e9ec6de0566e9bb10a9b8dd9582d5e041 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:30:15 +0300 Subject: [PATCH 261/501] build(deps): Bump org.projectlombok:lombok from 1.18.28 to 1.18.30 (#2022) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.28 to 1.18.30. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.28...v1.18.30) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1021b18b2..958e67905 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.28' - annotationProcessor 'org.projectlombok:lombok:1.18.28' + compileOnly 'org.projectlombok:lombok:1.18.30' + annotationProcessor 'org.projectlombok:lombok:1.18.30' api ('org.seleniumhq.selenium:selenium-api') { version { From 0a2bfee430435921637677e78f9abc9e210e2f1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 11:47:50 +0300 Subject: [PATCH 262/501] build(deps): Bump org.seleniumhq.selenium:selenium-bom (#2024) Bumps [org.seleniumhq.selenium:selenium-bom](https://github.com/SeleniumHQ/selenium) from 4.12.1 to 4.13.0. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Commits](https://github.com/SeleniumHQ/selenium/commits/selenium-4.13.0) --- updated-dependencies: - dependency-name: org.seleniumhq.selenium:selenium-bom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 958e67905..44cd0c8d1 100644 --- a/build.gradle +++ b/build.gradle @@ -62,7 +62,7 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { exclude group: 'org.seleniumhq.selenium' } - testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.12.1') + testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.13.0') testImplementation 'org.seleniumhq.selenium:selenium-api' testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' testImplementation 'org.seleniumhq.selenium:selenium-support' From 0ac4b4236319f74b20c846dfda3af4acf2fe5eb7 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 27 Sep 2023 10:40:44 -0700 Subject: [PATCH 263/501] fix: class of proxy method in AppiumClientConfig (#2026) --- src/main/java/io/appium/java_client/AppiumClientConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java index b25a3032d..c8e123fc9 100644 --- a/src/main/java/io/appium/java_client/AppiumClientConfig.java +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -147,7 +147,7 @@ public AppiumClientConfig withRetries() { @Override - public ClientConfig proxy(Proxy proxy) { + public AppiumClientConfig proxy(Proxy proxy) { ClientConfig clientConfig = super.proxy(proxy); return buildAppiumClientConfig(clientConfig, directConnect); } From e7482971479935ecd304ad0e231c68b90b7243f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:09:51 +0300 Subject: [PATCH 264/501] build(deps): Bump commons-io:commons-io from 2.13.0 to 2.14.0 (#2027) Bumps commons-io:commons-io from 2.13.0 to 2.14.0. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 44cd0c8d1..ff247ab7f 100644 --- a/build.gradle +++ b/build.gradle @@ -53,7 +53,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.13.0' - implementation 'commons-io:commons-io:2.13.0' + implementation 'commons-io:commons-io:2.14.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' From a5a25b51a08062e96b0189e8a2aece031fdc06da Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 3 Oct 2023 10:50:50 +0300 Subject: [PATCH 265/501] docs: Add Selenium 4.13.0 to compatibility matrix (#2025) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dacbe1340..97ecb5017 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client --------------------|----------------- - `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004) + `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` From f875c3b86aa0f14e27a91d0a3d1f8e51d02e9054 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 3 Oct 2023 11:32:26 +0300 Subject: [PATCH 266/501] chore: Automate more static code checks (#2028) --- config/checkstyle/appium-style.xml | 10 ++++++++++ .../java/io/appium/java_client/AppiumDriver.java | 6 +++--- .../appium/java_client/CommandExecutionHelper.java | 6 +++--- src/main/java/io/appium/java_client/LogsEvents.java | 4 ++-- .../java/io/appium/java_client/MobileCommand.java | 3 ++- .../android/AndroidMobileCommandHelper.java | 3 +-- .../java_client/internal/CapabilityHelpers.java | 6 +++--- .../java/io/appium/java_client/internal/Config.java | 4 ++-- .../java_client/internal/ReflectionHelpers.java | 6 +++--- .../appium/java_client/internal/SessionHelpers.java | 6 +++--- .../pagefactory/AppiumFieldDecorator.java | 4 ++-- .../pagefactory/DefaultElementByBuilder.java | 2 +- .../pagefactory/OverrideWidgetReader.java | 6 +++--- .../java_client/pagefactory/ThrowableUtil.java | 6 +++--- .../java_client/pagefactory/WidgetInterceptor.java | 2 +- .../pagefactory/WidgetListInterceptor.java | 2 +- .../appium/java_client/pagefactory/WithTimeout.java | 7 +++---- .../pagefactory/utils/WebDriverUnpackUtility.java | 6 +++--- .../io/appium/java_client/proxy/Interceptor.java | 12 ++++++------ .../remote/options/BaseMapOptionData.java | 8 ++++---- .../java_client/remote/options/BaseOptions.java | 2 +- .../java/io/appium/java_client/TestResources.java | 3 +++ src/test/java/io/appium/java_client/TestUtils.java | 3 +++ .../java_client/android/AndroidDriverTest.java | 7 +++---- .../android/AndroidLogcatListenerTest.java | 2 +- .../appium/java_client/android/BaseAndroidTest.java | 1 + .../appium/java_client/android/BaseEspressoTest.java | 1 + .../drivers/options/OptionsBuildingTest.java | 2 +- .../java/io/appium/java_client/ios/BaseIOSTest.java | 1 + .../java/io/appium/java_client/ios/IOSAlertTest.java | 4 ++-- .../java_client/ios/IOSSyslogListenerTest.java | 2 +- 31 files changed, 77 insertions(+), 60 deletions(-) diff --git a/config/checkstyle/appium-style.xml b/config/checkstyle/appium-style.xml index 2feb5eeff..630949b66 100755 --- a/config/checkstyle/appium-style.xml +++ b/config/checkstyle/appium-style.xml @@ -128,6 +128,7 @@

Read appium-chromium-driver + * for more details on how to configure and use it.

+ @@ -198,6 +199,12 @@ + + + + + + @@ -208,4 +215,7 @@ + + + diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index ead0a05d0..749a0204d 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -70,7 +70,7 @@ public class AppiumDriver extends RemoteWebDriver implements CanRememberExtensionPresence, HasSettings { - private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); + private static final ErrorHandler ERROR_HANDLER = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters private final URL remoteAddress; protected final RemoteLocationContext locationContext; @@ -89,7 +89,7 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, capabilities); this.executeMethod = new AppiumExecutionMethod(this); locationContext = new RemoteLocationContext(executeMethod); - super.setErrorHandler(errorHandler); + super.setErrorHandler(ERROR_HANDLER); this.remoteAddress = executor.getAddressOfRemoteServer(); } @@ -167,7 +167,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa setCommandExecutor(executor); this.executeMethod = new AppiumExecutionMethod(this); locationContext = new RemoteLocationContext(executeMethod); - super.setErrorHandler(errorHandler); + super.setErrorHandler(ERROR_HANDLER); this.remoteAddress = executor.getAddressOfRemoteServer(); setSessionId(sessionAddress.getId()); diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 7abfef612..692f7cf0f 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -17,8 +17,6 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; @@ -28,9 +26,11 @@ import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class CommandExecutionHelper { + private CommandExecutionHelper() { + } + @Nullable public static T execute( ExecutesMethod executesMethod, Map.Entry> keyValuePair diff --git a/src/main/java/io/appium/java_client/LogsEvents.java b/src/main/java/io/appium/java_client/LogsEvents.java index a29d9eecf..33f50d2db 100644 --- a/src/main/java/io/appium/java_client/LogsEvents.java +++ b/src/main/java/io/appium/java_client/LogsEvents.java @@ -63,8 +63,8 @@ default ServerEvents getEvents() { .stream() .map((Map cmd) -> new CommandEvent( (String) cmd.get("cmd"), - ((Long) cmd.get("startTime")), - ((Long) cmd.get("endTime")) + (Long) cmd.get("startTime"), + (Long) cmd.get("endTime") )) .collect(Collectors.toList()); diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 721c854a7..d61a3ef01 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -38,6 +38,7 @@ * Most of these commands are platform-specific obsolete things and should eventually be replaced with * calls to corresponding `mobile:` extensions, so we don't abuse non-w3c APIs */ +@SuppressWarnings({"checkstyle:HideUtilityClassConstructor", "checkstyle:ConstantName"}) public class MobileCommand { //General @Deprecated @@ -434,7 +435,7 @@ public static ImmutableMap prepareArguments(String[] params, Object[] values) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (int i = 0; i < params.length; i++) { - if (!StringUtils.isBlank(params[i]) && (values[i] != null)) { + if (!StringUtils.isBlank(params[i]) && values[i] != null) { builder.put(params[i], values[i]); } } 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 1bed116d7..562eb9172 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -214,8 +214,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { String intentAction, String intentCategory, String intentFlags, String optionalIntentArguments, boolean stopApp) throws IllegalArgumentException { - checkArgument((!StringUtils.isBlank(appPackage) - && !StringUtils.isBlank(appActivity)), + checkArgument(!StringUtils.isBlank(appPackage) && !StringUtils.isBlank(appActivity), String.format("'%s' and '%s' are required.", "appPackage", "appActivity")); String targetWaitPackage = !StringUtils.isBlank(appWaitPackage) ? appWaitPackage : ""; diff --git a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java index 5280b8e17..855a40cdb 100644 --- a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java +++ b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java @@ -16,8 +16,6 @@ package io.appium.java_client.internal; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.openqa.selenium.Capabilities; import javax.annotation.Nullable; @@ -28,10 +26,12 @@ import java.util.List; import java.util.function.Function; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class CapabilityHelpers { public static final String APPIUM_PREFIX = "appium:"; + private CapabilityHelpers() { + } + /** * Helper that is used for capability values retrieval. * Supports both prefixed W3C and "classic" capability names. diff --git a/src/main/java/io/appium/java_client/internal/Config.java b/src/main/java/io/appium/java_client/internal/Config.java index 83bfb7995..4413f28ab 100644 --- a/src/main/java/io/appium/java_client/internal/Config.java +++ b/src/main/java/io/appium/java_client/internal/Config.java @@ -11,7 +11,7 @@ public class Config { private static Config mainInstance = null; private static final String MAIN_CONFIG = "main.properties"; - private static final Map cache = new ConcurrentHashMap<>(); + private static final Map CACHE = new ConcurrentHashMap<>(); private final String configName; /** @@ -58,7 +58,7 @@ public T getValue(String key, Class valueType) { * @throws ClassCastException if the retrieved value cannot be cast to `valueType` type */ public Optional getOptionalValue(String key, Class valueType) { - final Properties cachedProps = cache.computeIfAbsent(configName, k -> { + final Properties cachedProps = CACHE.computeIfAbsent(configName, k -> { try (InputStream configFileStream = getClass().getClassLoader().getResourceAsStream(configName)) { final Properties p = new Properties(); p.load(configFileStream); diff --git a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java index abe16a170..10375e2ad 100644 --- a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java +++ b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java @@ -16,15 +16,15 @@ package io.appium.java_client.internal; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.openqa.selenium.WebDriverException; import java.lang.reflect.Field; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class ReflectionHelpers { + private ReflectionHelpers() { + } + /** * Sets the given value to a private instance field. * diff --git a/src/main/java/io/appium/java_client/internal/SessionHelpers.java b/src/main/java/io/appium/java_client/internal/SessionHelpers.java index c028bdfb5..51371dbd1 100644 --- a/src/main/java/io/appium/java_client/internal/SessionHelpers.java +++ b/src/main/java/io/appium/java_client/internal/SessionHelpers.java @@ -16,9 +16,7 @@ package io.appium.java_client.internal; -import lombok.AccessLevel; import lombok.Data; -import lombok.NoArgsConstructor; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.WebDriverException; @@ -27,10 +25,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class SessionHelpers { private static final Pattern SESSION = Pattern.compile("/session/([^/]+)"); + private SessionHelpers() { + } + @Data public static class SessionAddress { private final URL serverUrl; private final String id; diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 2d5daaa03..b0c8cd428 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -62,7 +62,7 @@ */ public class AppiumFieldDecorator implements FieldDecorator { - private static final List> availableElementClasses = ImmutableList.of( + private static final List> AVAILABLE_ELEMENT_CLASSES = ImmutableList.of( WebElement.class, RemoteWebElement.class ); @@ -169,7 +169,7 @@ protected boolean isDecoratableList(Field field) { List bounds = (listType instanceof TypeVariable) ? Arrays.asList(((TypeVariable) listType).getBounds()) : Collections.emptyList(); - return availableElementClasses.stream() + return AVAILABLE_ELEMENT_CLASSES.stream() .anyMatch(webElClass -> webElClass.equals(listType) || bounds.contains(webElClass)); } }; diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index 23195e5ce..5cb10c9de 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -186,7 +186,7 @@ protected By buildMobileNativeBy() { @Override public boolean isLookupCached() { AnnotatedElement annotatedElement = annotatedElementContainer.getAnnotated(); - return (annotatedElement.getAnnotation(CacheLookup.class) != null); + return annotatedElement.getAnnotation(CacheLookup.class) != null; } private By returnMappedBy(By byDefault, By nativeAppBy) { diff --git a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java index 9f8b59c17..e08f413dd 100644 --- a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java +++ b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java @@ -17,8 +17,6 @@ package io.appium.java_client.pagefactory; import io.appium.java_client.pagefactory.bys.ContentType; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; @@ -31,7 +29,6 @@ import static io.appium.java_client.remote.MobilePlatform.IOS; import static io.appium.java_client.remote.MobilePlatform.WINDOWS; -@NoArgsConstructor(access = AccessLevel.PRIVATE) class OverrideWidgetReader { private static final Class EMPTY = Widget.class; private static final String HTML = "html"; @@ -39,6 +36,9 @@ class OverrideWidgetReader { private static final String IOS_XCUIT_AUTOMATION = "iOSXCUITAutomation"; private static final String WINDOWS_AUTOMATION = "windowsAutomation"; + private OverrideWidgetReader() { + } + @SuppressWarnings("unchecked") private static Class getConvenientClass(Class declaredClass, AnnotatedElement annotatedElement, String method) { diff --git a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java index f5b310702..af09676f7 100644 --- a/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java +++ b/src/main/java/io/appium/java_client/pagefactory/ThrowableUtil.java @@ -16,17 +16,17 @@ package io.appium.java_client.pagefactory; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.openqa.selenium.InvalidSelectorException; import org.openqa.selenium.StaleElementReferenceException; import java.lang.reflect.InvocationTargetException; -@NoArgsConstructor(access = AccessLevel.PRIVATE) class ThrowableUtil { private static final String INVALID_SELECTOR_PATTERN = "Invalid locator strategy:"; + private ThrowableUtil() { + } + protected static boolean isInvalidSelectorRootCause(Throwable e) { if (e == null) { return false; diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java index d00c6e3c9..bfc358bd8 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java @@ -67,7 +67,7 @@ protected Object getObject(WebElement element, Method method, Object[] args) thr ContentType type = getCurrentContentType(element); WebElement cachedElement = cachedElementReference == null ? null : cachedElementReference.get(); if (cachedElement == null || !cachedInstances.containsKey(type) - || (locator != null && !((CacheableLocator) locator).isLookUpCached()) + || locator != null && !((CacheableLocator) locator).isLookUpCached() ) { cachedElementReference = new WeakReference<>(element); diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java index 031a0e624..ff9983f8c 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java @@ -71,7 +71,7 @@ protected Object getObject(List elements, Method method, Object[] ar .filter(Objects::nonNull) .collect(Collectors.toList()); if (cachedElements.size() != cachedWidgets.size() - || (locator != null && !((CacheableLocator) locator).isLookUpCached())) { + || locator != null && !((CacheableLocator) locator).isLookUpCached()) { cachedWidgets.clear(); cachedElementReferences.clear(); diff --git a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java index 0727bc2b3..0b04dadf2 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java +++ b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java @@ -16,9 +16,6 @@ package io.appium.java_client.pagefactory; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -46,8 +43,10 @@ */ ChronoUnit chronoUnit(); - @NoArgsConstructor(access = AccessLevel.PRIVATE) class DurationBuilder { + private DurationBuilder() { + } + static Duration build(WithTimeout withTimeout) { return Duration.of(withTimeout.time(), withTimeout.chronoUnit()); } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 9df129930..6d31fcc5a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -18,8 +18,6 @@ import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.openqa.selenium.ContextAware; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; @@ -33,10 +31,12 @@ import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class WebDriverUnpackUtility { private static final String NATIVE_APP_PATTERN = "NATIVE_APP"; + private WebDriverUnpackUtility() { + } + /** * This method extract an instance of {@link WebDriver} from the given {@link SearchContext}. * @param searchContext is an instance of {@link SearchContext}. It may be the instance of diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java index aca474044..fa4d72405 100644 --- a/src/main/java/io/appium/java_client/proxy/Interceptor.java +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -16,8 +16,6 @@ package io.appium.java_client.proxy; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import net.bytebuddy.implementation.bind.annotation.AllArguments; import net.bytebuddy.implementation.bind.annotation.Origin; import net.bytebuddy.implementation.bind.annotation.RuntimeType; @@ -31,9 +29,11 @@ import java.util.UUID; import java.util.concurrent.Callable; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class Interceptor { - private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Interceptor.class); + + private Interceptor() { + } /** * A magic method used to wrap public method calls in classes @@ -64,7 +64,7 @@ public static Object intercept( } catch (NotImplementedException e) { // ignore } catch (Exception e) { - logger.atError() + LOGGER.atError() .addArgument(() -> self.getClass().getName()) .addArgument(method::getName) .log("Got an unexpected error in beforeCall listener of {}.{} method", e); @@ -110,7 +110,7 @@ public static Object intercept( } catch (NotImplementedException e) { // ignore } catch (Exception e) { - logger.atError() + LOGGER.atError() .addArgument(() -> self.getClass().getName()) .addArgument(method::getName) .log("Got an unexpected error in afterCall listener of {}.{} method", e); diff --git a/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java b/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java index a7b75e3d7..dc5ada3a5 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseMapOptionData.java @@ -26,7 +26,7 @@ public abstract class BaseMapOptionData> { private Map options; - private static final Gson gson = new Gson(); + private static final Gson GSON = new Gson(); public BaseMapOptionData() { } @@ -37,7 +37,7 @@ public BaseMapOptionData(Map options) { public BaseMapOptionData(String json) { //noinspection unchecked - this((Map) gson.fromJson(json, Map.class)); + this((Map) GSON.fromJson(json, Map.class)); } /** @@ -78,11 +78,11 @@ public Map toMap() { } public JsonObject toJson() { - return gson.toJsonTree(toMap()).getAsJsonObject(); + return GSON.toJsonTree(toMap()).getAsJsonObject(); } @Override public String toString() { - return gson.toJson(toMap()); + return GSON.toJson(toMap()); } } diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index 7ef52b7e4..dff4f5c44 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -96,7 +96,7 @@ public Platform getPlatformName() { } try { - return Platform.fromString((String.valueOf(cap))); + return Platform.fromString(String.valueOf(cap)); } catch (WebDriverException e) { return null; } diff --git a/src/test/java/io/appium/java_client/TestResources.java b/src/test/java/io/appium/java_client/TestResources.java index 9d188fb58..6928cdcaf 100644 --- a/src/test/java/io/appium/java_client/TestResources.java +++ b/src/test/java/io/appium/java_client/TestResources.java @@ -5,6 +5,9 @@ import static io.appium.java_client.TestUtils.resourcePathToLocalPath; public class TestResources { + private TestResources() { + } + public static Path apiDemosApk() { return resourcePathToLocalPath("apps/ApiDemos-debug.apk"); } diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index f2ed2792e..6a968a4e1 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -19,6 +19,9 @@ import java.util.function.Supplier; public class TestUtils { + private TestUtils() { + } + public static String getLocalIp4Address() throws SocketException, UnknownHostException { // https://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java try (final DatagramSocket socket = new DatagramSocket()) { diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index 45f048272..095866e89 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -220,7 +220,7 @@ public void runAppInBackgroundTest() { long time = System.currentTimeMillis(); driver.runAppInBackground(Duration.ofSeconds(4)); long timeAfter = System.currentTimeMillis(); - assert (timeAfter - time > 3000); + assert timeAfter - time > 3000; } @Test @@ -237,9 +237,8 @@ public void testApplicationsManagement() throws InterruptedException { @Test public void pullFileTest() { - byte[] data = - driver.pullFile("/data/system/users/userlist.xml"); - assert (data.length > 0); + byte[] data = driver.pullFile("/data/system/users/userlist.xml"); + assert data.length > 0; } @Test diff --git a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java b/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java index e7a40383c..618da2e32 100644 --- a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java @@ -16,7 +16,7 @@ public void verifyLogcatListenerCanBeAssigned() { final Semaphore messageSemaphore = new Semaphore(1); final Duration timeout = Duration.ofSeconds(15); - driver.addLogcatMessagesListener((msg) -> messageSemaphore.release()); + driver.addLogcatMessagesListener(msg -> messageSemaphore.release()); driver.addLogcatConnectionListener(() -> System.out.println("Connected to the web socket")); driver.addLogcatDisconnectionListener(() -> System.out.println("Disconnected from the web socket")); driver.addLogcatErrorsListener(Throwable::printStackTrace); diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 28c1c95f4..21142e631 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -25,6 +25,7 @@ import static io.appium.java_client.TestResources.apiDemosApk; +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class BaseAndroidTest { public static final String APP_ID = "io.appium.android.apis"; protected static final int PORT = 4723; diff --git a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java index cfc690021..d312587bd 100644 --- a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java +++ b/src/test/java/io/appium/java_client/android/BaseEspressoTest.java @@ -24,6 +24,7 @@ import static io.appium.java_client.TestResources.apiDemosApk; +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class BaseEspressoTest { private static AppiumDriverLocalService service; diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java index 04574448c..7a22ffd93 100644 --- a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -67,7 +67,7 @@ public void canBuildXcuiTestOptions() throws MalformedURLException { assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); assertEquals(new URL("http://localhost:8000"), options.getWdaBaseUrl().orElse(null)); assertNotNull(options.getPermissions() - .map((v) -> v.getAppPermissions("com.apple.MobileSafari")) + .map(v -> v.getAppPermissions("com.apple.MobileSafari")) .orElse(null)); assertEquals(10L, (long) options.getSafariSocketChunkSize().orElse(0)); assertEquals(1L, options.getCommandTimeouts().orElse(null).left() diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java index fe5764e7b..cc571b6fa 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/test/java/io/appium/java_client/ios/BaseIOSTest.java @@ -22,6 +22,7 @@ import java.time.Duration; +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class BaseIOSTest { protected static AppiumDriverLocalService service; diff --git a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java index 7e1fb6528..7d91e596a 100644 --- a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSAlertTest.java @@ -38,16 +38,16 @@ public class IOSAlertTest extends AppIOSTest { private static final Duration ALERT_TIMEOUT = Duration.ofSeconds(5); private static final int CLICK_RETRIES = 2; + private static final String IOS_AUTOMATION_TEXT = "show alert"; private final WebDriverWait waiter = new WebDriverWait(driver, ALERT_TIMEOUT); - private static final String iOSAutomationText = "show alert"; private void ensureAlertPresence() { int retry = 0; // CI might not be performant enough, so we need to retry while (true) { try { - driver.findElement(AppiumBy.accessibilityId(iOSAutomationText)).click(); + driver.findElement(AppiumBy.accessibilityId(IOS_AUTOMATION_TEXT)).click(); } catch (WebDriverException e) { // ignore } diff --git a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java b/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java index 34429e5df..b2c4c96bd 100644 --- a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java @@ -16,7 +16,7 @@ public void verifySyslogListenerCanBeAssigned() { final Semaphore messageSemaphore = new Semaphore(1); final Duration timeout = Duration.ofSeconds(15); - driver.addSyslogMessagesListener((msg) -> messageSemaphore.release()); + driver.addSyslogMessagesListener(msg -> messageSemaphore.release()); driver.addSyslogConnectionListener(() -> System.out.println("Connected to the web socket")); driver.addSyslogDisconnectionListener(() -> System.out.println("Disconnected from the web socket")); driver.addSyslogErrorsListener(Throwable::printStackTrace); From c0088b8f25a0734fc3b8622a3a03d727e2387a0a Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 6 Oct 2023 13:04:32 +0300 Subject: [PATCH 267/501] chore: Bump Gradle from `8.3` to `8.4` (#2029) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index ff247ab7f..f6b39cebd 100644 --- a/build.gradle +++ b/build.gradle @@ -189,7 +189,7 @@ signing { } wrapper { - gradleVersion = '8.3' + gradleVersion = '8.4' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d11cdd907..8838ba97b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1a5..1aa94a426 100755 --- a/gradlew +++ b/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ From 8386bd28f024a22f07a650651780fd3e24db0cae Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 6 Oct 2023 16:41:15 +0200 Subject: [PATCH 268/501] chore: Limit the maximum selenium version (#2031) --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index f6b39cebd..f2269fc6a 100644 --- a/build.gradle +++ b/build.gradle @@ -34,19 +34,19 @@ dependencies { api ('org.seleniumhq.selenium:selenium-api') { version { - strictly "[${seleniumVersion}, 5.0)" + strictly "[${seleniumVersion}, 4.14)" prefer "${seleniumVersion}" } } api ('org.seleniumhq.selenium:selenium-remote-driver') { version { - strictly "[${seleniumVersion}, 5.0)" + strictly "[${seleniumVersion}, 4.14)" prefer "${seleniumVersion}" } } api ('org.seleniumhq.selenium:selenium-support') { version { - strictly "[${seleniumVersion}, 5.0)" + strictly "[${seleniumVersion}, 4.14)" prefer "${seleniumVersion}" } } From f838c7116d12d0368c21680b6d2399ebac76e138 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 6 Oct 2023 17:25:27 +0200 Subject: [PATCH 269/501] chore: Remove the obsolete commons-validator dependency (#2032) --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index f2269fc6a..a2286e1e7 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,6 @@ dependencies { } } implementation 'com.google.code.gson:gson:2.10.1' - implementation 'commons-validator:commons-validator:1.7' implementation 'org.apache.commons:commons-lang3:3.13.0' implementation 'commons-io:commons-io:2.14.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" From c6f21546d9d10945d58105317466c04d6df4c4d3 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Sun, 8 Oct 2023 23:34:50 +0530 Subject: [PATCH 270/501] Release 8.6.0 and update release notes (#2033) --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf1920ce1..607a44c86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,47 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_8.6.0_ + +- **[BUG FIX]** + - Exclude abstract methods from proxy matching. [#1937](https://github.com/appium/java-client/pull/1937) + - AppiumClientConfig#readTimeout to call super.readTimeout. [#1959](https://github.com/appium/java-client/pull/1959) + - Use weak references to elements inside of interceptor objects. [#1981](https://github.com/appium/java-client/pull/1981) + - Correct spelling and semantic mistakes in method naming. [#1970](https://github.com/appium/java-client/pull/1970) + - Change scope of selenium-support dependency to compile. [#2019](https://github.com/appium/java-client/pull/2019) + - Fix Code style issues to match Java standards. [#2017](https://github.com/appium/java-client/pull/2017) + - class of proxy method in AppiumClientConfig. [#2026](https://github.com/appium/java-client/pull/2026) +- **[ENHANCEMENTS]** + - Mark Windows page object annotations as deprecated. [#1938](https://github.com/appium/java-client/pull/1938) + - Deprecate obsolete capabilities constants. [#1961](https://github.com/appium/java-client/pull/1961) + - patch AutomationName with Chromium. [#1993](https://github.com/appium/java-client/pull/1993) + - Implementation of Chromium driver plus capabilities. [#2003](https://github.com/appium/java-client/pull/2003) +- **[REFACTOR]** + - Increase server start timeout for iOS tests. [#1983](https://github.com/appium/java-client/pull/1983) + - Fix Android test: --base-path arg must start with /. [#1952](https://github.com/appium/java-client/pull/1952) + - Added fixes for No service provider found for `io.appium.java_client.events.api.Listener`. [#1975](https://github.com/appium/java-client/pull/1975) + - Run tests against latest Selenium release. [#1978](https://github.com/appium/java-client/pull/1978) + - Use server releases from the main branch for testing. [#1994](https://github.com/appium/java-client/pull/1994) + - Remove obsolete API calls from tests. [#2006](https://github.com/appium/java-client/pull/2006) + - Automate more static code checks. [#2028](https://github.com/appium/java-client/pull/2028) + - Limit the maximum selenium version to 4.14. [#2031](https://github.com/appium/java-client/pull/2031) + - Remove the obsolete commons-validator dependency. [#2032](https://github.com/appium/java-client/pull/2032) +- **[DOCUMENTATION]** + - Add the latest versions of clients to the compatibility matrix. [#1935](https://github.com/appium/java-client/pull/1935) + - Added correct url path for the latest appium documentation. [#1974](https://github.com/appium/java-client/pull/1974) + - Add Selenium 4.11.0, 4.12.0, 4.12.1 & 4.13.0 to compatibility matrix. [#1986](https://github.com/appium/java-client/pull/1986) & [#1999](https://github.com/appium/java-client/pull/1999) & [#2002](https://github.com/appium/java-client/pull/2025) & [#1986](https://github.com/appium/java-client/pull/2025) + - Add known compatibility issue for Selenium 4.12.1. [#2008](https://github.com/appium/java-client/pull/2008) +- **[DEPENDENCY UPDATES]** + - `org.owasp.dependencycheck` was updated to 8.4.0. + - `org.junit.jupiter:junit-jupiter` was updated to 5.10.0. + - `commons-io:commons-io` was updated to 2.14.0. + - `checkstyle` was updated to 10.12.1. + - `org.apache.commons:commons-lang3` was updated to 3.13.0. + - `gradle` was updated to 8.4.0. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.5.3. + - `org.seleniumhq.selenium:selenium-bom` was updated to 4.13.0. + - `org.projectlombok:lombok` was updated to 1.18.30. + *8.5.1* - **[BUG FIX]** - Use correct exception type for fallback at file/folder pulling. [#1912](https://github.com/appium/java-client/pull/1912) diff --git a/gradle.properties b/gradle.properties index e7f91060b..8542862b9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.9.1 # Please increment the value in a release -appiumClient.version=8.5.1 +appiumClient.version=8.6.0 From 39c2526775d01ef7224557c9a1587cc97274c58a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 12 Oct 2023 20:34:02 +0200 Subject: [PATCH 271/501] refactor!: Update selenium dependencies to v4.14 (#2036) BREAKING CHANGE: The library is now only compatible to Java11 and above BREAKING CHANGE: The previously deprecated MobileBy class has been removed. Use AppiumBy instead BREAKING CHANGE: The previously deprecated launchApp, resetApp and closeApp methods have been removed. Use extension methods instead BREAKING CHANGE: The previously deprecated WindowsBy class and related location strategies have been removed BREAKING CHANGE: The previously deprecated ByAll class has been removed in favour of the Selenium one BREAKING CHANGE: The previously deprecated AndroidMobileCapabilityType interface has been removed. Use driver options instead BREAKING CHANGE: The previously deprecated IOSMobileCapabilityType interface has been removed. Use driver options instead BREAKING CHANGE: The previously deprecated MobileCapabilityType interface has been removed. Use driver options instead BREAKING CHANGE: The previously deprecated MobileOptions class has been removed. Use driver options instead BREAKING CHANGE: The previously deprecated YouiEngineCapabilityType interface has been removed. Use driver options instead BREAKING CHANGE: Removed several misspelled methods. Use properly spelled alternatives instead BREAKING CHANGE: Removed startActivity method from AndroidDriver. Use 'mobile: startActivity' extension method instead BREAKING CHANGE: Removed the previously deprecated APPIUM constant from the AutomationName interface BREAKING CHANGE: Removed the previously deprecated PRE_LAUNCH value from the GeneralServerFlag enum BREAKING CHANGE: Moved AppiumUserAgentFilter class to io.appium.java_client.internal.filters package Removed dependencies to Apache Commons libraries --- .github/workflows/gradle.yml | 11 +- .github/workflows/publish.yml | 2 +- build.gradle | 27 +- gradle.properties | 2 +- .../java/io/appium/java_client/AppiumBy.java | 6 +- .../java_client/AppiumClientConfig.java | 28 +- .../io/appium/java_client/AppiumDriver.java | 38 +- .../io/appium/java_client/ComparesImages.java | 16 +- .../appium/java_client/HasBrowserCheck.java | 8 +- .../java_client/HidesKeyboardWithKeyName.java | 15 - .../java/io/appium/java_client/MobileBy.java | 348 ------------ .../io/appium/java_client/MobileCommand.java | 5 +- .../io/appium/java_client/PushesFiles.java | 4 +- .../SupportsLegacyAppManagement.java | 59 -- .../appium/java_client/android/Activity.java | 6 +- .../java_client/android/AndroidDriver.java | 18 +- .../android/AndroidMobileCommandHelper.java | 66 --- .../java_client/android/StartsActivity.java | 29 - .../SupportsShowChromedriverLogOption.java | 21 - .../filters/AppiumIdempotencyFilter.java | 38 ++ .../filters}/AppiumUserAgentFilter.java | 3 +- .../io/appium/java_client/ios/IOSDriver.java | 4 +- .../SupportsCustomSslCertOption.java | 10 - .../SupportsSimulatorTracePointerOption.java | 10 - .../pagefactory/AppiumFieldDecorator.java | 6 +- .../pagefactory/DefaultElementByBuilder.java | 5 - .../pagefactory/HowToUseLocators.java | 10 - .../java_client/pagefactory/WindowsBy.java | 74 --- .../pagefactory/WindowsFindAll.java | 51 -- .../pagefactory/WindowsFindBy.java | 88 --- .../pagefactory/WindowsFindByAllSet.java | 26 - .../pagefactory/WindowsFindByChainSet.java | 26 - .../pagefactory/WindowsFindBySet.java | 42 -- .../pagefactory/WindowsFindBys.java | 49 -- .../pagefactory/bys/builder/ByAll.java | 65 --- .../pagefactory/bys/builder/Strategies.java | 21 - .../pagefactory/utils/ProxyFactory.java | 16 +- .../utils/WebDriverUnpackUtility.java | 5 +- .../io/appium/java_client/proxy/Helpers.java | 1 - .../appium/java_client/proxy/Interceptor.java | 20 +- .../proxy/ProxyListenersContainer.java | 54 +- .../remote/AndroidMobileCapabilityType.java | 495 ----------------- .../remote/AppiumCommandExecutor.java | 14 +- .../java_client/remote/AutomationName.java | 2 - .../remote/IOSMobileCapabilityType.java | 400 -------------- .../remote/MobileCapabilityType.java | 142 ----- .../java_client/remote/MobileOptions.java | 512 ------------------ .../remote/YouiEngineCapabilityType.java | 16 - .../local/AppiumDriverLocalService.java | 6 +- .../service/local/AppiumServiceBuilder.java | 30 +- .../local/flags/GeneralServerFlag.java | 9 - .../java_client/ws/StringWebSocketClient.java | 33 +- .../android/ExecuteCDPCommandTest.java | 11 +- .../internal/AppiumUserAgentFilterTest.java | 2 +- .../java_client/internal/ConfigTest.java | 2 +- .../java_client/remote/MobileOptionsTest.java | 110 ---- .../local/StartingAppLocallyAndroidTest.java | 21 +- .../local/StartingAppLocallyIosTest.java | 7 +- 58 files changed, 239 insertions(+), 2906 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/MobileBy.java delete mode 100644 src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java create mode 100644 src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java rename src/main/java/io/appium/java_client/{ => internal/filters}/AppiumUserAgentFilter.java (98%) delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsBy.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java delete mode 100644 src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java delete mode 100644 src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java delete mode 100644 src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java delete mode 100644 src/main/java/io/appium/java_client/remote/MobileCapabilityType.java delete mode 100644 src/main/java/io/appium/java_client/remote/MobileOptions.java delete mode 100644 src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java delete mode 100644 src/test/java/io/appium/java_client/remote/MobileOptionsTest.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d427bec19..a7094028a 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -14,6 +14,10 @@ on: - 'docs/**' - '*.md' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + env: ANDROID_SDK_VERSION: 28 ANDROID_EMU_NAME: test @@ -27,14 +31,13 @@ jobs: strategy: matrix: include: - # TODO: add new LTS Java ( 21 ) once it's released - - java: 8 - platform: macos-latest - e2e-tests: android - java: 11 # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available platform: macos-12 e2e-tests: ios + - java: 15 + platform: macos-latest + e2e-tests: android - java: 17 platform: ubuntu-latest fail-fast: false diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7e95af207..71837dd3c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,7 +10,7 @@ jobs: - name: Set up Java uses: actions/setup-java@v3 with: - java-version: '8' + java-version: '11' distribution: 'zulu' cache: 'gradle' - name: Publish package diff --git a/build.gradle b/build.gradle index a2286e1e7..05e17653f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,8 +16,8 @@ repositories { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 withJavadocJar() withSourcesJar() } @@ -34,25 +34,23 @@ dependencies { api ('org.seleniumhq.selenium:selenium-api') { version { - strictly "[${seleniumVersion}, 4.14)" + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } api ('org.seleniumhq.selenium:selenium-remote-driver') { version { - strictly "[${seleniumVersion}, 4.14)" + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } api ('org.seleniumhq.selenium:selenium-support') { version { - strictly "[${seleniumVersion}, 4.14)" + strictly "[${seleniumVersion}, 5.0)" prefer "${seleniumVersion}" } } implementation 'com.google.code.gson:gson:2.10.1' - implementation 'org.apache.commons:commons-lang3:3.13.0' - implementation 'commons-io:commons-io:2.14.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' @@ -93,16 +91,13 @@ tasks.withType(JacocoReport) { } jacocoTestReport.dependsOn test -// Checkstyle requires Java 11 starting from 10.0 -if (JavaVersion.current().isJava11Compatible()) { - apply plugin: 'checkstyle' +apply plugin: 'checkstyle' - checkstyle { - toolVersion = '10.12.1' - configFile = configDirectory.file('appium-style.xml').get().getAsFile() - showViolations = true - ignoreFailures = false - } +checkstyle { + toolVersion = '10.12.1' + configFile = configDirectory.file('appium-style.xml').get().getAsFile() + showViolations = true + ignoreFailures = false } javadoc { diff --git a/gradle.properties b/gradle.properties index 8542862b9..9b917685b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.9.1 +selenium.version=4.14.1 # Please increment the value in a release appiumClient.version=8.6.0 diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 7e067287d..21e11d08e 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -16,8 +16,8 @@ package io.appium.java_client; +import com.google.common.base.Preconditions; import lombok.Getter; -import org.apache.commons.lang3.Validate; import org.openqa.selenium.By; import org.openqa.selenium.By.Remotable; import org.openqa.selenium.SearchContext; @@ -27,13 +27,15 @@ import java.util.List; import java.util.Objects; +import static com.google.common.base.Strings.isNullOrEmpty; + public abstract class AppiumBy extends By implements Remotable { @Getter private final Parameters remoteParameters; private final String locatorName; protected AppiumBy(String selector, String locatorString, String locatorName) { - Validate.notBlank(locatorString, "Must supply a not empty locator value."); + Preconditions.checkArgument(!isNullOrEmpty(locatorString), "Must supply a not empty locator value."); this.remoteParameters = new Parameters(selector, locatorString); this.locatorName = locatorName; } diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java index c8e123fc9..bb77b4ec9 100644 --- a/src/main/java/io/appium/java_client/AppiumClientConfig.java +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -16,11 +16,15 @@ package io.appium.java_client; +import io.appium.java_client.internal.filters.AppiumIdempotencyFilter; +import io.appium.java_client.internal.filters.AppiumUserAgentFilter; import org.openqa.selenium.Credentials; import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.Filter; +import javax.annotation.Nullable; +import javax.net.ssl.SSLContext; import java.net.Proxy; import java.net.URI; import java.net.URISyntaxException; @@ -33,7 +37,10 @@ public class AppiumClientConfig extends ClientConfig { private final boolean directConnect; - private static final Filter DEFAULT_FILTER = new AppiumUserAgentFilter(); + private static final Filter DEFAULT_FILTERS = new AppiumUserAgentFilter() + .andThen(new AppiumIdempotencyFilter()); + + private static final String DEFAULT_HTTP_VERSION = "HTTP_1_1"; private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofMinutes(10); @@ -49,6 +56,7 @@ public class AppiumClientConfig extends ClientConfig { * {@link org.openqa.selenium.remote.http.HttpResponse}. * @param proxy The client proxy preference. * @param credentials Credentials used for authenticating http requests + * @param sslContext SSL context (if present) * @param directConnect If directConnect is enabled. */ protected AppiumClientConfig( @@ -56,10 +64,12 @@ protected AppiumClientConfig( Duration connectionTimeout, Duration readTimeout, Filter filters, - Proxy proxy, - Credentials credentials, + @Nullable Proxy proxy, + @Nullable Credentials credentials, + @Nullable SSLContext sslContext, + @Nullable String version, Boolean directConnect) { - super(baseUri, connectionTimeout, readTimeout, filters, proxy, credentials); + super(baseUri, connectionTimeout, readTimeout, filters, proxy, credentials, sslContext, version); this.directConnect = Require.nonNull("Direct Connect", directConnect); } @@ -73,9 +83,11 @@ public static AppiumClientConfig defaultConfig() { null, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_READ_TIMEOUT, - DEFAULT_FILTER, + DEFAULT_FILTERS, + null, null, null, + DEFAULT_HTTP_VERSION, false); } @@ -92,6 +104,8 @@ public static AppiumClientConfig fromClientConfig(ClientConfig clientConfig) { clientConfig.filter(), clientConfig.proxy(), clientConfig.credentials(), + clientConfig.sslContext(), + clientConfig.version(), false); } @@ -103,6 +117,8 @@ private AppiumClientConfig buildAppiumClientConfig(ClientConfig clientConfig, Bo clientConfig.filter(), clientConfig.proxy(), clientConfig.credentials(), + clientConfig.sslContext(), + clientConfig.version(), directConnect); } @@ -175,6 +191,8 @@ public AppiumClientConfig directConnect(boolean directConnect) { this.filter(), this.proxy(), this.credentials(), + this.sslContext(), + this.version(), directConnect ); } diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 749a0204d..28d0bd529 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -23,10 +23,10 @@ import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumNewSessionCommandPayload; import io.appium.java_client.remote.AppiumW3CHttpCommandCodec; -import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; +import lombok.Getter; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; @@ -53,10 +53,10 @@ import java.util.Map; import java.util.Set; +import static com.google.common.base.Strings.isNullOrEmpty; import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; -import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME; -import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME; -import static org.apache.commons.lang3.StringUtils.isBlank; +import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; +import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; /** * Default Appium driver implementation. @@ -72,6 +72,7 @@ public class AppiumDriver extends RemoteWebDriver implements private static final ErrorHandler ERROR_HANDLER = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters + @Getter private final URL remoteAddress; protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; @@ -154,7 +155,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa RemoteWebDriver.class, this, "capabilities", new ImmutableCapabilities( ImmutableMap.of( PLATFORM_NAME, platformName, - APPIUM_PREFIX + AUTOMATION_NAME, automationName + APPIUM_PREFIX + AUTOMATION_NAME_OPTION, automationName ) ) ); @@ -177,8 +178,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa * Changes platform name if it is not set and returns merged capabilities. * * @param originalCapabilities the given {@link Capabilities}. - * @param defaultName a {@link MobileCapabilityType#PLATFORM_NAME} value which has - * to be set up + * @param defaultName a platformName value which has to be set up * @return {@link Capabilities} with changed platform name value or the original capabilities */ protected static Capabilities ensurePlatformName( @@ -192,17 +192,16 @@ protected static Capabilities ensurePlatformName( * Changes automation name if it is not set and returns merged capabilities. * * @param originalCapabilities the given {@link Capabilities}. - * @param defaultName a {@link MobileCapabilityType#AUTOMATION_NAME} value which has - * to be set up + * @param defaultName a platformName value which has to be set up * @return {@link Capabilities} with changed mobile automation name value or the original capabilities */ protected static Capabilities ensureAutomationName( Capabilities originalCapabilities, String defaultName) { String currentAutomationName = CapabilityHelpers.getCapability( - originalCapabilities, AUTOMATION_NAME, String.class); - if (isBlank(currentAutomationName)) { + originalCapabilities, AUTOMATION_NAME_OPTION, String.class); + if (isNullOrEmpty(currentAutomationName)) { String capabilityName = originalCapabilities.getCapabilityNames() - .contains(AUTOMATION_NAME) ? AUTOMATION_NAME : APPIUM_PREFIX + AUTOMATION_NAME; + .contains(AUTOMATION_NAME_OPTION) ? AUTOMATION_NAME_OPTION : APPIUM_PREFIX + AUTOMATION_NAME_OPTION; return originalCapabilities.merge(new ImmutableCapabilities(capabilityName, defaultName)); } return originalCapabilities; @@ -213,8 +212,7 @@ protected static Capabilities ensureAutomationName( * and returns merged capabilities. * * @param originalCapabilities the given {@link Capabilities}. - * @param defaultPlatformName a {@link MobileCapabilityType#PLATFORM_NAME} value which has - * to be set up + * @param defaultPlatformName a platformName value which has to be set up * @param defaultAutomationName The default automation name to set up for this class * @return {@link Capabilities} with changed platform/automation name value or the original capabilities */ @@ -265,10 +263,6 @@ public void addCommand(HttpMethod httpMethod, String url, String methodName) { ((AppiumCommandExecutor) getCommandExecutor()).refreshAdditionalCommands(); } - public URL getRemoteAddress() { - return remoteAddress; - } - @Override protected void startSession(Capabilities capabilities) { Response response = execute(new AppiumNewSessionCommandPayload(capabilities)); @@ -293,7 +287,7 @@ protected void startSession(Capabilities capabilities) { // TODO: remove this workaround for Selenium API enforcing some legacy capability values in major version rawCapabilities.remove("platform"); if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME) - && isBlank((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { + && isNullOrEmpty((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { rawCapabilities.remove(CapabilityType.BROWSER_NAME); } MutableCapabilities returnedCapabilities = new BaseOptions<>(rawCapabilities); @@ -346,4 +340,10 @@ public AppiumDriver markExtensionAbsence(String extName) { absentExtensionNames.add(extName); return this; } + + protected HttpClient getHttpClient() { + return ReflectionHelpers.getPrivateFieldValue( + HttpCommandExecutor.class, getCommandExecutor(), "client", HttpClient.class + ); + } } diff --git a/src/main/java/io/appium/java_client/ComparesImages.java b/src/main/java/io/appium/java_client/ComparesImages.java index 4aeefec6a..1b29c35cf 100644 --- a/src/main/java/io/appium/java_client/ComparesImages.java +++ b/src/main/java/io/appium/java_client/ComparesImages.java @@ -23,11 +23,11 @@ import io.appium.java_client.imagecomparison.OccurrenceMatchingResult; import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; -import org.apache.commons.io.FileUtils; import javax.annotation.Nullable; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.Base64; import java.util.Map; @@ -93,8 +93,8 @@ default FeaturesMatchingResult matchImagesFeatures(File image1, File image2) thr */ default FeaturesMatchingResult matchImagesFeatures(File image1, File image2, @Nullable FeaturesMatchingOptions options) throws IOException { - return matchImagesFeatures(Base64.getEncoder().encode(FileUtils.readFileToByteArray(image1)), - Base64.getEncoder().encode(FileUtils.readFileToByteArray(image2)), options); + return matchImagesFeatures(Base64.getEncoder().encode(Files.readAllBytes(image1.toPath())), + Base64.getEncoder().encode(Files.readAllBytes(image2.toPath())), options); } /** @@ -160,8 +160,8 @@ default OccurrenceMatchingResult findImageOccurrence(File fullImage, File partia default OccurrenceMatchingResult findImageOccurrence(File fullImage, File partialImage, @Nullable OccurrenceMatchingOptions options) throws IOException { - return findImageOccurrence(Base64.getEncoder().encode(FileUtils.readFileToByteArray(fullImage)), - Base64.getEncoder().encode(FileUtils.readFileToByteArray(partialImage)), options); + return findImageOccurrence(Base64.getEncoder().encode(Files.readAllBytes(fullImage.toPath())), + Base64.getEncoder().encode(Files.readAllBytes(partialImage.toPath())), options); } /** @@ -227,7 +227,7 @@ default SimilarityMatchingResult getImagesSimilarity(File image1, File image2) t default SimilarityMatchingResult getImagesSimilarity(File image1, File image2, @Nullable SimilarityMatchingOptions options) throws IOException { - return getImagesSimilarity(Base64.getEncoder().encode(FileUtils.readFileToByteArray(image1)), - Base64.getEncoder().encode(FileUtils.readFileToByteArray(image2)), options); + return getImagesSimilarity(Base64.getEncoder().encode(Files.readAllBytes(image1.toPath())), + Base64.getEncoder().encode(Files.readAllBytes(image2.toPath())), options); } -} \ No newline at end of file +} diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java index 6b00a8d5d..c5cd62cdb 100644 --- a/src/main/java/io/appium/java_client/HasBrowserCheck.java +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -7,8 +7,7 @@ import org.openqa.selenium.remote.CapabilityType; import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; -import static org.apache.commons.lang3.StringUtils.isBlank; +import static com.google.common.base.Strings.isNullOrEmpty; public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { /** @@ -19,7 +18,7 @@ public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { default boolean isBrowser() { String browserName = CapabilityHelpers.getCapability(getCapabilities(), CapabilityType.BROWSER_NAME, String.class); - if (!isBlank(browserName)) { + if (!isNullOrEmpty(browserName)) { try { return checkNotNull( CommandExecutionHelper.executeScript(this, "return !!window.navigator;") @@ -32,7 +31,8 @@ default boolean isBrowser() { return false; } try { - return !containsIgnoreCase(((ContextAware) this).getContext(), "NATIVE_APP"); + var context = ((ContextAware) this).getContext(); + return context != null && !context.toUpperCase().contains("NATIVE_APP"); } catch (WebDriverException e) { return false; } diff --git a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java index 35d7a7b0c..4223ab814 100644 --- a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java +++ b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java @@ -45,19 +45,4 @@ default void hideKeyboard(String keyName) { CommandExecutionHelper.execute(markExtensionAbsence(extName), hideKeyboardCommand(keyName)); } } - - /** - * Hides the keyboard if it is showing. Hiding the keyboard often - * depends on the way an app is implemented, no single strategy always - * works. - * - * @param strategy HideKeyboardStrategy. - * @param keyName a String, representing the text displayed on the button of the - * keyboard you want to press. For example: "Done". - * @deprecated This API is deprecated and will be removed in the future. - */ - @Deprecated - default void hideKeyboard(String strategy, String keyName) { - CommandExecutionHelper.execute(this, hideKeyboardCommand(strategy, keyName)); - } } diff --git a/src/main/java/io/appium/java_client/MobileBy.java b/src/main/java/io/appium/java_client/MobileBy.java deleted file mode 100644 index 902baa249..000000000 --- a/src/main/java/io/appium/java_client/MobileBy.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * 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.By; - -import java.io.Serializable; - -/** - * Appium locating strategies. - * - * @deprecated Use {@link AppiumBy} instead. - */ -@SuppressWarnings("serial") -@Deprecated -public abstract class MobileBy extends AppiumBy { - - protected MobileBy(String selector, String locatorString, String locatorName) { - super(selector, locatorString, locatorName); - } - - /** - * Refer to https://developer.android.com/training/testing/ui-automator - * - * @param uiautomatorText is Android UIAutomator string - * @return an instance of {@link ByAndroidUIAutomator} - * @deprecated Use {@link AppiumBy#androidUIAutomator(String)} instead. - */ - @Deprecated - public static By AndroidUIAutomator(final String uiautomatorText) { - return new ByAndroidUIAutomator(uiautomatorText); - } - - /** - * About Android accessibility - * https://developer.android.com/intl/ru/training/accessibility/accessible-app.html - * About iOS accessibility - * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ - * UIAccessibilityIdentification_Protocol/index.html - * - * @param accessibilityId id is a convenient UI automation accessibility Id. - * @return an instance of {@link ByAndroidUIAutomator} - * @deprecated Use {@link AppiumBy#accessibilityId(String)} instead. - */ - @Deprecated - public static By AccessibilityId(final String accessibilityId) { - return new ByAccessibilityId(accessibilityId); - } - - /** - * This locator strategy is available in XCUITest Driver mode. - * - * @param iOSClassChainString is a valid class chain locator string. - * See - * the documentation for more details - * @return an instance of {@link ByIosClassChain} - * @deprecated Use {@link AppiumBy#iOSClassChain(String)} instead. - */ - @Deprecated - public static By iOSClassChain(final String iOSClassChainString) { - return new ByIosClassChain(iOSClassChainString); - } - - /** - * This locator strategy is only available in Espresso Driver mode. - * - * @param dataMatcherString is a valid json string detailing hamcrest matcher for Espresso onData(). - * See - * the documentation for more details - * @return an instance of {@link ByAndroidDataMatcher} - * @deprecated Use {@link AppiumBy#androidDataMatcher(String)} instead. - */ - @Deprecated - public static By androidDataMatcher(final String dataMatcherString) { - return new ByAndroidDataMatcher(dataMatcherString); - } - - /** - * This locator strategy is only available in Espresso Driver mode. - * - * @param viewMatcherString is a valid json string detailing hamcrest matcher for Espresso onView(). - * See - * the documentation for more details - * @return an instance of {@link ByAndroidViewMatcher} - * @deprecated Use {@link AppiumBy#androidViewMatcher(String)} instead. - */ - @Deprecated - public static By androidViewMatcher(final String viewMatcherString) { - return new ByAndroidViewMatcher(viewMatcherString); - } - - /** - * This locator strategy is available in XCUITest Driver mode. - * - * @param iOSNsPredicateString is an iOS NsPredicate String - * @return an instance of {@link ByIosNsPredicate} - * @deprecated Use {@link AppiumBy#iOSNsPredicateString(String)} instead. - */ - @Deprecated - public static By iOSNsPredicateString(final String iOSNsPredicateString) { - return new ByIosNsPredicate(iOSNsPredicateString); - } - - /** - * The Windows UIAutomation selector. - * - * @param windowsAutomation The element name in the Windows UIAutomation selector - * @return an instance of {@link MobileBy.ByWindowsAutomation} - * @deprecated Not supported on the server side. - */ - @Deprecated - public static By windowsAutomation(final String windowsAutomation) { - return new ByWindowsAutomation(windowsAutomation); - } - - /** - * This locator strategy is available in Espresso Driver mode. - * - * @param tag is an view tag string - * @return an instance of {@link ByAndroidViewTag} - * @since Appium 1.8.2 beta - * @deprecated Use {@link AppiumBy#androidViewTag(String)} instead. - */ - @Deprecated - public static By AndroidViewTag(final String tag) { - return new ByAndroidViewTag(tag); - } - - /** - * This locator strategy is available only if OpenCV libraries and - * NodeJS bindings are installed on the server machine. - * - * @param b64Template base64-encoded template image string. Supported image formats are the same - * as for OpenCV library. - * @return an instance of {@link ByImage} - * @see - * The documentation on Image Comparison Features - * @see - * The settings available for lookup fine-tuning - * @since Appium 1.8.2 - * @deprecated Use {@link AppiumBy#image(String)} instead. - */ - @Deprecated - public static By image(final String b64Template) { - return new ByImage(b64Template); - } - - /** - * This type of locator requires the use of the 'customFindModules' capability and a - * separately-installed element finding plugin. - * - * @param selector selector to pass to the custom element finding plugin - * @return an instance of {@link ByCustom} - * @since Appium 1.9.2 - * @deprecated Use {@link AppiumBy#custom(String)} instead. - */ - @Deprecated - public static By custom(final String selector) { - return new ByCustom(selector); - } - - /** - * Refer to https://developer.android.com/training/testing/ui-automator - * - * @deprecated Use {@link AppiumBy.ByAndroidUIAutomator} instead. - */ - @Deprecated - public static class ByAndroidUIAutomator extends AppiumBy.ByAndroidUIAutomator { - - public ByAndroidUIAutomator(String uiautomatorText) { - super(uiautomatorText); - } - - @Override public String toString() { - return "By.AndroidUIAutomator: " + getRemoteParameters().value(); - } - } - - /** - * About Android accessibility - * https://developer.android.com/intl/ru/training/accessibility/accessible-app.html - * About iOS accessibility - * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ - * UIAccessibilityIdentification_Protocol/index.html - * @deprecated Use {@link AppiumBy.ByAccessibilityId} instead. - */ - @Deprecated - public static class ByAccessibilityId extends AppiumBy.ByAccessibilityId { - - public ByAccessibilityId(String accessibilityId) { - super(accessibilityId); - } - - @Override public String toString() { - return "By.AccessibilityId: " + getRemoteParameters().value(); - } - } - - /** - * This locator strategy is available in XCUITest Driver mode. - * See - * the documentation for more details - * @deprecated Use {@link AppiumBy.ByIosClassChain} instead. - */ - @Deprecated - public static class ByIosClassChain extends AppiumBy.ByIosClassChain { - - protected ByIosClassChain(String locatorString) { - super(locatorString); - } - - @Override public String toString() { - return "By.IosClassChain: " + getRemoteParameters().value(); - } - } - - /** - * This locator strategy is only available in Espresso Driver mode. - * See - * the documentation for more details - * @deprecated Use {@link AppiumBy.ByAndroidDataMatcher} instead. - */ - @Deprecated - public static class ByAndroidDataMatcher extends AppiumBy.ByAndroidDataMatcher { - - protected ByAndroidDataMatcher(String locatorString) { - super(locatorString); - } - - @Override public String toString() { - return "By.AndroidDataMatcher: " + getRemoteParameters().value(); - } - } - - /** - * This locator strategy is only available in Espresso Driver mode. - * See - * the documentation for more details - * @deprecated Use {@link AppiumBy.ByAndroidViewMatcher} instead. - */ - @Deprecated - public static class ByAndroidViewMatcher extends AppiumBy.ByAndroidViewMatcher { - - protected ByAndroidViewMatcher(String locatorString) { - super(locatorString); - } - - @Override public String toString() { - return "By.AndroidViewMatcher: " + getRemoteParameters().value(); - } - } - - /** - * This locator strategy is available in XCUITest Driver mode. - * @deprecated Use {@link AppiumBy.ByIosNsPredicate} instead. - */ - @Deprecated - public static class ByIosNsPredicate extends AppiumBy.ByIosNsPredicate { - - protected ByIosNsPredicate(String locatorString) { - super(locatorString); - } - - @Override public String toString() { - return "By.IosNsPredicate: " + getRemoteParameters().value(); - } - } - - /** - * The Windows UIAutomation selector. - * @deprecated Not supported on the server side. - */ - @Deprecated - public static class ByWindowsAutomation extends MobileBy implements Serializable { - - protected ByWindowsAutomation(String locatorString) { - super("-windows uiautomation", locatorString, "windowsAutomation"); - } - - @Override public String toString() { - return "By.windowsAutomation: " + getRemoteParameters().value(); - } - } - - /** - * This locator strategy is available only if OpenCV libraries and - * NodeJS bindings are installed on the server machine. - * @deprecated Use {@link AppiumBy.ByImage} instead. - */ - @Deprecated - public static class ByImage extends AppiumBy.ByImage { - - protected ByImage(String b64Template) { - super(b64Template); - } - - @Override public String toString() { - return "By.Image: " + getRemoteParameters().value(); - } - } - - /** - * This type of locator requires the use of the 'customFindModules' capability and a - * separately-installed element finding plugin. - * @deprecated Use {@link AppiumBy.ByCustom} instead. - */ - @Deprecated - public static class ByCustom extends AppiumBy.ByCustom { - - protected ByCustom(String selector) { - super(selector); - } - - @Override public String toString() { - return "By.Custom: " + getRemoteParameters().value(); - } - } - - /** - * This locator strategy is available in Espresso Driver mode. - * @deprecated Use {@link AppiumBy.ByAndroidViewTag} instead. - */ - @Deprecated - public static class ByAndroidViewTag extends AppiumBy.ByAndroidViewTag { - - public ByAndroidViewTag(String tag) { - super(tag); - } - - @Override public String toString() { - return "By.AndroidViewTag: " + getRemoteParameters().value(); - } - } -} diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index d61a3ef01..878c13c4d 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -21,7 +21,6 @@ import io.appium.java_client.imagecomparison.ComparisonMode; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import io.appium.java_client.screenrecording.BaseStopScreenRecordingOptions; -import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.http.HttpMethod; @@ -32,6 +31,8 @@ import java.util.HashMap; import java.util.Map; +import static com.google.common.base.Strings.isNullOrEmpty; + /** * The repository of mobile commands defined in the Mobile JSON * wire protocol. @@ -435,7 +436,7 @@ public static ImmutableMap prepareArguments(String[] params, Object[] values) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (int i = 0; i < params.length; i++) { - if (!StringUtils.isBlank(params[i]) && values[i] != null) { + if (!isNullOrEmpty(params[i]) && values[i] != null) { builder.put(params[i], values[i]); } } diff --git a/src/main/java/io/appium/java_client/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java index 1bfd7f8eb..b91aada90 100644 --- a/src/main/java/io/appium/java_client/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -17,12 +17,12 @@ package io.appium.java_client; import com.google.common.collect.ImmutableMap; -import org.apache.commons.io.FileUtils; import org.openqa.selenium.UnsupportedCommandException; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Base64; import static io.appium.java_client.MobileCommand.pushFileCommand; @@ -59,7 +59,7 @@ default void pushFile(String remotePath, byte[] base64Data) { * @throws IOException when there are problems with a file on current file system */ default void pushFile(String remotePath, File file) throws IOException { - pushFile(remotePath, Base64.getEncoder().encode(FileUtils.readFileToByteArray(file))); + pushFile(remotePath, Base64.getEncoder().encode(Files.readAllBytes(file.toPath()))); } } diff --git a/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java b/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java deleted file mode 100644 index 7be14ec6d..000000000 --- a/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 static io.appium.java_client.MobileCommand.CLOSE_APP; -import static io.appium.java_client.MobileCommand.LAUNCH_APP; -import static io.appium.java_client.MobileCommand.RESET; - -@Deprecated -public interface SupportsLegacyAppManagement extends ExecutesMethod { - /** - * Launches the app, which was provided in the capabilities at session creation, - * and (re)starts the session. - * - * @deprecated This method is deprecated and will be removed. - * See https://github.com/appium/appium/issues/15807 - */ - @Deprecated - default void launchApp() { - execute(LAUNCH_APP); - } - - /** - * Resets the currently running app together with the session. - * - * @deprecated This method is deprecated and will be removed. - * See https://github.com/appium/appium/issues/15807 - */ - @Deprecated - default void resetApp() { - execute(RESET); - } - - /** - * Close the app which was provided in the capabilities at session creation - * and quits the session. - * - * @deprecated This method is deprecated and will be removed. - * See https://github.com/appium/appium/issues/15807 - */ - @Deprecated - default void closeApp() { - execute(CLOSE_APP); - } -} diff --git a/src/main/java/io/appium/java_client/android/Activity.java b/src/main/java/io/appium/java_client/android/Activity.java index 41a17dc8c..34821f8d4 100644 --- a/src/main/java/io/appium/java_client/android/Activity.java +++ b/src/main/java/io/appium/java_client/android/Activity.java @@ -4,7 +4,7 @@ import lombok.experimental.Accessors; import static com.google.common.base.Preconditions.checkArgument; -import static org.apache.commons.lang3.StringUtils.isBlank; +import static com.google.common.base.Strings.isNullOrEmpty; /** * This is a simple POJO class to support the {@link StartsActivity}. @@ -29,9 +29,9 @@ public class Activity { * @param appActivity The value for the app activity. */ public Activity(String appPackage, String appActivity) { - checkArgument(!isBlank(appPackage), + checkArgument(!isNullOrEmpty(appPackage), "App package should be defined as not empty or null string"); - checkArgument(!isBlank(appActivity), + checkArgument(!isNullOrEmpty(appActivity), "App activity should be defined as not empty or null string"); this.appPackage = appPackage; this.appActivity = appActivity; 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 27b3bd5cf..584dde1a7 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -29,7 +29,6 @@ import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.PullsFiles; import io.appium.java_client.PushesFiles; -import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.android.connection.HasNetworkConnection; import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; import io.appium.java_client.android.nativekey.PressesKey; @@ -50,8 +49,6 @@ import java.net.URL; -import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; - /** * Android driver implementation. */ @@ -65,7 +62,6 @@ public class AndroidDriver extends AppiumDriver implements HasDeviceTime, PullsFiles, InteractsWithApps, - SupportsLegacyAppManagement, HasAppStrings, HasNetworkConnection, PushesFiles, @@ -250,18 +246,6 @@ public AndroidDriver(URL remoteSessionAddress, String automationName) { super(remoteSessionAddress, ANDROID_PLATFORM, automationName); } - /** - * Get test-coverage data. - * - * @param intent intent to broadcast. - * @param path path to .ec file. - * @deprecated This API will be removed - */ - @Deprecated - public void endTestCoverage(String intent, String path) { - CommandExecutionHelper.execute(this, endTestCoverageCommand(intent, path)); - } - @Override public AndroidBatteryInfo getBatteryInfo() { return new AndroidBatteryInfo(CommandExecutionHelper.executeScript(this, "mobile: batteryInfo")); @@ -275,7 +259,7 @@ public RemoteLocationContext getLocationContext() { @Override public synchronized StringWebSocketClient getLogcatClient() { if (logcatClient == null) { - logcatClient = new StringWebSocketClient(); + logcatClient = new StringWebSocketClient(getHttpClient()); } return logcatClient; } 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 562eb9172..a3b31f716 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -18,14 +18,11 @@ import com.google.common.collect.ImmutableMap; import io.appium.java_client.MobileCommand; -import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.remote.RemoteWebElement; import java.util.AbstractMap; import java.util.Map; -import static com.google.common.base.Preconditions.checkArgument; - /** * This util class helps to prepare parameters of Android-specific JSONWP * commands. @@ -52,22 +49,6 @@ public class AndroidMobileCommandHelper extends MobileCommand { return new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()); } - /** - * This method forms a {@link Map} of parameters for the ending of the test coverage. - * - * @param intent intent to broadcast. - * @param path path to .ec file. - * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. - */ - @Deprecated - public static Map.Entry> endTestCoverageCommand(String intent, - String path) { - String[] parameters = new String[] {"intent", "path"}; - Object[] values = new Object[] {intent, path}; - return new AbstractMap.SimpleEntry<>( - END_TEST_COVERAGE, prepareArguments(parameters, values)); - } - /** * returns the information type of the system state which is supported to read * as like cpu, memory, network traffic, and battery. @@ -192,53 +173,6 @@ public class AndroidMobileCommandHelper extends MobileCommand { SET_NETWORK_CONNECTION, prepareArguments(parameters, values)); } - /** - * This method forms a {@link Map} of parameters for the activity starting. - * - * @param appPackage The package containing the activity. [Required] - * @param appActivity The activity to start. [Required] - * @param appWaitPackage Automation will begin after this package starts. [Optional] - * @param appWaitActivity Automation will begin after this activity starts. [Optional] - * @param intentAction Intent action which will be used to start activity [Optional] - * @param intentCategory Intent category which will be used to start activity [Optional] - * @param intentFlags Flags that will be used to start activity [Optional] - * @param optionalIntentArguments Additional intent arguments that will be used to - * start activity [Optional] - * @param stopApp Stop app on reset or not - * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. - * @throws IllegalArgumentException when any required argument is empty - */ - @Deprecated - public static Map.Entry> startActivityCommand(String appPackage, - String appActivity, String appWaitPackage, String appWaitActivity, - String intentAction, String intentCategory, String intentFlags, - String optionalIntentArguments, boolean stopApp) throws IllegalArgumentException { - - checkArgument(!StringUtils.isBlank(appPackage) && !StringUtils.isBlank(appActivity), - String.format("'%s' and '%s' are required.", "appPackage", "appActivity")); - - String targetWaitPackage = !StringUtils.isBlank(appWaitPackage) ? appWaitPackage : ""; - String targetWaitActivity = !StringUtils.isBlank(appWaitActivity) ? appWaitActivity : ""; - String targetIntentAction = !StringUtils.isBlank(intentAction) ? intentAction : ""; - String targetIntentCategory = !StringUtils.isBlank(intentCategory) ? intentCategory : ""; - String targetIntentFlags = !StringUtils.isBlank(intentFlags) ? intentFlags : ""; - String targetOptionalIntentArguments = !StringUtils.isBlank(optionalIntentArguments) - ? optionalIntentArguments : ""; - - ImmutableMap parameters = ImmutableMap - .builder().put("appPackage", appPackage) - .put("appActivity", appActivity) - .put("appWaitPackage", targetWaitPackage) - .put("appWaitActivity", targetWaitActivity) - .put("dontStopAppOnReset", !stopApp) - .put("intentAction", targetIntentAction) - .put("intentCategory", targetIntentCategory) - .put("intentFlags", targetIntentFlags) - .put("optionalIntentArguments", targetOptionalIntentArguments) - .build(); - return new AbstractMap.SimpleEntry<>(START_ACTIVITY, parameters); - } - /** * This method forms a {@link Map} of parameters for the toggling of location services. * 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 f1d538881..d4cb4258a 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -28,37 +28,8 @@ import static io.appium.java_client.MobileCommand.CURRENT_ACTIVITY; import static io.appium.java_client.MobileCommand.GET_CURRENT_PACKAGE; -import static io.appium.java_client.android.AndroidMobileCommandHelper.startActivityCommand; public interface StartsActivity extends ExecutesMethod, CanRememberExtensionPresence { - /** - * 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. - *

- * Usage: - *

- *
-     *     {@code
-     *     Activity activity = new Activity("app package goes here", "app activity goes here");
-     *     activity.setWaitAppPackage("app wait package goes here");
-     *     activity.setWaitAppActivity("app wait activity goes here");
-     *     driver.startActivity(activity);
-     *     }
-     * 
- * - * @param activity The {@link Activity} object - * @deprecated Use 'mobile: startActivity' extension instead - */ - @Deprecated - default void startActivity(Activity activity) { - CommandExecutionHelper.execute(this, - startActivityCommand(activity.getAppPackage(), activity.getAppActivity(), - activity.getAppWaitPackage(), activity.getAppWaitActivity(), - activity.getIntentAction(), activity.getIntentCategory(), activity.getIntentFlags(), - activity.getOptionalIntentArguments(), activity.isStopApp()) - ); - } - /** * Get the current activity being run on the mobile device. * diff --git a/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java b/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java index bd86a041e..ef2b6f301 100644 --- a/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java +++ b/src/main/java/io/appium/java_client/android/options/context/SupportsShowChromedriverLogOption.java @@ -49,17 +49,6 @@ default T setShowChromedriverLog(boolean value) { return amend(SHOW_CHROMEDRIVER_LOG_OPTION, value); } - /** - * If set to true then all the output from chromedriver binary will be - * forwarded to the Appium server log. false by default. - * - * @deprecated Use {@link SupportsShowChromedriverLogOption#setShowChromedriverLog(boolean)} instead. - */ - @Deprecated - default T setDhowChromedriverLog(boolean value) { - return setShowChromedriverLog(value); - } - /** * Get whether to forward chromedriver output to the Appium server log. * @@ -70,14 +59,4 @@ default Optional doesShowChromedriverLog() { toSafeBoolean(getCapability(SHOW_CHROMEDRIVER_LOG_OPTION)) ); } - - /** - * Get whether to forward chromedriver output to the Appium server log. - * - * @deprecated Use {@link SupportsShowChromedriverLogOption#doesShowChromedriverLog()} (boolean)} instead. - */ - @Deprecated - default Optional doesDhowChromedriverLog() { - return doesShowChromedriverLog(); - } } diff --git a/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java new file mode 100644 index 000000000..9a8f8156b --- /dev/null +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java @@ -0,0 +1,38 @@ +/* + * 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.internal.filters; + +import org.openqa.selenium.remote.http.Filter; +import org.openqa.selenium.remote.http.HttpHandler; +import org.openqa.selenium.remote.http.HttpMethod; + +import java.util.UUID; + +public class AppiumIdempotencyFilter implements Filter { + // https://github.com/appium/appium-base-driver/pull/400 + private static final String IDEMPOTENCY_KEY_HEADER = "X-Idempotency-Key"; + + @Override + public HttpHandler apply(HttpHandler next) { + return req -> { + if (req.getMethod() == HttpMethod.POST && req.getUri().endsWith("/session")) { + req.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); + } + return next.execute(req); + }; + } +} diff --git a/src/main/java/io/appium/java_client/AppiumUserAgentFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java similarity index 98% rename from src/main/java/io/appium/java_client/AppiumUserAgentFilter.java rename to src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java index a36da9d08..50e9449e0 100644 --- a/src/main/java/io/appium/java_client/AppiumUserAgentFilter.java +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appium.java_client; +package io.appium.java_client.internal.filters; import com.google.common.annotations.VisibleForTesting; import com.google.common.net.HttpHeaders; @@ -82,7 +82,6 @@ public static String buildUserAgent(@Nullable String userAgent) { @Override public HttpHandler apply(HttpHandler next) { - return req -> { req.setHeader(HttpHeaders.USER_AGENT, buildUserAgent(req.getHeader(HttpHeaders.USER_AGENT))); return next.execute(req); 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 2b735d649..33c048710 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -29,7 +29,6 @@ import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.PullsFiles; import io.appium.java_client.PushesFiles; -import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.SupportsContextSwitching; @@ -64,7 +63,6 @@ public class IOSDriver extends AppiumDriver implements HasDeviceTime, PullsFiles, InteractsWithApps, - SupportsLegacyAppManagement, HasAppStrings, PerformsTouchActions, HidesKeyboardWithKeyName, @@ -290,7 +288,7 @@ public RemoteLocationContext getLocationContext() { @Override public synchronized StringWebSocketClient getSyslogClient() { if (syslogClient == null) { - syslogClient = new StringWebSocketClient(); + syslogClient = new StringWebSocketClient(getHttpClient()); } return syslogClient; } diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java index e5ceefef2..af501a76e 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsCustomSslCertOption.java @@ -37,16 +37,6 @@ default T setCustomSSLCert(String cert) { return amend(CUSTOM_SSLCERT_OPTION, cert); } - /** - * Get the SSL certificate content. - * - * @deprecated use {@link SupportsCustomSslCertOption#getCustomSSLCert()} instead - */ - @Deprecated - default Optional setCustomSSLCert() { - return getCustomSSLCert(); - } - /** * Get the SSL certificate content. * diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java index 3958de502..d7a1d115e 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorTracePointerOption.java @@ -58,14 +58,4 @@ default T setSimulatorTracePointer(boolean value) { default Optional doesSimulatorTracePointer() { return Optional.ofNullable(toSafeBoolean(getCapability(SIMULATOR_TRACE_POINTER_OPTION))); } - - /** - * Get whether to highlight pointer moves in the Simulator window. - * - * @deprecated use {@link SupportsSimulatorTracePointerOption#doesSimulatorTracePointer()} instead - */ - @Deprecated - default Optional doesSimulatorTracePointerd() { - return doesSimulatorTracePointer(); - } } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index b0c8cd428..63208ef1f 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -20,7 +20,6 @@ import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; -import io.appium.java_client.remote.MobileCapabilityType; import org.openqa.selenium.Capabilities; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.SearchContext; @@ -49,6 +48,7 @@ import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; +import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; import static java.time.Duration.ofSeconds; /** @@ -88,7 +88,7 @@ public AppiumFieldDecorator(SearchContext context, Duration duration) { if (wd instanceof HasCapabilities) { Capabilities caps = ((HasCapabilities) wd).getCapabilities(); this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); - this.automation = CapabilityHelpers.getCapability(caps, MobileCapabilityType.AUTOMATION_NAME, String.class); + this.automation = CapabilityHelpers.getCapability(caps, AUTOMATION_NAME_OPTION, String.class); } else { this.platform = null; this.automation = null; @@ -123,7 +123,7 @@ public AppiumFieldDecorator(SearchContext context) { if (wd instanceof HasCapabilities) { Capabilities caps = ((HasCapabilities) wd).getCapabilities(); this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); - this.automation = CapabilityHelpers.getCapability(caps, MobileCapabilityType.AUTOMATION_NAME, String.class); + this.automation = CapabilityHelpers.getCapability(caps, AUTOMATION_NAME_OPTION, String.class); } else { this.platform = null; this.automation = null; diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index 5cb10c9de..ab4e29274 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -175,11 +175,6 @@ protected By buildMobileNativeBy() { getBys(iOSXCUITFindBy.class, iOSXCUITFindBys.class, iOSXCUITFindAll.class)); } - if (isWindows()) { - return buildMobileBy(howToUseLocatorsOptional.map(HowToUseLocators::windowsAutomation).orElse(null), - getBys(WindowsFindBy.class, WindowsFindBys.class, WindowsFindAll.class)); - } - return null; } diff --git a/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java b/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java index 2e091064f..cdeb9da1e 100644 --- a/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java +++ b/src/main/java/io/appium/java_client/pagefactory/HowToUseLocators.java @@ -33,16 +33,6 @@ */ LocatorGroupStrategy androidAutomation() default LocatorGroupStrategy.CHAIN; - /** - * The strategy which defines how to use locators which are described by the - * {@link WindowsFindBy} annotation. These annotations can define the chained searching - * or the searching by all possible locators. - * - * @return the strategy which defines how to use locators which are described by the - * {@link WindowsFindBy} annotation - */ - LocatorGroupStrategy windowsAutomation() default LocatorGroupStrategy.CHAIN; - /** * The strategy which defines how to use locators which are described by the * {@link iOSXCUITFindBy} annotation. These annotations can define the chained searching diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java b/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java deleted file mode 100644 index 3c599c326..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsBy.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.pagefactory; - -/** - * Used to build a complex Windows automation locator. - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -public @interface WindowsBy { - - /** - * It is a Windows automator string. - * - * @return a Windows automator string - */ - String windowsAutomation() default ""; - - /** - * It an UI automation accessibility Id which is a convenient to Windows. - * - * @return an UI automation accessibility Id - */ - String accessibility() default ""; - - /** - * It is an id of the target element. - * - * @return an id of the target element - */ - String id() default ""; - - /** - * It is a className of the target element. - * - * @return a className of the target element - */ - String className() default ""; - - /** - * It is a desired element tag. - * - * @return a desired element tag - */ - String tagName() default ""; - - /** - * It is a xpath to the target element. - * - * @return a xpath to the target element - */ - String xpath() default ""; - - /** - * Priority of the searching. Higher number means lower priority. - * - * @return priority of the searching - */ - int priority() default 0; -} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java deleted file mode 100644 index ac1d0d0a5..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindAll.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.pagefactory; - -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Used to mark a field on a Page/Screen Object to indicate that lookup should use a series - * of {@link WindowsBy} tags - * It will then search for all elements that match any criteria. Note that elements - * are not guaranteed to be in document order. - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -@Retention(RUNTIME) @Target({FIELD, TYPE}) -@Repeatable(WindowsFindByAllSet.class) -public @interface WindowsFindAll { - /** - * It is a set of {@link WindowsBy} strategies which may be used to find the target element. - * - * @return a collection of strategies which may be used to find the target element - */ - WindowsBy[] value(); - - /** - * Priority of the searching. Higher number means lower priority. - * - * @return priority of the searching - */ - int priority() default 0; -} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java deleted file mode 100644 index f1c67be98..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBy.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.pagefactory; - -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Used to mark a field on a Page Object to indicate an alternative mechanism for locating the - * element or a list of elements. Used in conjunction with - * {@link org.openqa.selenium.support.PageFactory} - * this allows users to quickly and easily create PageObjects. - * using Windows automation selectors, accessibility, id, name, class name, tag and xpath - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -@Retention(RUNTIME) @Target({FIELD, TYPE}) -@Repeatable(WindowsFindBySet.class) -public @interface WindowsFindBy { - - /** - * It is a Windows automator string. - * - * @return a Windows automator string - */ - String windowsAutomation() default ""; - - /** - * It an UI automation accessibility Id which is a convenient to Windows. - * - * @return an UI automation accessibility Id - */ - String accessibility() default ""; - - /** - * It is an id of the target element. - * - * @return an id of the target element - */ - String id() default ""; - - /** - * It is a className of the target element. - * - * @return a className of the target element - */ - String className() default ""; - - /** - * It is a desired element tag. - * - * @return a desired element tag - */ - String tagName() default ""; - - /** - * It is a xpath to the target element. - * - * @return a xpath to the target element - */ - String xpath() default ""; - - /** - * Priority of the searching. Higher number means lower priority. - * - * @return priority of the searching - */ - int priority() default 0; -} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java deleted file mode 100644 index f93e00d92..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByAllSet.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.appium.java_client.pagefactory; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Defines set of chained/possible locators. Each one locator - * should be defined with {@link WindowsFindAll} - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -@Target(value = {TYPE, FIELD}) -@Retention(value = RUNTIME) -public @interface WindowsFindByAllSet { - /** - * An array of which builds a sequence of the chained searching for elements or a set of possible locators. - * - * @return an array of {@link WindowsFindAll} which builds a sequence of - * the chained searching for elements or a set of possible locators - */ - WindowsFindAll[] value(); -} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java deleted file mode 100644 index b8a3e9f23..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindByChainSet.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.appium.java_client.pagefactory; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Defines set of chained/possible locators. Each one locator - * should be defined with {@link WindowsFindBys} - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -@Target(value = {TYPE, FIELD}) -@Retention(value = RUNTIME) -public @interface WindowsFindByChainSet { - /** - * An array of which builds a sequence of the chained searching for elements or a set of possible locators. - * - * @return an array of {@link WindowsFindBys} which builds a sequence of - * the chained searching for elements or a set of possible locators - */ - WindowsFindBys[] value(); -} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java deleted file mode 100644 index e953d63a1..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBySet.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.pagefactory; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Defines set of chained/possible locators. Each one locator - * should be defined with {@link WindowsFindBy} - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -@Target(value = {TYPE, FIELD}) -@Retention(value = RUNTIME) -public @interface WindowsFindBySet { - /** - * An array ofwhich builds a sequence of the chained searching for elements or a set of possible locators. - * - * @return an array of {@link WindowsFindBy} which builds a sequence of - * the chained searching for elements or a set of possible locators - */ - WindowsFindBy[] value(); -} diff --git a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java b/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java deleted file mode 100644 index 358a77ae8..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/WindowsFindBys.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.pagefactory; - -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Used to mark a field on a Page Object to indicate that lookup should use - * a series of {@link WindowsBy} tags. - * @deprecated This annotation is deprecated and will be removed. - */ -@Deprecated -@Retention(RUNTIME) @Target({FIELD, TYPE}) -@Repeatable(WindowsFindByChainSet.class) -public @interface WindowsFindBys { - /** - * It is a set of {@link WindowsBy} strategies which build the chain of the searching for the target element. - * - * @return a collection of strategies which build the chain of the searching for the target element - */ - WindowsBy[] value(); - - /** - * Priority of the searching. Higher number means lower priority. - * - * @return priority of the searching - */ - int priority() default 0; -} diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java deleted file mode 100644 index 4999c294d..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByAll.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.appium.java_client.pagefactory.bys.builder; - -import org.openqa.selenium.By; -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.SearchContext; -import org.openqa.selenium.WebElement; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Mechanism used to locate elements within a document using a series of lookups. This class will - * find all DOM elements that matches any of the locators in sequence, e.g. - *
- * driver.findElements(new ByAll(by1, by2))
- * 
- * will find all elements that match by1 and then all elements that match by2. - * This means that the list of elements returned may not be in document order. - * - * @deprecated Use {@link org.openqa.selenium.support.pagefactory.ByAll} - */ -@Deprecated -public class ByAll extends org.openqa.selenium.support.pagefactory.ByAll { - - private final List bys; - - private Function> getSearchingFunction(By by) { - return input -> { - try { - return Optional.of(input.findElement(by)); - } catch (NoSuchElementException e) { - return Optional.empty(); - } - }; - } - - /** - * Finds all elements that matches any of the locators in sequence. - * - * @param bys is a set of {@link By} which forms the all possible searching. - */ - public ByAll(By[] bys) { - super(bys); - checkNotNull(bys); - - this.bys = Arrays.asList(bys); - - checkArgument(!this.bys.isEmpty(), "By array should not be empty"); - } - - @Override - public WebElement findElement(SearchContext context) { - return bys.stream() - .map(by -> getSearchingFunction(by).apply(context)) - .filter(Optional::isPresent) - .map(Optional::get) - .findFirst() - .orElseThrow(() -> new NoSuchElementException("Cannot locate an element using " + toString())); - } -} diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 452a8cda0..590db8278 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -17,7 +17,6 @@ package io.appium.java_client.pagefactory.bys.builder; import io.appium.java_client.AppiumBy; -import io.appium.java_client.MobileBy; import io.appium.java_client.pagefactory.AndroidBy; import io.appium.java_client.pagefactory.AndroidFindBy; import org.openqa.selenium.By; @@ -40,16 +39,6 @@ enum Strategies { return super.getBy(annotation); } }, - /** - * This has been deprecated due to misspelling. - * @deprecated Use {@link Strategies#BYACCESSIBILITY} instead. - */ - @Deprecated - BYACCESSABILITY("accessibility") { - @Override By getBy(Annotation annotation) { - return AppiumBy.accessibilityId(getValue(annotation, this)); - } - }, BYACCESSIBILITY("accessibility") { @Override By getBy(Annotation annotation) { return AppiumBy.accessibilityId(getValue(annotation, this)); @@ -93,16 +82,6 @@ enum Strategies { .partialLinkText(getValue(annotation, this)); } }, - /** - * The Windows UIAutomation strategy. - * @deprecated Not supported on the server side. - */ - @Deprecated - BYWINDOWSAUTOMATION("windowsAutomation") { - @Override By getBy(Annotation annotation) { - return MobileBy.windowsAutomation(getValue(annotation, this)); - } - }, BY_CLASS_CHAIN("iOSClassChain") { @Override By getBy(Annotation annotation) { return AppiumBy diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java index 7cec1ad07..3cf725bd6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import static io.appium.java_client.proxy.Helpers.OBJECT_METHOD_NAMES; @@ -36,17 +37,26 @@ * proxy object here. */ public final class ProxyFactory { - private static final Set NON_PROXYABLE_METHODS = setWithout(OBJECT_METHOD_NAMES, "toString"); + private static final Set NON_PROXYABLE_METHODS = setWith( + setWithout(OBJECT_METHOD_NAMES, "toString"), + "iterator" + ); - @SuppressWarnings("unchecked") + @SafeVarargs private static Set setWithout(@SuppressWarnings("SameParameterValue") Set source, T... items) { Set result = new HashSet<>(source); Arrays.asList(items).forEach(result::remove); return Collections.unmodifiableSet(result); } + @SafeVarargs + private static Set setWith(@SuppressWarnings("SameParameterValue") Set source, T... items) { + Set result = new HashSet<>(source); + result.addAll(List.of(items)); + return Collections.unmodifiableSet(result); + } + private ProxyFactory() { - super(); } /** diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 6d31fcc5a..01cc25a7e 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -29,7 +29,6 @@ import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; import static java.util.Optional.ofNullable; -import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; public final class WebDriverUnpackUtility { private static final String NATIVE_APP_PATTERN = "NATIVE_APP"; @@ -91,8 +90,8 @@ public static ContentType getCurrentContentType(SearchContext context) { if (ContextAware.class.isAssignableFrom(driver.getClass())) { //it is desktop browser ContextAware contextAware = (ContextAware) driver; - String currentContext = contextAware.getContext(); - if (containsIgnoreCase(currentContext, NATIVE_APP_PATTERN)) { + var currentContext = contextAware.getContext(); + if (currentContext != null && currentContext.toUpperCase().contains(NATIVE_APP_PATTERN)) { return NATIVE_MOBILE_SPECIFIC; } } diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index 2dd5912ca..6ed19b7a4 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -35,7 +35,6 @@ import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; public class Helpers { - public static final Set OBJECT_METHOD_NAMES = Stream.of(Object.class.getMethods()) .map(Method::getName) .collect(Collectors.toSet()); diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java index fa4d72405..b8417e14b 100644 --- a/src/main/java/io/appium/java_client/proxy/Interceptor.java +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -39,9 +39,9 @@ private Interceptor() { * A magic method used to wrap public method calls in classes * patched by ByteBuddy and acting as proxies. * - * @param self The reference to the original instance. - * @param method The reference to the original method. - * @param args The reference to method args. + * @param self The reference to the original instance. + * @param method The reference to the original method. + * @param args The reference to method args. * @param callable The reference to the non-patched callable to avoid call recursion. * @return Either the original method result or the patched one. */ @@ -64,10 +64,9 @@ public static Object intercept( } catch (NotImplementedException e) { // ignore } catch (Exception e) { - LOGGER.atError() - .addArgument(() -> self.getClass().getName()) - .addArgument(method::getName) - .log("Got an unexpected error in beforeCall listener of {}.{} method", e); + LOGGER.atError().log("Got an unexpected error in beforeCall listener of {}.{} method", + self.getClass().getName(), method.getName(), e + ); } }); @@ -110,10 +109,9 @@ public static Object intercept( } catch (NotImplementedException e) { // ignore } catch (Exception e) { - LOGGER.atError() - .addArgument(() -> self.getClass().getName()) - .addArgument(method::getName) - .log("Got an unexpected error in afterCall listener of {}.{} method", e); + LOGGER.atError().log("Got an unexpected error in afterCall listener of {}.{} method", + self.getClass().getName(), method.getName(), e + ); } }); return endResult; diff --git a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java index 4b314b02b..8ba4d734b 100644 --- a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java +++ b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java @@ -16,14 +16,20 @@ package io.appium.java_client.proxy; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + import java.lang.ref.WeakReference; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Semaphore; +@NoArgsConstructor(access = AccessLevel.PRIVATE) class ProxyListenersContainer { private static ProxyListenersContainer INSTANCE; @@ -35,31 +41,14 @@ public static synchronized ProxyListenersContainer getInstance() { } private final Semaphore listenersGuard = new Semaphore(1); - // Previously WeakHashMap has been used because of O(1) lookup performance, although - // we had to change it to a list, which has O(N). The reason for that is that - // maps implicitly call `hashCode` API on instances, which might not always - // work as expected for arbitrary proxies - private final List, Collection>> listeners = new LinkedList<>(); + private final List, Collection>> listenerPairs = new LinkedList<>(); + @Getter + @AllArgsConstructor private static class Pair { private final K key; - private final V value; - - public Pair(K key, V value) { - this.key = key; - this.value = value; - } - - public K getKey() { - return key; - } - - public V getValue() { - return value; - } - } - - private ProxyListenersContainer() { + @Setter + private V value; } /** @@ -78,24 +67,23 @@ public T setListeners(T proxyInstance, Collection listen try { int i = 0; boolean wasInstancePresent = false; - while (i < this.listeners.size()) { - Pair, Collection> pair = this.listeners.get(i); + while (i < listenerPairs.size()) { + var pair = listenerPairs.get(i); Object key = pair.getKey().get(); if (key == null) { // The instance has been garbage-collected - this.listeners.remove(i); + listenerPairs.remove(i); continue; } if (key == proxyInstance) { - pair.getValue().clear(); - pair.getValue().addAll(listeners); + pair.setValue(List.copyOf(listeners)); wasInstancePresent = true; } i++; } if (!wasInstancePresent) { - this.listeners.add(new Pair<>(new WeakReference<>(proxyInstance), new HashSet<>(listeners))); + listenerPairs.add(new Pair<>(new WeakReference<>(proxyInstance), List.copyOf(listeners))); } } finally { listenersGuard.release(); @@ -116,13 +104,13 @@ public Collection getListeners(Object proxyInstance) { } try { int i = 0; - Collection result = Collections.emptySet(); - while (i < listeners.size()) { - Pair, Collection> pair = listeners.get(i); + Collection result = Collections.emptyList(); + while (i < listenerPairs.size()) { + var pair = listenerPairs.get(i); Object key = pair.getKey().get(); if (key == null) { // The instance has been garbage-collected - listeners.remove(i); + listenerPairs.remove(i); continue; } diff --git a/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java deleted file mode 100644 index 6b698d004..000000000 --- a/src/main/java/io/appium/java_client/remote/AndroidMobileCapabilityType.java +++ /dev/null @@ -1,495 +0,0 @@ -/* - * 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.remote; - -import org.openqa.selenium.remote.CapabilityType; - -/** - * The list of Android-specific capabilities.
- * Read:
- * - * https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md#android-only - * - * @deprecated This interface will be removed. Use Options instead. - */ -@Deprecated -public interface AndroidMobileCapabilityType extends CapabilityType { - - /** - * Activity name for the Android activity you want to launch from your package. - * This often needs to be preceded by a {@code .} (e.g., {@code .MainActivity} - * instead of {@code MainActivity}). By default this capability is received from the package - * manifest (action: android.intent.action.MAIN , category: android.intent.category.LAUNCHER) - */ - String APP_ACTIVITY = "appActivity"; - - /** - * Java package of the Android app you want to run. By default this capability is received - * from the package manifest ({@literal @}package attribute value) - */ - String APP_PACKAGE = "appPackage"; - - /** - * Activity name/names, comma separated, for the Android activity you want to wait for. - * By default the value of this capability is the same as for {@code appActivity}. - * You must set it to the very first focused application activity name in case it is different - * from the one which is set as {@code appActivity} if your capability has {@code appActivity} - * and {@code appPackage}. You can also use wildcards ({@code *}). - */ - String APP_WAIT_ACTIVITY = "appWaitActivity"; - - /** - * Java package of the Android app you want to wait for. - * By default the value of this capability is the same as for {@code appActivity} - */ - String APP_WAIT_PACKAGE = "appWaitPackage"; - - /** - * Timeout in milliseconds used to wait for the appWaitActivity to launch (default 20000). - * @since 1.6.0 - */ - String APP_WAIT_DURATION = "appWaitDuration"; - - /** - * Timeout in seconds while waiting for device to become ready. - */ - String DEVICE_READY_TIMEOUT = "deviceReadyTimeout"; - - /** - * Allow to install a test package which has {@code android:testOnly="true"} in the manifest. - * {@code false} by default - */ - String ALLOW_TEST_PACKAGES = "allowTestPackages"; - - /** - * Fully qualified instrumentation class. Passed to -w in adb shell - * am instrument -e coverage true -w. - */ - String ANDROID_COVERAGE = "androidCoverage"; - - /** - * A broadcast action implemented by yourself which is used to dump coverage into file system. - * Passed to -a in adb shell am broadcast -a - */ - String ANDROID_COVERAGE_END_INTENT = "androidCoverageEndIntent"; - - /** - * (Chrome and webview only) Enable Chromedriver's performance logging (default false). - * - * @deprecated move to {@link MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING} - */ - @Deprecated - String ENABLE_PERFORMANCE_LOGGING = "enablePerformanceLogging"; - - /** - * Timeout in seconds used to wait for a device to become ready after booting. - */ - String ANDROID_DEVICE_READY_TIMEOUT = "androidDeviceReadyTimeout"; - - /** - * Port used to connect to the ADB server (default 5037). - */ - String ADB_PORT = "adbPort"; - - /** - * Devtools socket name. Needed only when tested app is a Chromium embedding browser. - * The socket is open by the browser and Chromedriver connects to it as a devtools client. - */ - String ANDROID_DEVICE_SOCKET = "androidDeviceSocket"; - - /** - * Timeout in milliseconds used to wait for an apk to install to the device. Defaults to `90000`. - * @since 1.6.0 - */ - String ANDROID_INSTALL_TIMEOUT = "androidInstallTimeout"; - - /** - * The name of the directory on the device in which the apk will be push before install. - * Defaults to {@code /data/local/tmp} - * @since 1.6.5 - */ - String ANDROID_INSTALL_PATH = "androidInstallPath"; - - /** - * Name of avd to launch. - */ - String AVD = "avd"; - - /** - * How long to wait in milliseconds for an avd to launch and connect to - * ADB (default 120000). - * @since 0.18.0 - */ - String AVD_LAUNCH_TIMEOUT = "avdLaunchTimeout"; - - /** - * How long to wait in milliseconds for an avd to finish its - * boot animations (default 120000). - * @since 0.18.0 - */ - String AVD_READY_TIMEOUT = "avdReadyTimeout"; - - /** - * Additional emulator arguments used when launching an avd. - */ - String AVD_ARGS = "avdArgs"; - - /** - * Use a custom keystore to sign apks, default false. - */ - String USE_KEYSTORE = "useKeystore"; - - /** - * Path to custom keystore, default ~/.android/debug.keystore. - */ - String KEYSTORE_PATH = "keystorePath"; - - /** - * Password for custom keystore. - */ - String KEYSTORE_PASSWORD = "keystorePassword"; - - /** - * Alias for key. - */ - String KEY_ALIAS = "keyAlias"; - - /** - * Password for key. - */ - String KEY_PASSWORD = "keyPassword"; - - /** - * The absolute local path to webdriver executable (if Chromium embedder provides - * its own webdriver, it should be used instead of original chromedriver - * bundled with Appium). - */ - String CHROMEDRIVER_EXECUTABLE = "chromedriverExecutable"; - - /** - * An array of arguments to be passed to the chromedriver binary when it's run by Appium. - * By default no CLI args are added beyond what Appium uses internally (such as {@code --url-base}, {@code --port}, - * {@code --adb-port}, and {@code --log-path}. - * @since 1.12.0 - */ - String CHROMEDRIVER_ARGS = "chromedriverArgs"; - - /** - * The absolute path to a directory to look for Chromedriver executables in, for automatic discovery of compatible - * Chromedrivers. Ignored if {@code chromedriverUseSystemExecutable} is {@code true} - * @since 1.8.0 - */ - String CHROMEDRIVER_EXECUTABLE_DIR = "chromedriverExecutableDir"; - - /** - * The absolute path to a file which maps Chromedriver versions to the minimum Chrome that it supports. - * Ignored if {@code chromedriverUseSystemExecutable} is {@code true} - * @since 1.8.0 - */ - String CHROMEDRIVER_CHROME_MAPPING_FILE = "chromedriverChromeMappingFile"; - - /** - * If true, bypasses automatic Chromedriver configuration and uses the version that comes downloaded with Appium. - * Ignored if {@code chromedriverExecutable} is set. Defaults to {@code false} - * @since 1.9.0 - */ - String CHROMEDRIVER_USE_SYSTEM_EXECUTABLE = "chromedriverUseSystemExecutable"; - - /** - * Numeric port to start Chromedriver on. Note that use of this capability is discouraged as it will cause undefined - * behavior in case there are multiple webviews present. By default Appium will find a free port. - */ - String CHROMEDRIVER_PORT = "chromedriverPort"; - - /** - * A list of valid ports for Appium to use for communication with Chromedrivers. This capability supports multiple - * webview scenarios. The form of this capability is an array of numeric ports, where array items can themselves be - * arrays of length 2, where the first element is the start of an inclusive range and the second is the end. - * By default, Appium will use any free port. - * @since 1.13.0 - */ - String CHROMEDRIVER_PORTS = "chromedriverPorts"; - - /** - * Sets the chromedriver flag {@code --disable-build-check} for Chrome webview tests. - * @since 1.11.0 - */ - String CHROMEDRIVER_DISABLE_BUILD_CHECK = "chromedriverDisableBuildCheck"; - - /** - * Amount of time to wait for Webview context to become active, in ms. Defaults to 2000. - * @since 1.5.2 - */ - String AUTO_WEBVIEW_TIMEOUT = "autoWebviewTimeout"; - - /** - * Intent action which will be used to start activity - * (default android.intent.action.MAIN). - */ - String INTENT_ACTION = "intentAction"; - - /** - * Intent category which will be used to start - * activity (default android.intent.category.LAUNCHER). - */ - String INTENT_CATEGORY = "intentCategory"; - - /** - * Flags that will be used to start activity (default 0x10200000). - */ - String INTENT_FLAGS = "intentFlags"; - - /** - * Additional intent arguments that will be used to start activity. See - * - * Intent arguments. - */ - String OPTIONAL_INTENT_ARGUMENTS = "optionalIntentArguments"; - - /** - * Doesn't stop the process of the app under test, before starting the app using adb. - * If the app under test is created by another anchor app, setting this false, - * allows the process of the anchor app to be still alive, during the start of - * the test app using adb. In other words, with dontStopAppOnReset set to true, - * we will not include the -S flag in the adb shell am start call. - * With this capability omitted or set to false, we include the -S flag. Default false - * @since 1.4.0 - */ - String DONT_STOP_APP_ON_RESET = "dontStopAppOnReset"; - - /** - * Enable Unicode input, default false. - * @since 1.2.0 - */ - String UNICODE_KEYBOARD = "unicodeKeyboard"; - - /** - * Reset keyboard to its original state, after running Unicode tests with - * unicodeKeyboard capability. Ignored if used alone. Default false - */ - String RESET_KEYBOARD = "resetKeyboard"; - - /** - * Skip checking and signing of app with debug keys, will work only with - * UiAutomator and not with selendroid, default false. - * @since 1.2.2 - */ - String NO_SIGN = "noSign"; - - /** - * Calls the setCompressedLayoutHierarchy() uiautomator function. - * This capability can speed up test execution, since Accessibility commands will run - * faster ignoring some elements. The ignored elements will not be findable, - * which is why this capability has also been implemented as a toggle-able - * setting as well as a capability. Defaults to false. - */ - String IGNORE_UNIMPORTANT_VIEWS = "ignoreUnimportantViews"; - - /** - * Disables android watchers that watch for application not responding and application crash, - * this will reduce cpu usage on android device/emulator. This capability will work only with - * UiAutomator and not with selendroid, default false. - * @since 1.4.0 - */ - String DISABLE_ANDROID_WATCHERS = "disableAndroidWatchers"; - - /** - * Allows passing chromeOptions capability for ChromeDriver. - * For more information see - * - * chromeOptions. - */ - String CHROME_OPTIONS = "chromeOptions"; - - /** - * Kill ChromeDriver session when moving to a non-ChromeDriver webview. - * Defaults to false - */ - String RECREATE_CHROME_DRIVER_SESSIONS = "recreateChromeDriverSessions"; - - /** - * In a web context, use native (adb) method for taking a screenshot, rather than proxying - * to ChromeDriver, default false. - * @since 1.5.3 - */ - String NATIVE_WEB_SCREENSHOT = "nativeWebScreenshot"; - - /** - * The name of the directory on the device in which the screenshot will be put. - * Defaults to /data/local/tmp. - * @since 1.6.0 - */ - String ANDROID_SCREENSHOT_PATH = "androidScreenshotPath"; - - /** - * Set the network speed emulation. Specify the maximum network upload and download speeds. Defaults to {@code full} - */ - String NETWORK_SPEED = "networkSpeed"; - - /** - * Toggle gps location provider for emulators before starting the session. By default the emulator will have this - * option enabled or not according to how it has been provisioned. - */ - String GPS_ENABLED = "gpsEnabled"; - - /** - * Set this capability to {@code true} to run the Emulator headless when device display is not needed to be visible. - * {@code false} is the default value. isHeadless is also support for iOS, check XCUITest-specific capabilities. - */ - String IS_HEADLESS = "isHeadless"; - - /** - * Timeout in milliseconds used to wait for adb command execution. Defaults to {@code 20000} - */ - String ADB_EXEC_TIMEOUT = "adbExecTimeout"; - - /** - * Sets the locale script. - * @since 1.10.0 - */ - String LOCALE_SCRIPT = "localeScript"; - - /** - * Skip device initialization which includes i.a.: installation and running of Settings app or setting of - * permissions. Can be used to improve startup performance when the device was already used for automation and - * it's prepared for the next automation. Defaults to {@code false} - * @since 1.11.0 - */ - String SKIP_DEVICE_INITIALIZATION = "skipDeviceInitialization"; - - /** - * Have Appium automatically determine which permissions your app requires and - * grant them to the app on install. Defaults to {@code false}. If noReset is {@code true}, this capability doesn't - * work. - */ - String AUTO_GRANT_PERMISSIONS = "autoGrantPermissions"; - - /** - * Allow for correct handling of orientation on landscape-oriented devices. - * Set to {@code true} to basically flip the meaning of {@code PORTRAIT} and {@code LANDSCAPE}. - * Defaults to {@code false}. - * @since 1.6.4 - */ - String ANDROID_NATURAL_ORIENTATION = "androidNaturalOrientation"; - - /** - * {@code systemPort} used to connect to - * appium-uiautomator2-server or - * appium-espresso-driver. - * The default is {@code 8200} in general and selects one port from {@code 8200} to {@code 8299} - * for appium-uiautomator2-server, it is {@code 8300} from {@code 8300} to {@code 8399} for - * appium-espresso-driver. When you run tests in parallel, you must adjust the port to avoid conflicts. Read - * - * Parallel Testing Setup Guide for more details. - */ - String SYSTEM_PORT = "systemPort"; - - /** - * Optional remote ADB server host. - * @since 1.7.0 - */ - String REMOTE_ADB_HOST = "remoteAdbHost"; - - /** - * Skips unlock during session creation. Defaults to {@code false} - */ - String SKIP_UNLOCK = "skipUnlock"; - - /** - * Unlock the target device with particular lock pattern instead of just waking up the device with a helper app. - * It works with {@code unlockKey} capability. Defaults to undefined. {@code fingerprint} is available only for - * Android 6.0+ and emulators. - * Read unlock doc in - * android driver. - */ - String UNLOCK_TYPE = "unlockType"; - - /** - * A key pattern to unlock used by {@code unlockType}. - */ - String UNLOCK_KEY = "unlockKey"; - - /** - * Initializing the app under test automatically. - * Appium does not launch the app under test if this is {@code false}. Defaults to {@code true} - */ - String AUTO_LAUNCH = "autoLaunch"; - - /** - * Skips to start capturing logcat. It might improve performance such as network. - * Log related commands will not work. Defaults to {@code false}. - * @since 1.12.0 - */ - String SKIP_LOGCAT_CAPTURE = "skipLogcatCapture"; - - /** - * A package, list of packages or * to uninstall package/s before installing apks for test. - * {@code '*'} uninstall all of thrid-party packages except for packages which is necessary for Appium to test such - * as {@code io.appium.settings} or {@code io.appium.uiautomator2.server} since Appium already contains the logic to - * manage them. - * @since 1.12.0 - */ - String UNINSTALL_OTHER_PACKAGES = "uninstallOtherPackages"; - - /** - * Set device animation scale zero if the value is {@code true}. After session is complete, Appium restores the - * animation scale to it's original value. Defaults to {@code false} - * @since 1.9.0 - */ - String DISABLE_WINDOW_ANIMATION = "disableWindowAnimation"; - - /** - * Specify the Android build-tools version to be something different than the default, which is to use the most - * recent version. It is helpful to use a non-default version if your environment uses alpha/beta build tools. - * @since 1.14.0 - */ - String BUILD_TOOLS_VERSION = "buildToolsVersion"; - - /** - * By default application installation is skipped if newer or the same version of this app is already present on - * the device under test. Setting this option to {@code true} will enforce Appium to always install the current - * application build independently of the currently installed version of it. Defaults to {@code false}. - * @since 1.16.0 - */ - String ENFORCE_APP_INSTALL = "enforceAppInstall"; - - /** - * Whether or not Appium should augment its webview detection with page detection, guaranteeing that any - * webview contexts which show up in the context list have active pages. This can prevent an error if a - * context is selected where Chromedriver cannot find any pages. Defaults to {@code false}. - * @since 1.15.0 - */ - String ENSURE_WEBVIEWS_HAVE_PAGES = "ensureWebviewsHavePages"; - - /** - * To support the `ensureWebviewsHavePages` feature, it is necessary to open a TCP port for communication with - * the webview on the device under test. This capability allows overriding of the default port of {@code 9222}, - * in case multiple sessions are running simultaneously (to avoid port clash), or in case the default port - * is not appropriate for your system. - * @since 1.15.0 - */ - String WEBVIEW_DEVTOOLS_PORT = "webviewDevtoolsPort"; - - /** - * Set the maximum number of remote cached apks which are pushed to the device-under-test's - * local storage. Caching apks remotely speeds up the execution of sequential test cases, when using the - * same set of apks, by avoiding the need to be push an apk to the remote file system every time a - * reinstall is needed. Set this capability to {@code 0} to disable caching. Defaults to {@code 10}. - * @since 1.14.0 - */ - String REMOTE_APPS_CACHE_LIMIT = "remoteAppsCacheLimit"; -} diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index ee0e5a396..d7dd90683 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -18,9 +18,7 @@ import com.google.common.base.Supplier; import com.google.common.base.Throwables; -import com.google.common.net.HttpHeaders; import io.appium.java_client.AppiumClientConfig; -import io.appium.java_client.AppiumUserAgentFilter; import io.appium.java_client.internal.ReflectionHelpers; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; @@ -48,7 +46,6 @@ import java.net.URL; import java.util.Map; import java.util.Optional; -import java.util.UUID; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.throwIfUnchecked; @@ -56,8 +53,6 @@ import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; public class AppiumCommandExecutor extends HttpCommandExecutor { - // https://github.com/appium/appium-base-driver/pull/400 - private static final String IDEMPOTENCY_KEY_HEADER = "X-Idempotency-Key"; private final Optional serviceOptional; @@ -179,14 +174,7 @@ private Response createSession(Command command) throws IOException { throw new SessionNotCreatedException("Session already exists"); } - ProtocolHandshake.Result result = new AppiumProtocolHandshake().createSession( - getClient().with(httpHandler -> req -> { - req.setHeader(HttpHeaders.USER_AGENT, - AppiumUserAgentFilter.buildUserAgent(req.getHeader(HttpHeaders.USER_AGENT))); - req.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); - return httpHandler.execute(req); - }), command - ); + ProtocolHandshake.Result result = new AppiumProtocolHandshake().createSession(getClient(), command); Dialect dialect = result.getDialect(); if (!(dialect.getCommandCodec() instanceof W3CHttpCommandCodec)) { throw new SessionNotCreatedException("Only W3C sessions are supported. " diff --git a/src/main/java/io/appium/java_client/remote/AutomationName.java b/src/main/java/io/appium/java_client/remote/AutomationName.java index 4ee53ea1a..7df904c4d 100644 --- a/src/main/java/io/appium/java_client/remote/AutomationName.java +++ b/src/main/java/io/appium/java_client/remote/AutomationName.java @@ -18,8 +18,6 @@ public interface AutomationName { // Officially supported drivers - @Deprecated - String APPIUM = "Appium"; // https://github.com/appium/appium-xcuitest-driver String IOS_XCUI_TEST = "XCuiTest"; // https://github.com/appium/appium-uiautomator2-driver diff --git a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java deleted file mode 100644 index b8b517132..000000000 --- a/src/main/java/io/appium/java_client/remote/IOSMobileCapabilityType.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * 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.remote; - -import org.openqa.selenium.remote.CapabilityType; - -/** - * The list of iOS-specific capabilities.
- * Read:
- * - * https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md#ios-only - *
- * and
- * - * https://appium.github.io/appium-xcuitest-driver/latest/capabilities/ - * - * @deprecated This interface will be removed. Use Options instead. - */ -@Deprecated -public interface IOSMobileCapabilityType extends CapabilityType { - - /** - * (Sim-only) Calendar format to set for the iOS Simulator. - */ - String CALENDAR_FORMAT = "calendarFormat"; - - /** - * Bundle ID of the app under test. Useful for starting an app on a real device - * or for using other caps which require the bundle ID during test startup. - * To run a test on a real device using the bundle ID, - * you may omit the 'app' capability, but you must provide 'udid'. - */ - String BUNDLE_ID = "bundleId"; - - /** - * (Sim-only) Force location services to be either on or off. - * Default is to keep current sim setting. - */ - String LOCATION_SERVICES_ENABLED = "locationServicesEnabled"; - - /** - * (Sim-only) Set location services to be authorized or not authorized for app via plist, - * so that location services alert doesn't pop up. Default is to keep current sim - * setting. Note that if you use this setting you MUST also use the bundleId - * capability to send in your app's bundle ID. - */ - String LOCATION_SERVICES_AUTHORIZED = "locationServicesAuthorized"; - - /** - * Accept all iOS alerts automatically if they pop up. - * This includes privacy access permission alerts - * (e.g., location, contacts, photos). Default is false. - */ - String AUTO_ACCEPT_ALERTS = "autoAcceptAlerts"; - - /** - * Dismiss all iOS alerts automatically if they pop up. - * This includes privacy access permission alerts (e.g., - * location, contacts, photos). Default is false. - */ - String AUTO_DISMISS_ALERTS = "autoDismissAlerts"; - - /** - * Use native intruments lib (ie disable instruments-without-delay). - */ - String NATIVE_INSTRUMENTS_LIB = "nativeInstrumentsLib"; - - /** - * Enable "real", non-javascript-based web taps in Safari. - * Default: false. - * Warning: depending on viewport size/ratio this might not accurately tap an element. - */ - String NATIVE_WEB_TAP = "nativeWebTap"; - - /** - * (Sim-only) (>= 8.1) Initial safari url, default is a local welcome page. - */ - String SAFARI_INITIAL_URL = "safariInitialUrl"; - - /** - * (Sim-only) Allow javascript to open new windows in Safari. Default keeps current sim - * setting. - */ - String SAFARI_ALLOW_POPUPS = "safariAllowPopups"; - - /** - * (Sim-only) Prevent Safari from showing a fraudulent website warning. - * Default keeps current sim setting. - */ - String SAFARI_IGNORE_FRAUD_WARNING = "safariIgnoreFraudWarning"; - - /** - * (Sim-only) Whether Safari should allow links to open in new windows. - * Default keeps current sim setting. - */ - String SAFARI_OPEN_LINKS_IN_BACKGROUND = "safariOpenLinksInBackground"; - - /** - * (Sim-only) Whether to keep keychains (Library/Keychains) when appium - * session is started/finished. - */ - String KEEP_KEY_CHAINS = "keepKeyChains"; - - /** - * Where to look for localizable strings. Default en.lproj. - */ - String LOCALIZABLE_STRINGS_DIR = "localizableStringsDir"; - - /** - * Arguments to pass to the AUT using instruments. - */ - String PROCESS_ARGUMENTS = "processArguments"; - - /** - * The delay, in ms, between keystrokes sent to an element when typing. - */ - String INTER_KEY_DELAY = "interKeyDelay"; - - /** - * Whether to show any logs captured from a device in the appium logs. Default false. - */ - String SHOW_IOS_LOG = "showIOSLog"; - - /** - * strategy to use to type test into a test field. Simulator default: oneByOne. - * Real device default: grouped. - */ - String SEND_KEY_STRATEGY = "sendKeyStrategy"; - - /** - * Max timeout in sec to wait for a screenshot to be generated. default: 10. - */ - String SCREENSHOT_WAIT_TIMEOUT = "screenshotWaitTimeout"; - - /** - * The ios automation script used to determined if the app has been launched, - * by default the system wait for the page source not to be empty. - * The result must be a boolean. - */ - String WAIT_FOR_APP_SCRIPT = "waitForAppScript"; - - /** - * Number of times to send connection message to remote debugger, to get webview. - * Default: 8. - */ - String WEBVIEW_CONNECT_RETRIES = "webviewConnectRetries"; - - /** - * The display name of the application under test. Used to automate backgrounding - * the app in iOS 9+. - */ - String APP_NAME = "appName"; - - /** - * (Sim only) Add an SSL certificate to IOS Simulator. - */ - String CUSTOM_SSL_CERT = "customSSLCert"; - - /** - * The desired capability to specify a length for tapping, if the regular - * tap is too long for the app under test. The XCUITest specific capability. - * - * @deprecated This capability is not being used. - */ - @Deprecated - String TAP_WITH_SHORT_PRESS_DURATION = "tapWithShortPressDuration"; - - /** - * Simulator scale factor. - * This is useful to have if the default resolution of simulated device is - * greater than the actual display resolution. So you can scale the simulator - * to see the whole device screen without scrolling. - * This capability only works below Xcode9. - */ - String SCALE_FACTOR = "scaleFactor"; - - /** - * This value if specified, will be used to forward traffic from Mac - * host to real ios devices over USB. Default value is same as port - * number used by WDA on device. - * eg: 8100 - */ - String WDA_LOCAL_PORT = "wdaLocalPort"; - - /** - * Whether to display the output of the Xcode command - * used to run the tests.If this is true, - * there will be lots of extra logging at startup. Defaults to false - */ - String SHOW_XCODE_LOG = "showXcodeLog"; - - /** - * Time in milliseconds to pause between installing the application - * and starting WebDriverAgent on the device. Used particularly for larger applications. - * Defaults to 0 - */ - String IOS_INSTALL_PAUSE = "iosInstallPause"; - - /** - * Full path to an optional Xcode configuration file that - * specifies the code signing identity - * and team for running the WebDriverAgent on the real device. - * e.g., /path/to/myconfig.xcconfig - */ - String XCODE_CONFIG_FILE = "xcodeConfigFile"; - - /** - * Password for unlocking keychain specified in keychainPath. - */ - String KEYCHAIN_PASSWORD = "keychainPassword"; - - /** - * Skips the build phase of running the WDA app. - * Building is then the responsibility of the user. - * Only works for Xcode 8+. Defaults to false - */ - String USE_PREBUILT_WDA = "usePrebuiltWDA"; - - /** - * Sets read only permissons to Attachments subfolder of WebDriverAgent - * root inside Xcode's DerivedData. - * This is necessary to prevent XCTest framework from - * creating tons of unnecessary screenshots and logs, - * which are impossible to shutdown using programming - * interfaces provided by Apple - * - * @deprecated This capability was deleted at Appium 1.14.0 - */ - @Deprecated - String PREVENT_WDAATTACHMENTS = "preventWDAAttachments"; - - /** - * Appium will connect to an existing WebDriverAgent, - * instance at this URL instead of starting a new one. - * eg : http://localhost:8100 - */ - String WEB_DRIVER_AGENT_URL = "webDriverAgentUrl"; - - /** - * Full path to the private development key exported - * from the system keychain. Used in conjunction - * with keychainPassword when testing on real devices. - * e.g., /path/to/MyPrivateKey.p12 - */ - String KEYCHAIN_PATH = "keychainPath"; - - /** - * If {@code true}, forces uninstall of any existing WebDriverAgent app on device. - * Set it to {@code true} if you want to apply different startup options for WebDriverAgent for each session. - * Although, it is only guaranteed to work stable on Simulator. Real devices require WebDriverAgent - * client to run for as long as possible without reinstall/restart to avoid issues like - * - * https://github.com/facebook/WebDriverAgent/issues/507. - * The {@code false} value (the default behaviour since driver version 2.35.0) will try to detect currently - * running WDA listener executed by previous testing session(s) and reuse it if possible, which is - * highly recommended for real device testing and to speed up suites of multiple tests in general. - * A new WDA session will be triggered at the default URL (http://localhost:8100) if WDA is not - * listening and {@code webDriverAgentUrl} capability is not set. The negative/unset value of {@code useNewWDA} - * capability has no effect prior to xcuitest driver version 2.35.0. - */ - String USE_NEW_WDA = "useNewWDA"; - - /** - * Time, in ms, to wait for WebDriverAgent to be pingable. Defaults to 60000ms. - */ - String WDA_LAUNCH_TIMEOUT = "wdaLaunchTimeout"; - - /** - * Timeout, in ms, for waiting for a response from WebDriverAgent. Defaults to 240000ms. - */ - String WDA_CONNECTION_TIMEOUT = "wdaConnectionTimeout"; - - /** - * Apple developer team identifier string. - * Must be used in conjunction with xcodeSigningId to take effect. - * e.g., JWL241K123 - */ - String XCODE_ORG_ID = "xcodeOrgId"; - - /** - * String representing a signing certificate. - * Must be used in conjunction with xcodeOrgId. - * This is usually just iPhone Developer, so the default (if not included) is iPhone Developer - */ - String XCODE_SIGNING_ID = "xcodeSigningId"; - - /** - * Bundle id to update WDA to before building and launching on real devices. - * This bundle id must be associated with a valid provisioning profile. - * e.g., io.appium.WebDriverAgentRunner. - */ - String UPDATE_WDA_BUNDLEID = "updatedWDABundleId"; - - /** - * By default application installation is not skipped if newer or the same version of this app is already present on - * the device under test. Setting this option to {@code false} will enforce Appium to always skip the current - * application build. Defaults to {@code true}. - * - * @since 4.19.0 - */ - String ENFORCE_APP_INSTALL = "enforceAppInstall"; - - /** - * Whether to perform reset on test session finish (false) or not (true). - * Keeping this variable set to true and Simulator running - * (the default behaviour since version 1.6.4) may significantly shorten the - * duration of test session initialization. - * Defaults to true. - */ - String RESET_ON_SESSION_START_ONLY = "resetOnSessionStartOnly"; - - /** - * Custom timeout(s) in milliseconds for WDA backend commands execution. - * This might be useful if WDA backend freezes unexpectedly or requires - * too much time to fail and blocks automated test execution. - * The value is expected to be of type string and can either contain - * max milliseconds to wait for each WDA command to be executed before - * terminating the session forcefully or a valid JSON string, - * where keys are internal Appium command names (you can find these in logs, - * look for "Executing command 'command_name'" records) and values are - * timeouts in milliseconds. You can also set the 'default' key to assign - * the timeout for all other commands not explicitly enumerated as JSON keys. - */ - String COMMAND_TIMEOUTS = "commandTimeouts"; - - /** - * Number of times to try to build and launch WebDriverAgent onto the device. - * Defaults to 2. - */ - String WDA_STARTUP_RETRIES = "wdaStartupRetries"; - - /** - * Time, in ms, to wait between tries to build and launch WebDriverAgent. - * Defaults to 10000ms. - */ - String WDA_STARTUP_RETRY_INTERVAL = "wdaStartupRetryInterval"; - - /** - * Set this option to true in order to enable hardware keyboard in Simulator. - * It is set to false by default, because this helps to workaround some XCTest bugs. - */ - String CONNECT_HARDWARE_KEYBOARD = "connectHardwareKeyboard"; - - /** - * Maximum frequency of keystrokes for typing and clear. - * If your tests are failing because of typing errors, you may want to adjust this. - * Defaults to 60 keystrokes per minute. - */ - String MAX_TYPING_FREQUENCY = "maxTypingFrequency"; - - /** - * Use native methods for determining visibility of elements. - * In some cases this takes a long time. - * Setting this capability to false will cause the system to use the position - * and size of elements to make sure they are visible on the screen. - * This can, however, lead to false results in some situations. - * Defaults to false, except iOS 9.3, where it defaults to true. - */ - String SIMPLE_ISVISIBLE_CHECK = "simpleIsVisibleCheck"; - - /** - * Use SSL to download dependencies for WebDriverAgent. Defaults to false. - */ - String USE_CARTHAGE_SSL = "useCarthageSsl"; - - /** - * Use default proxy for test management within WebDriverAgent. - * Setting this to false sometimes helps with socket hangup problems. - * Defaults to true. - */ - String SHOULD_USE_SINGLETON_TESTMANAGER = "shouldUseSingletonTestManager"; - - /** - * Set this to true if you want to start ios_webkit_debug proxy server - * automatically for accessing webviews on iOS. - * The capatibility only works for real device automation. - * Defaults to false. - */ - String START_IWDP = "startIWDP"; - - /** - * Enrolls simulator for touch id. Defaults to false. - */ - String ALLOW_TOUCHID_ENROLL = "allowTouchIdEnroll"; - -} diff --git a/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java b/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java deleted file mode 100644 index 44cc27214..000000000 --- a/src/main/java/io/appium/java_client/remote/MobileCapabilityType.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.remote; - -import org.openqa.selenium.remote.CapabilityType; - -/** - * The list of common capabilities.
- * Read:
- * - * https://appium.io/docs/en/latest/guides/caps/#appium-capabilities - * - * @deprecated This interface will be removed. Use Options instead. - */ -@Deprecated -public interface MobileCapabilityType extends CapabilityType { - - /** - * Which automation engine to use. - */ - String AUTOMATION_NAME = "automationName"; - - /** - * Mobile OS version. - */ - String PLATFORM_VERSION = "platformVersion"; - - /** - * The kind of mobile device or emulator to use. - */ - String DEVICE_NAME = "deviceName"; - - /** - * How long (in seconds) Appium will wait for a new command from the - * client before assuming the client quit and ending the session. - */ - String NEW_COMMAND_TIMEOUT = "newCommandTimeout"; - - /** - * The absolute local path or remote http URL to a {@code .ipa} file (IOS), - * {@code .app} folder (IOS Simulator), {@code .apk} file (Android) or {@code .apks} file (Android App Bundle), - * or a {@code .zip} file containing one of these (for .app, the .app folder must be the root of the zip file). - * Appium will attempt to install this app binary on the appropriate device first. - * Note that this capability is not required for Android if you specify {@code appPackage} - * and {@code appActivity} capabilities (see below). Incompatible with {@code browserName}. See - * - * here - * about {@code .apks} file. - */ - String APP = "app"; - - /** - * Unique device identifier of the connected physical device. - */ - String UDID = "udid"; - - - /** - * Language to set for iOS (XCUITest driver only) and Android. - */ - String LANGUAGE = "language"; - - /** - * Locale to set for iOS (XCUITest driver only) and Android. - * {@code fr_CA} format for iOS. {@code CA} format (country name abbreviation) for Android - */ - String LOCALE = "locale"; - - /** - * (Sim/Emu-only) start in a certain orientation. - */ - String ORIENTATION = "orientation"; - - /** - * Move directly into Webview context. Default false. - */ - String AUTO_WEBVIEW = "autoWebview"; - - /** - * Don't reset app state before this session. See - * - * here - * for more detail. - */ - String NO_RESET = "noReset"; - - /** - * Perform a complete reset. See - * - * here - * for more detail. - */ - String FULL_RESET = "fullReset"; - - /** - * The desired capability which specifies whether to delete any generated files at - * the end of a session (see iOS and Android entries for particulars). - */ - String CLEAR_SYSTEM_FILES = "clearSystemFiles"; - - /** - * Enable or disable the reporting of the timings for various Appium-internal events - * (e.g., the start and end of each command, etc.). Defaults to {@code false}. - * To enable, use {@code true}. The timings are then reported as {@code events} property on response - * to querying the current session. See the - * - * event timing docs for the structure of this response. - */ - String EVENT_TIMINGS = "eventTimings"; - - /** - * (Web and webview only) Enable ChromeDriver's (on Android) - * or Safari's (on iOS) performance logging (default {@code false}). - */ - String ENABLE_PERFORMANCE_LOGGING = "enablePerformanceLogging"; - - - /** - * App or list of apps (as a JSON array) to install prior to running tests. Note that it will not work with - * automationName of Espresso and iOS real devices. - */ - String OTHER_APPS = "otherApps"; - - /** - * When a find operation fails, print the current page source. Defaults to false. - */ - String PRINT_PAGE_SOURCE_ON_FIND_FAILURE = "printPageSourceOnFindFailure"; -} diff --git a/src/main/java/io/appium/java_client/remote/MobileOptions.java b/src/main/java/io/appium/java_client/remote/MobileOptions.java deleted file mode 100644 index 98bd098b7..000000000 --- a/src/main/java/io/appium/java_client/remote/MobileOptions.java +++ /dev/null @@ -1,512 +0,0 @@ -/* - * 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.remote; - -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.remote.CapabilityType; - -import java.net.URL; -import java.time.Duration; - -/** - * Use the specific options class for your driver, - * for example XCUITestOptions or UiAutomator2Options. - * - * @param The child class for a proper chaining. - */ -@Deprecated -public class MobileOptions> extends MutableCapabilities { - - /** - * Creates new instance with no preset capabilities. - */ - public MobileOptions() { - } - - /** - * Creates new instance with provided capabilities capabilities. - * - * @param source is Capabilities instance to merge into new instance - */ - public MobileOptions(Capabilities source) { - super(source); - } - - /** - * Set the kind of mobile device or emulator to use. - * - * @param platform the kind of mobile device or emulator to use. - * @return this MobileOptions, for chaining. - * @see org.openqa.selenium.remote.CapabilityType#PLATFORM_NAME - */ - public T setPlatformName(String platform) { - return amend(CapabilityType.PLATFORM_NAME, platform); - } - - /** - * Set the absolute local path for the location of the App. - * The or remote http URL to a {@code .ipa} file (IOS), - * - * @param path is a String representing the location of the App - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#APP - */ - public T setApp(String path) { - return amend(MobileCapabilityType.APP, path); - } - - /** - * Set the remote http URL for the location of the App. - * - * @param url is the URL representing the location of the App - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#APP - */ - public T setApp(URL url) { - return setApp(url.toString()); - } - - /** - * Get the app location. - * - * @return String representing app location - * @see MobileCapabilityType#APP - */ - public String getApp() { - return (String) getCapability(MobileCapabilityType.APP); - } - - /** - * Set the automation engine to use. - * - * @param name is the name of the automation engine - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTOMATION_NAME - */ - public T setAutomationName(String name) { - return amend(MobileCapabilityType.AUTOMATION_NAME, name); - } - - /** - * Get the automation engine to use. - * - * @return String representing the name of the automation engine - * @see MobileCapabilityType#AUTOMATION_NAME - */ - public String getAutomationName() { - return (String) getCapability(MobileCapabilityType.AUTOMATION_NAME); - } - - /** - * Set the app to move directly into Webview context. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTO_WEBVIEW - */ - public T setAutoWebview() { - return setAutoWebview(true); - } - - /** - * Set whether the app moves directly into Webview context. - * - * @param bool is whether the app moves directly into Webview context. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#AUTO_WEBVIEW - */ - public T setAutoWebview(boolean bool) { - return amend(MobileCapabilityType.AUTO_WEBVIEW, bool); - } - - /** - * Get whether the app moves directly into Webview context. - * - * @return true if app moves directly into Webview context. - * @see MobileCapabilityType#AUTO_WEBVIEW - */ - public boolean doesAutoWebview() { - return (boolean) getCapability(MobileCapabilityType.AUTO_WEBVIEW); - } - - /** - * Set the app to delete any generated files at the end of a session. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES - */ - public T setClearSystemFiles() { - return setClearSystemFiles(true); - } - - /** - * Set whether the app deletes generated files at the end of a session. - * - * @param bool is whether the app deletes generated files at the end of a session. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES - */ - public T setClearSystemFiles(boolean bool) { - return amend(MobileCapabilityType.CLEAR_SYSTEM_FILES, bool); - } - - /** - * Get whether the app deletes generated files at the end of a session. - * - * @return true if the app deletes generated files at the end of a session. - * @see MobileCapabilityType#CLEAR_SYSTEM_FILES - */ - public boolean doesClearSystemFiles() { - return (boolean) getCapability(MobileCapabilityType.CLEAR_SYSTEM_FILES); - } - - /** - * Set the name of the device. - * - * @param deviceName is the name of the device. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#DEVICE_NAME - */ - public T setDeviceName(String deviceName) { - return amend(MobileCapabilityType.DEVICE_NAME, deviceName); - } - - /** - * Get the name of the device. - * - * @return String representing the name of the device. - * @see MobileCapabilityType#DEVICE_NAME - */ - public String getDeviceName() { - return (String) getCapability(MobileCapabilityType.DEVICE_NAME); - } - - /** - * Set the app to enable performance logging. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING - */ - public T setEnablePerformanceLogging() { - return setEnablePerformanceLogging(true); - } - - /** - * Set whether the app logs performance. - * - * @param bool is whether the app logs performance. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING - */ - public T setEnablePerformanceLogging(boolean bool) { - return amend(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING, bool); - } - - /** - * Get the app logs performance. - * - * @return true if the app logs performance. - * @see MobileCapabilityType#ENABLE_PERFORMANCE_LOGGING - */ - public boolean isEnablePerformanceLogging() { - return (boolean) getCapability(MobileCapabilityType.ENABLE_PERFORMANCE_LOGGING); - } - - /** - * Set the app to report the timings for various Appium-internal events. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public T setEventTimings() { - return setEventTimings(true); - } - - /** - * Set whether the app reports the timings for various Appium-internal events. - * - * @param bool is whether the app enables event timings. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public T setEventTimings(boolean bool) { - return amend(MobileCapabilityType.EVENT_TIMINGS, bool); - } - - /** - * Get whether the app reports the timings for various Appium-internal events. - * - * @return true if the app reports event timings. - * @see MobileCapabilityType#EVENT_TIMINGS - */ - public boolean doesEventTimings() { - return (boolean) getCapability(MobileCapabilityType.EVENT_TIMINGS); - } - - /** - * Set the app to do a full reset. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#FULL_RESET - */ - public T setFullReset() { - return setFullReset(true); - } - - /** - * Set whether the app does a full reset. - * - * @param bool is whether the app does a full reset. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#FULL_RESET - */ - public T setFullReset(boolean bool) { - return amend(MobileCapabilityType.FULL_RESET, bool); - } - - /** - * Get whether the app does a full reset. - * - * @return true if the app does a full reset. - * @see MobileCapabilityType#FULL_RESET - */ - public boolean doesFullReset() { - return (boolean) getCapability(MobileCapabilityType.FULL_RESET); - } - - /** - * Set language abbreviation for use in session. - * - * @param language is the language abbreviation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#LANGUAGE - */ - public T setLanguage(String language) { - return amend(MobileCapabilityType.LANGUAGE, language); - } - - /** - * Get language abbreviation for use in session. - * - * @return String representing the language abbreviation. - * @see MobileCapabilityType#LANGUAGE - */ - public String getLanguage() { - return (String) getCapability(MobileCapabilityType.LANGUAGE); - } - - /** - * Set locale abbreviation for use in session. - * - * @param locale is the locale abbreviation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#LOCALE - */ - public T setLocale(String locale) { - return amend(MobileCapabilityType.LOCALE, locale); - } - - /** - * Get locale abbreviation for use in session. - * - * @return String representing the locale abbreviation. - * @see MobileCapabilityType#LOCALE - */ - public String getLocale() { - return (String) getCapability(MobileCapabilityType.LOCALE); - } - - /** - * Set the timeout for new commands. - * - * @param duration is the allowed time before seeing a new command. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT - */ - public T setNewCommandTimeout(Duration duration) { - return amend(MobileCapabilityType.NEW_COMMAND_TIMEOUT, duration.getSeconds()); - } - - /** - * Get the timeout for new commands. - * - * @return allowed time before seeing a new command. - * @see MobileCapabilityType#NEW_COMMAND_TIMEOUT - */ - public Duration getNewCommandTimeout() { - Object duration = getCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT); - return Duration.ofSeconds(Long.parseLong("" + duration)); - } - - /** - * Set the app not to do a reset. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NO_RESET - */ - public T setNoReset() { - return setNoReset(true); - } - - /** - * Set whether the app does not do a reset. - * - * @param bool is whether the app does not do a reset. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#NO_RESET - */ - public T setNoReset(boolean bool) { - return amend(MobileCapabilityType.NO_RESET, bool); - } - - /** - * Get whether the app does not do a reset. - * - * @return true if the app does not do a reset. - * @see MobileCapabilityType#NO_RESET - */ - public boolean doesNoReset() { - return (boolean) getCapability(MobileCapabilityType.NO_RESET); - } - - /** - * Set the orientation of the screen. - * - * @param orientation is the screen orientation. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#ORIENTATION - */ - public T setOrientation(ScreenOrientation orientation) { - return amend(MobileCapabilityType.ORIENTATION, orientation); - } - - /** - * Get the orientation of the screen. - * - * @return ScreenOrientation of the app. - * @see MobileCapabilityType#ORIENTATION - */ - public ScreenOrientation getOrientation() { - return (ScreenOrientation) getCapability(MobileCapabilityType.ORIENTATION); - } - - /** - * Set the location of the app(s) to install before running a test. - * - * @param apps is the apps to install. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#OTHER_APPS - */ - public T setOtherApps(String apps) { - return amend(MobileCapabilityType.OTHER_APPS, apps); - } - - /** - * Get the list of apps to install before running a test. - * - * @return String of apps to install. - * @see MobileCapabilityType#OTHER_APPS - */ - public String getOtherApps() { - return (String) getCapability(MobileCapabilityType.OTHER_APPS); - } - - /** - * Set the version of the platform. - * - * @param version is the platform version. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PLATFORM_VERSION - */ - public T setPlatformVersion(String version) { - return amend(MobileCapabilityType.PLATFORM_VERSION, version); - } - - /** - * Get the version of the platform. - * - * @return String representing the platform version. - * @see MobileCapabilityType#PLATFORM_VERSION - */ - public String getPlatformVersion() { - return (String) getCapability(MobileCapabilityType.PLATFORM_VERSION); - } - - /** - * Set the app to print page source when a find operation fails. - * - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public T setPrintPageSourceOnFindFailure() { - return setPrintPageSourceOnFindFailure(true); - } - - /** - * Set whether the app to print page source when a find operation fails. - * - * @param bool is whether to print page source. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public T setPrintPageSourceOnFindFailure(boolean bool) { - return amend(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE, bool); - } - - /** - * Get whether the app to print page source when a find operation fails. - * - * @return true if app prints page source. - * @see MobileCapabilityType#PRINT_PAGE_SOURCE_ON_FIND_FAILURE - */ - public boolean doesPrintPageSourceOnFindFailure() { - return (boolean) getCapability(MobileCapabilityType.PRINT_PAGE_SOURCE_ON_FIND_FAILURE); - } - - /** - * Set the id of the device. - * - * @param id is the unique device identifier. - * @return this MobileOptions, for chaining. - * @see MobileCapabilityType#UDID - */ - public T setUdid(String id) { - return amend(MobileCapabilityType.UDID, id); - } - - /** - * Get the id of the device. - * - * @return String representing the unique device identifier. - * @see MobileCapabilityType#UDID - */ - public String getUdid() { - return (String) getCapability(MobileCapabilityType.UDID); - } - - @Override - public T merge(Capabilities extraCapabilities) { - super.merge(extraCapabilities); - return (T) this; - } - - protected T amend(String optionName, Object value) { - setCapability(optionName, value); - return (T) this; - } -} diff --git a/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java b/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java deleted file mode 100644 index 1657103a6..000000000 --- a/src/main/java/io/appium/java_client/remote/YouiEngineCapabilityType.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.appium.java_client.remote; - -import org.openqa.selenium.remote.CapabilityType; - -/** - * The list of youiengine-specific capabilities. - * - * @deprecated This interface will be removed. Use Options instead. - */ -@Deprecated -public interface YouiEngineCapabilityType extends CapabilityType { - /** - * IP address of the app to execute commands against. - */ - String APP_ADDRESS = "youiEngineAppAddress"; -} diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index f37b89e29..fa2ed6584 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -19,7 +19,6 @@ import com.google.common.annotations.VisibleForTesting; import io.appium.java_client.internal.ReflectionHelpers; import lombok.SneakyThrows; -import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.net.UrlChecker; import org.openqa.selenium.os.CommandLine; import org.openqa.selenium.remote.service.DriverService; @@ -47,6 +46,7 @@ import java.util.regex.Pattern; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.isNullOrEmpty; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP6_ADDRESS; import static org.slf4j.event.Level.DEBUG; @@ -183,7 +183,7 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { } catch (Exception e) { final Optional output = Optional.ofNullable(process) .map(CommandLine::getStdOut) - .filter(o -> !StringUtils.isBlank(o)); + .filter(o -> !isNullOrEmpty(o)); destroyProcess(); List errorLines = new ArrayList<>(); errorLines.add("The local appium server has not been started"); @@ -200,7 +200,7 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { errorLines.add(String.format("Arguments: %s", nodeJSArgs)); output.ifPresent(o -> errorLines.add(String.format("Output: %s", o))); throw new AppiumServerHasNotBeenStartedLocallyException( - StringUtils.joinWith("\n", errorLines), e + String.join("\n", errorLines), e ); } } finally { diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 774399a9c..a8879cc36 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -19,16 +19,14 @@ import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import io.appium.java_client.android.options.context.SupportsChromedriverExecutableOption; +import io.appium.java_client.android.options.signing.SupportsKeystoreOptions; import io.appium.java_client.internal.ReflectionHelpers; -import io.appium.java_client.remote.AndroidMobileCapabilityType; import io.appium.java_client.remote.MobileBrowserType; -import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.remote.options.SupportsAppOption; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.appium.java_client.service.local.flags.ServerArgument; import lombok.SneakyThrows; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.SystemUtils; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.os.ExecutableFinder; @@ -52,6 +50,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.isNullOrEmpty; import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; public final class AppiumServiceBuilder @@ -86,8 +85,11 @@ public final class AppiumServiceBuilder private static final Function NODE_JS_NOT_EXIST_ERROR = fullPath -> String.format("The main NodeJS executable does not exist at '%s'", fullPath.getAbsolutePath()); - private static final List PATH_CAPABILITIES = ImmutableList.of(AndroidMobileCapabilityType.KEYSTORE_PATH, - AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, MobileCapabilityType.APP); + private static final List PATH_CAPABILITIES = List.of( + SupportsChromedriverExecutableOption.CHROMEDRIVER_EXECUTABLE_OPTION, + SupportsKeystoreOptions.KEYSTORE_PATH_OPTION, + SupportsAppOption.APP_OPTION + ); public AppiumServiceBuilder() { usingPort(DEFAULT_APPIUM_PORT); @@ -142,14 +144,14 @@ private static File findNpm() { private static File findMainScript() { File npm = findNpm(); - List cmdLine = SystemUtils.IS_OS_WINDOWS + List cmdLine = System.getProperty("os.name").toLowerCase().contains("win") // npm is a batch script, so on windows we need to use cmd.exe in order to execute it ? Arrays.asList("cmd.exe", "/c", String.format("\"%s\" root -g", npm.getAbsolutePath())) : Arrays.asList(npm.getAbsolutePath(), "root", "-g"); ProcessBuilder pb = new ProcessBuilder(cmdLine); String nodeModulesRoot; try { - nodeModulesRoot = IOUtils.toString(pb.start().getInputStream(), StandardCharsets.UTF_8).trim(); + nodeModulesRoot = new String(pb.start().getInputStream().readAllBytes(), StandardCharsets.UTF_8).trim(); } catch (IOException e) { throw new InvalidServerInstanceException( "Cannot retrieve the path to the folder where NodeJS modules are located", e); @@ -282,10 +284,10 @@ public AppiumServiceBuilder withIPAddress(String ipAddress) { @Nullable private static File loadPathFromEnv(String envVarName) { String fullPath = System.getProperty(envVarName); - if (StringUtils.isBlank(fullPath)) { + if (isNullOrEmpty(fullPath)) { fullPath = System.getenv(envVarName); } - return StringUtils.isBlank(fullPath) ? null : new File(fullPath); + return isNullOrEmpty(fullPath) ? null : new File(fullPath); } private void loadPathToMainScript() { @@ -362,7 +364,7 @@ protected ImmutableList createArgs() { argList.add("--port"); argList.add(String.valueOf(getPort())); - if (StringUtils.isBlank(ipAddress)) { + if (isNullOrEmpty(ipAddress)) { ipAddress = BROADCAST_IP4_ADDRESS; } argList.add("--address"); @@ -378,12 +380,12 @@ protected ImmutableList createArgs() { for (Map.Entry entry : entries) { String argument = entry.getKey(); String value = entry.getValue(); - if (StringUtils.isBlank(argument) || value == null) { + if (isNullOrEmpty(argument) || value == null) { continue; } argList.add(argument); - if (!StringUtils.isBlank(value)) { + if (!isNullOrEmpty(value)) { argList.add(value); } } diff --git a/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java b/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java index 19b69c38c..8bf2b9679 100644 --- a/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java +++ b/src/main/java/io/appium/java_client/service/local/flags/GeneralServerFlag.java @@ -38,15 +38,6 @@ public enum GeneralServerFlag implements ServerArgument { * Enables session override (clobbering). Default: false */ SESSION_OVERRIDE("--session-override"), - /** - * Pre-launch the application before allowing the first session - * (Requires –app and, for Android, –app-pkg and –app-activity). - * Default: false - * - * @deprecated This argument has been removed from Appium 2.0 - */ - @Deprecated - PRE_LAUNCH("--pre-launch"), /** * The message log level to be shown. * Sample: --log-level debug diff --git a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java index 99f16d8d3..33c5d8aa6 100644 --- a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java +++ b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java @@ -16,16 +16,16 @@ package io.appium.java_client.ws; -import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.WebSocket; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.net.URI; -import java.time.Duration; import java.util.List; +import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; @@ -38,6 +38,12 @@ public class StringWebSocketClient implements WebSocket.Listener, private volatile boolean isListening = false; + private final WeakReference httpClient; + + public StringWebSocketClient(HttpClient httpClient) { + this.httpClient = new WeakReference<>(httpClient); + } + private URI endpoint; private void setEndpoint(URI endpoint) { @@ -64,26 +70,31 @@ public void connect(URI endpoint) { return; } - ClientConfig clientConfig = ClientConfig.defaultConfig() - .readTimeout(Duration.ZERO) - .baseUri(endpoint); // To avoid NPE in org.openqa.selenium.remote.http.netty.NettyMessages (line 78) - HttpClient client = HttpClient.Factory.createDefault().createClient(clientConfig); HttpRequest request = new HttpRequest(HttpMethod.GET, endpoint.toString()); - client.openSocket(request, this); + Objects.requireNonNull(httpClient.get()).openSocket(request, this); onOpen(); setEndpoint(endpoint); } + /** + * The callback method invoked on websocket opening. + */ public void onOpen() { - getConnectionHandlers().forEach(Runnable::run); - isListening = true; + try { + getConnectionHandlers().forEach(Runnable::run); + } finally { + isListening = true; + } } @Override public void onClose(int code, String reason) { - getDisconnectionHandlers().forEach(Runnable::run); - isListening = false; + try { + getDisconnectionHandlers().forEach(Runnable::run); + } finally { + isListening = false; + } } @Override 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 259dd0d4d..1e0bff096 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -16,16 +16,15 @@ package io.appium.java_client.android; +import io.appium.java_client.android.options.UiAutomator2Options; 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.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; @@ -53,11 +52,9 @@ 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); + driver = new AndroidDriver(service.getUrl(), new UiAutomator2Options() + .withBrowserName(MobileBrowserType.CHROME) + .setDeviceName("Android Emulator")); //This time out is set because test can be run on slow Android SDK emulator PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } diff --git a/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java b/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java index 7b1eec03a..3d90540a4 100644 --- a/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java +++ b/src/test/java/io/appium/java_client/internal/AppiumUserAgentFilterTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.internal; -import io.appium.java_client.AppiumUserAgentFilter; +import io.appium.java_client.internal.filters.AppiumUserAgentFilter; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; diff --git a/src/test/java/io/appium/java_client/internal/ConfigTest.java b/src/test/java/io/appium/java_client/internal/ConfigTest.java index 46651eac6..f509a4d23 100644 --- a/src/test/java/io/appium/java_client/internal/ConfigTest.java +++ b/src/test/java/io/appium/java_client/internal/ConfigTest.java @@ -1,6 +1,6 @@ package io.appium.java_client.internal; -import io.appium.java_client.AppiumUserAgentFilter; +import io.appium.java_client.internal.filters.AppiumUserAgentFilter; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; diff --git a/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java b/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java deleted file mode 100644 index 13faeb583..000000000 --- a/src/test/java/io/appium/java_client/remote/MobileOptionsTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.remote; - -import org.junit.jupiter.api.Test; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.ScreenOrientation; - -import java.net.MalformedURLException; -import java.net.URL; -import java.time.Duration; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MobileOptionsTest { - private MobileOptions mobileOptions = new MobileOptions<>(); - - @Test - public void acceptsExistingCapabilities() { - MutableCapabilities capabilities = new MutableCapabilities(); - capabilities.setCapability("deviceName", "Pixel"); - capabilities.setCapability("platformVersion", "10"); - capabilities.setCapability("newCommandTimeout", 60); - - mobileOptions = new MobileOptions<>(capabilities); - - assertEquals("Pixel", mobileOptions.getDeviceName()); - assertEquals("10", mobileOptions.getPlatformVersion()); - assertEquals(Duration.ofSeconds(60), mobileOptions.getNewCommandTimeout()); - } - - @Test - public void acceptsMobileCapabilities() throws MalformedURLException { - mobileOptions.setApp(new URL("http://example.com/myapp.apk")) - .setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2) - .setPlatformVersion("10") - .setDeviceName("Pixel") - .setOtherApps("/path/to/app.apk") - .setLocale("fr_CA") - .setUdid("1ae203187fc012g") - .setOrientation(ScreenOrientation.LANDSCAPE) - .setNewCommandTimeout(Duration.ofSeconds(60)) - .setLanguage("fr"); - - assertEquals("http://example.com/myapp.apk", mobileOptions.getApp()); - assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, mobileOptions.getAutomationName()); - assertEquals("10", mobileOptions.getPlatformVersion()); - assertEquals("Pixel", mobileOptions.getDeviceName()); - assertEquals("/path/to/app.apk", mobileOptions.getOtherApps()); - assertEquals("fr_CA", mobileOptions.getLocale()); - assertEquals("1ae203187fc012g", mobileOptions.getUdid()); - assertEquals(ScreenOrientation.LANDSCAPE, mobileOptions.getOrientation()); - assertEquals(Duration.ofSeconds(60), mobileOptions.getNewCommandTimeout()); - assertEquals("fr", mobileOptions.getLanguage()); - } - - @Test - public void acceptsMobileBooleanCapabilityDefaults() { - mobileOptions.setClearSystemFiles() - .setAutoWebview() - .setEnablePerformanceLogging() - .setEventTimings() - .setAutoWebview() - .setFullReset() - .setPrintPageSourceOnFindFailure(); - - assertTrue(mobileOptions.doesClearSystemFiles()); - assertTrue(mobileOptions.doesAutoWebview()); - assertTrue(mobileOptions.isEnablePerformanceLogging()); - assertTrue(mobileOptions.doesEventTimings()); - assertTrue(mobileOptions.doesAutoWebview()); - assertTrue(mobileOptions.doesFullReset()); - assertTrue(mobileOptions.doesPrintPageSourceOnFindFailure()); - } - - @Test - public void setsMobileBooleanCapabilities() { - mobileOptions.setClearSystemFiles(false) - .setAutoWebview(false) - .setEnablePerformanceLogging(false) - .setEventTimings(false) - .setAutoWebview(false) - .setFullReset(false) - .setPrintPageSourceOnFindFailure(false); - - assertFalse(mobileOptions.doesClearSystemFiles()); - assertFalse(mobileOptions.doesAutoWebview()); - assertFalse(mobileOptions.isEnablePerformanceLogging()); - assertFalse(mobileOptions.doesEventTimings()); - assertFalse(mobileOptions.doesAutoWebview()); - assertFalse(mobileOptions.doesFullReset()); - assertFalse(mobileOptions.doesPrintPageSourceOnFindFailure()); - } -} diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index 36518f4ed..157077f88 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -19,7 +19,6 @@ import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.github.bonigarcia.wdm.WebDriverManager; @@ -29,10 +28,14 @@ import java.time.Duration; import static io.appium.java_client.TestResources.apiDemosApk; +import static io.appium.java_client.remote.options.SupportsAppOption.APP_OPTION; +import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; +import static io.appium.java_client.remote.options.SupportsDeviceNameOption.DEVICE_NAME_OPTION; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; class StartingAppLocallyAndroidTest { @@ -46,11 +49,11 @@ void startingAndroidAppWithCapabilitiesOnlyTest() { Capabilities caps = driver.getCapabilities(); assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( - String.valueOf(caps.getCapability(MobileCapabilityType.PLATFORM_NAME))) + String.valueOf(caps.getCapability(PLATFORM_NAME))) ); - assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(MobileCapabilityType.AUTOMATION_NAME)); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); - assertEquals(apiDemosApk().toAbsolutePath().toString(), caps.getCapability(MobileCapabilityType.APP)); + assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(AUTOMATION_NAME_OPTION)); + assertNotNull(caps.getCapability(DEVICE_NAME_OPTION)); + assertEquals(apiDemosApk().toAbsolutePath().toString(), caps.getCapability(APP_OPTION)); } finally { driver.quit(); } @@ -70,9 +73,9 @@ void startingAndroidAppWithCapabilitiesAndServiceTest() { Capabilities caps = driver.getCapabilities(); assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( - String.valueOf(caps.getCapability(MobileCapabilityType.PLATFORM_NAME))) + String.valueOf(caps.getCapability(PLATFORM_NAME))) ); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertNotNull(caps.getCapability(DEVICE_NAME_OPTION)); } finally { driver.quit(); } @@ -105,9 +108,9 @@ void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { Capabilities caps = driver.getCapabilities(); assertTrue(MobilePlatform.ANDROID.equalsIgnoreCase( - String.valueOf(caps.getCapability(MobileCapabilityType.PLATFORM_NAME))) + String.valueOf(caps.getCapability(PLATFORM_NAME))) ); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertNotNull(caps.getCapability(DEVICE_NAME_OPTION)); } finally { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index 3ce6bd9af..5041231ec 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -20,7 +20,6 @@ import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.AutomationName; -import io.appium.java_client.remote.MobileCapabilityType; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; import org.junit.jupiter.api.Test; @@ -28,10 +27,12 @@ import org.openqa.selenium.Platform; import static io.appium.java_client.TestResources.uiCatalogAppZip; +import static io.appium.java_client.remote.options.SupportsDeviceNameOption.DEVICE_NAME_OPTION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; class StartingAppLocallyIosTest { @Test @@ -72,9 +73,9 @@ void startingIOSAppWithCapabilitiesAndServiceTest() { IOSDriver driver = new IOSDriver(builder, options); try { Capabilities caps = driver.getCapabilities(); - assertTrue(caps.getCapability(MobileCapabilityType.PLATFORM_NAME) + assertTrue(caps.getCapability(PLATFORM_NAME) .toString().equalsIgnoreCase(MobilePlatform.IOS)); - assertNotNull(caps.getCapability(MobileCapabilityType.DEVICE_NAME)); + assertNotNull(caps.getCapability(DEVICE_NAME_OPTION)); } finally { driver.quit(); } From 269972643a0ca095b9e42fd7131319458384082f Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 13 Oct 2023 13:25:13 +0200 Subject: [PATCH 272/501] docs: Add 8 to 9 migration guide (#2039) --- README.md | 10 +++++-- docs/v8-to-v9-migration-guide.md | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 docs/v8-to-v9-migration-guide.md diff --git a/README.md b/README.md index 97ecb5017..892af6456 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,15 @@ This is the Java language bindings for writing Appium Tests that conform to [WebDriver Protocol](https://w3c.github.io/webdriver/) -## v8 Migration +## v8 to v9 Migration + +Since v9 the client only supports Java 11 and above. +Follow the [v8 to v9 Migration Guide](./docs/v8-to-v9-migration-guide.md) in order to streamline the migration process. + +## v7 to v8 Migration Since version 8 Appium Java Client had several major changes, which might require to -update your client code. Make sure to follow the [v7 to v8 Migration Guide](https://github.com/appium/java-client/blob/master/docs/v7-to-v8-migration-guide.md) +update your client code. Make sure to follow the [v7 to v8 Migration Guide](./docs/v7-to-v8-migration-guide.md) in order to streamline the migration process. ## Add Appium java client to your test framework @@ -90,6 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client --------------------|----------------- + `9.0.0` | `4.14.1` `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` diff --git a/docs/v8-to-v9-migration-guide.md b/docs/v8-to-v9-migration-guide.md new file mode 100644 index 000000000..a0b57cd35 --- /dev/null +++ b/docs/v8-to-v9-migration-guide.md @@ -0,0 +1,46 @@ +This is the list of main changes between major versions 8 and 9 of Appium +java client. This list should help you to successfully migrate your +existing automated tests codebase. + + +## The support for Java compilers below version 11 has been dropped + +- The minimum supported Java version is now 11. The library won't work +with Java compilers below this version. + +## The minimum supported Selenium version is set to 4.14.1 + +- Selenium versions below 4.14.1 won't work with Appium java client 9+. +Check the [Compatibility Matrix](../README.md#compatibility-matrix) for more +details about versions compatibility. + +## Removed previously deprecated items + +- `MobileBy` class has been removed. Use +[AppiumBy](../src/main/java/io/appium/java_client/AppiumBy.java) instead +- `launchApp`, `resetApp` and `closeApp` methods along with their +`SupportsLegacyAppManagement` container. +Use [the corresponding extension methods](https://github.com/appium/appium/issues/15807) instead. +- `WindowsBy` class and related location strategies. +- `ByAll` class has been removed in favour of the same class from Selenium lib. +- `AndroidMobileCapabilityType` interface. Use +[UIAutomator2 driver options](../src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java) +or [Espresso driver options](../src/main/java/io/appium/java_client/android/options/EspressoOptions.java) instead. +- `IOSMobileCapabilityType` interface. Use +[XCUITest driver options](../src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java) instead. +- `MobileCapabilityType` interface. Use +[driver options](../src/main/java/io/appium/java_client/remote/options/BaseOptions.java) instead. +- `MobileOptions` class. Use +[driver options](../src/main/java/io/appium/java_client/remote/options/BaseOptions.java) instead. +- `YouiEngineCapabilityType` interface. Use +[driver options](../src/main/java/io/appium/java_client/remote/options/BaseOptions.java) instead. +- Several misspelled methods. Use properly spelled alternatives instead. +- `startActivity` method from AndroidDriver. Use +[mobile: startActivity](https://github.com/appium/appium-uiautomator2-driver#mobile-startactivity) +extension method instead. +- `APPIUM` constant from the AutomationName interface. It is not needed anymore. +- `PRE_LAUNCH` value from the GeneralServerFlag enum. It is not needed anymore. + +## Moved items + +- `AppiumUserAgentFilter` class to `io.appium.java_client.internal.filters` package. From d7b3be4264b530ca66bc44dcf3ef99c8b372de5d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 13 Oct 2023 14:59:16 +0300 Subject: [PATCH 273/501] ci: Use LTS Java in CI (#2040) --- .github/workflows/gradle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a7094028a..5d15dfbc2 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -35,10 +35,10 @@ jobs: # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available platform: macos-12 e2e-tests: ios - - java: 15 + - java: 17 platform: macos-latest e2e-tests: android - - java: 17 + - java: 21 platform: ubuntu-latest fail-fast: false From 0701528838f38f103ff303e095e30c422487c749 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 13 Oct 2023 19:00:00 +0300 Subject: [PATCH 274/501] test: Align Selenium version in test dependencies (#2042) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 05e17653f..a5c3c2681 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { exclude group: 'org.seleniumhq.selenium' } - testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.13.0') + testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.14.1') testImplementation 'org.seleniumhq.selenium:selenium-api' testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' testImplementation 'org.seleniumhq.selenium:selenium-support' From 37ad22457bd68c2a34fa79a8ffc4e8c6275c7b8f Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Sat, 14 Oct 2023 16:24:25 +0530 Subject: [PATCH 275/501] release: v9.0.0 and update release notes (#2041) --- CHANGELOG.md | 24 ++++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 607a44c86..a16add346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.0.0_ +- **[DOCUMENTATION]** + - Add 8 to 9 migration guide. [#2039](https://github.com/appium/java-client/pull/2039) +- **[BREAKING CHANGE]** [#2036](https://github.com/appium/java-client/pull/2036) + - Set minimum Java version to 11. + - The previously deprecated MobileBy class has been removed. Use AppiumBy instead. + - The previously deprecated launchApp, resetApp and closeApp methods have been removed. Use extension methods instead. + - The previously deprecated WindowsBy class and related location strategies have been removed. + - The previously deprecated ByAll class has been removed in favour of the Selenium one. + - The previously deprecated AndroidMobileCapabilityType interface has been removed. Use driver options instead + - The previously deprecated IOSMobileCapabilityType interface has been removed. Use driver options instead + - The previously deprecated MobileCapabilityType interface has been removed. Use driver options instead + - The previously deprecated MobileOptions class has been removed. Use driver options instead + - The previously deprecated YouiEngineCapabilityType interface has been removed. Use driver options instead + - Removed several misspelled methods. Use properly spelled alternatives instead + - Removed startActivity method from AndroidDriver. Use 'mobile: startActivity' extension method instead + - Removed the previously deprecated APPIUM constant from the AutomationName interface + - Removed the previously deprecated PRE_LAUNCH value from the GeneralServerFlag enum + - Moved AppiumUserAgentFilter class to io.appium.java_client.internal.filters package +- **[REFACTOR]** + - Align Selenium version in test dependencies. [#2042](https://github.com/appium/java-client/pull/2042) +- **[DEPENDENCY CHANGE]** + - Removed dependencies to Apache Commons libraries. + _8.6.0_ - **[BUG FIX]** diff --git a/gradle.properties b/gradle.properties index 9b917685b..6e923bc15 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.14.1 # Please increment the value in a release -appiumClient.version=8.6.0 +appiumClient.version=9.0.0 From 72c33e0f26456cfacec18a51fba72239941a02cf Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 16 Oct 2023 08:33:25 +0200 Subject: [PATCH 276/501] docs: Update gesture shortcut links --- docs/v7-to-v8-migration-guide.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/v7-to-v8-migration-guide.md b/docs/v7-to-v8-migration-guide.md index a0ab9d256..b3be7def0 100644 --- a/docs/v7-to-v8-migration-guide.md +++ b/docs/v7-to-v8-migration-guide.md @@ -86,8 +86,27 @@ or the corresponding extension methods for the driver (if available). Check - https://www.youtube.com/watch?v=oAJ7jwMNFVU - https://appiumpro.com/editions/30-ios-specific-touch-action-methods - - https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/android/android-mobile-gestures.md - - https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios/ios-xctest-mobile-gestures.md + - Android gesture shortcuts: + * [mobile: longClickGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-longclickgesture) + * [mobile: doubleClickGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-doubleclickgesture) + * [mobile: clickGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-clickgesture) + * [mobile: dragGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-draggesture) + * [mobile: flingGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-flinggesture) + * [mobile: pinchOpenGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-pinchopengesture) + * [mobile: pinchCloseGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-pinchclosegesture) + * [mobile: swipeGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-swipegesture) + * [mobile: scrollGesture](https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-scrollgesture) + - iOS gesture shortcuts: + * [mobile: swipe](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-swipe) + * [mobile: scroll](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-scroll) + * [mobile: pinch](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-pinch) + * [mobile: doubleTap](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-doubletap) + * [mobile: touchAndHold](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-touchandhold) + * [mobile: twoFingerTap](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-twofingertap) + * [mobile: tap](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-tap) + * [mobile: dragFromToForDuration](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-dragfromtoforduration) + * [mobile: dragFromToWithVelocity](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-dragfromtowithvelocity) + * [mobile: scrollToElement](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-scrolltoelement) - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api for more details on how to properly apply W3C Actions to your automation context. From 10a3f627515f7db904e11c921dae1dd49453ce9d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 18 Oct 2023 04:29:22 +0300 Subject: [PATCH 277/501] docs: Add missing clients versions to compatibility matrix (#2049) --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 892af6456..c79742f12 100644 --- a/README.md +++ b/README.md @@ -93,13 +93,14 @@ dependencies { ``` ### Compatibility Matrix - Appium Java Client | Selenium client ---------------------|----------------- - `9.0.0` | `4.14.1` - `8.5.0`, `8.5.1` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` - `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` - `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` - `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` + Appium Java Client | Selenium client +---------------------------|----------------- + `9.0.0` | `4.14.1` + N/A | `4.14.0` + `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` + `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` + `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` + `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` #### Why is it so complicated? From a9240e38bfae96069043dec7b43dec53024f0de2 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 18 Oct 2023 12:31:26 +0300 Subject: [PATCH 278/501] refactor: Use Java 9+ APIs instead of outdated/3rd-party APIs (#2048) --- .../io/appium/java_client/AppiumDriver.java | 3 +- .../java_client/AppiumExecutionMethod.java | 3 +- .../java_client/CommandExecutionHelper.java | 4 +- .../appium/java_client/ErrorCodesMobile.java | 5 +- .../appium/java_client/ExecuteCDPCommand.java | 4 +- .../java_client/ExecutesDriverScript.java | 4 +- .../io/appium/java_client/HasAppStrings.java | 20 ++-- .../appium/java_client/HasBrowserCheck.java | 4 +- .../io/appium/java_client/HasDeviceTime.java | 4 +- .../java_client/HasOnScreenKeyboard.java | 6 +- .../java_client/HidesKeyboardWithKeyName.java | 9 +- .../appium/java_client/InteractsWithApps.java | 57 ++++++----- .../io/appium/java_client/LocksDevice.java | 10 +- .../io/appium/java_client/LogsEvents.java | 3 +- .../io/appium/java_client/MobileCommand.java | 82 ++++++++-------- .../appium/java_client/MultiTouchAction.java | 9 +- .../io/appium/java_client/PullsFiles.java | 21 ++-- .../io/appium/java_client/PushesFiles.java | 4 +- .../appium/java_client/ScreenshotState.java | 6 +- .../io/appium/java_client/TouchAction.java | 21 ++-- .../android/AndroidMobileCommandHelper.java | 95 +++++++++---------- .../AndroidStartScreenRecordingOptions.java | 6 +- .../android/AuthenticatesByFinger.java | 5 +- .../android/CanReplaceElementValue.java | 7 +- .../android/HasAndroidClipboard.java | 17 ++-- .../HasSupportedPerformanceDataType.java | 4 +- .../java_client/android/StartsActivity.java | 7 +- .../android/SupportsGpsStateManagement.java | 4 +- .../SupportsNetworkStateManagement.java | 15 ++- .../SupportsSpecialEmulatorCommands.java | 31 +++--- .../AndroidInstallApplicationOptions.java | 14 +-- .../AndroidRemoveApplicationOptions.java | 8 +- .../AndroidTerminateApplicationOptions.java | 6 +- .../connection/HasNetworkConnection.java | 11 +-- .../geolocation/AndroidGeoLocation.java | 6 +- .../SupportsExtendedGeolocationCommands.java | 10 +- .../android/nativekey/PressesKey.java | 5 +- .../options/server/EspressoBuildConfig.java | 2 +- .../java_client/clipboard/HasClipboard.java | 20 ++-- .../driverscripts/ScriptOptions.java | 8 +- .../BaseComparisonOptions.java | 2 +- .../FeaturesMatchingOptions.java | 6 +- .../OccurrenceMatchingOptions.java | 6 +- .../java_client/ios/HasIOSClipboard.java | 6 +- .../io/appium/java_client/ios/IOSDriver.java | 5 +- .../ios/IOSMobileCommandHelper.java | 12 +-- .../ios/IOSStartScreenRecordingOptions.java | 8 +- .../java_client/ios/PerformsTouchID.java | 7 +- .../pagefactory/AppiumFieldDecorator.java | 3 +- .../pagefactory/bys/ContentMappedBy.java | 4 +- .../pagefactory/bys/builder/ByChained.java | 13 ++- .../io/appium/java_client/proxy/Helpers.java | 3 +- .../remote/AppiumCommandExecutor.java | 16 ++-- .../AppiumNewSessionCommandPayload.java | 6 +- .../remote/SupportsContextSwitching.java | 10 +- .../java_client/remote/SupportsRotation.java | 3 +- .../BaseScreenRecordingOptions.java | 4 +- .../BaseStartScreenRecordingOptions.java | 4 +- .../ScreenRecordingUploadOptions.java | 16 ++-- .../local/AppiumDriverLocalService.java | 12 +-- .../service/local/AppiumServiceBuilder.java | 6 +- .../java_client/touch/LongPressOptions.java | 4 +- .../appium/java_client/touch/WaitOptions.java | 4 +- .../touch/offset/ElementOption.java | 4 +- .../AndroidAbilityToUseSupplierTest.java | 6 +- .../android/AndroidDataMatcherTest.java | 8 +- .../android/AndroidDriverTest.java | 6 +- .../java_client/android/AndroidTouchTest.java | 6 +- .../android/AndroidViewMatcherTest.java | 8 +- .../java_client/android/BaseAndroidTest.java | 5 +- .../java_client/android/ClipboardTest.java | 7 +- .../android/OpenNotificationsTest.java | 4 +- .../drivers/options/OptionsBuildingTest.java | 10 +- .../events/stubs/EmptyWebDriver.java | 3 +- .../events/stubs/StubWebElement.java | 3 +- .../appium/java_client/ios/IOSDriverTest.java | 8 +- .../widget/tests/AbstractStubWebDriver.java | 3 +- .../widget/tests/DefaultStubWidget.java | 3 +- .../widget/tests/StubWebElement.java | 11 +-- .../service/local/ServerBuilderTest.java | 4 +- 80 files changed, 387 insertions(+), 432 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 28d0bd529..f4721dbf5 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -16,7 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.internal.ReflectionHelpers; import io.appium.java_client.internal.SessionHelpers; @@ -153,7 +152,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa super(); ReflectionHelpers.setPrivateFieldValue( RemoteWebDriver.class, this, "capabilities", new ImmutableCapabilities( - ImmutableMap.of( + Map.of( PLATFORM_NAME, platformName, APPIUM_PREFIX + AUTOMATION_NAME_OPTION, automationName ) diff --git a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java index 9b9f79cb9..34a848f79 100644 --- a/src/main/java/io/appium/java_client/AppiumExecutionMethod.java +++ b/src/main/java/io/appium/java_client/AppiumExecutionMethod.java @@ -16,7 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.remote.ExecuteMethod; import org.openqa.selenium.remote.Response; @@ -40,7 +39,7 @@ public Object execute(String commandName, Map parameters) { Response response; if (parameters == null || parameters.isEmpty()) { - response = driver.execute(commandName, ImmutableMap.of()); + response = driver.execute(commandName, Map.of()); } else { response = driver.execute(commandName, parameters); } diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 692f7cf0f..7cb011677 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -16,11 +16,9 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; -import java.util.AbstractMap; import java.util.Collections; import java.util.Map; @@ -66,7 +64,7 @@ public static T executeScript(ExecutesMethod executesMethod, String scriptNa public static T executeScript( ExecutesMethod executesMethod, String scriptName, @Nullable Map args ) { - return execute(executesMethod, new AbstractMap.SimpleEntry<>(EXECUTE_SCRIPT, ImmutableMap.of( + return execute(executesMethod, Map.entry(EXECUTE_SCRIPT, Map.of( "script", scriptName, "args", (args == null || args.isEmpty()) ? Collections.emptyList() : Collections.singletonList(args) ))); diff --git a/src/main/java/io/appium/java_client/ErrorCodesMobile.java b/src/main/java/io/appium/java_client/ErrorCodesMobile.java index 473c014d9..c70514b0f 100644 --- a/src/main/java/io/appium/java_client/ErrorCodesMobile.java +++ b/src/main/java/io/appium/java_client/ErrorCodesMobile.java @@ -17,7 +17,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.ErrorCodes; @@ -32,9 +31,7 @@ public class ErrorCodesMobile extends ErrorCodes { public static final int NO_SUCH_CONTEXT = 35; - private static Map statusToState = - ImmutableMap.builder().put(NO_SUCH_CONTEXT, "No such context found") - .build(); + private static Map statusToState = Map.of(NO_SUCH_CONTEXT, "No such context found"); /** * Returns the exception type that corresponds to the given {@code statusCode}. All unrecognized diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java index 8cf09f357..5af5e1f83 100644 --- a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -24,8 +24,8 @@ import java.util.HashMap; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.EXECUTE_GOOGLE_CDP_COMMAND; +import static java.util.Objects.requireNonNull; public interface ExecuteCDPCommand extends ExecutesMethod { @@ -40,7 +40,7 @@ public interface ExecuteCDPCommand extends ExecutesMethod { */ default Map executeCdpCommand(String command, @Nullable Map params) { Map data = new HashMap<>(); - data.put("cmd", checkNotNull(command)); + data.put("cmd", requireNonNull(command)); data.put("params", params == null ? Collections.emptyMap() : params); Response response = execute(EXECUTE_GOOGLE_CDP_COMMAND, data); //noinspection unchecked diff --git a/src/main/java/io/appium/java_client/ExecutesDriverScript.java b/src/main/java/io/appium/java_client/ExecutesDriverScript.java index 997b061a2..1ffebedb9 100644 --- a/src/main/java/io/appium/java_client/ExecutesDriverScript.java +++ b/src/main/java/io/appium/java_client/ExecutesDriverScript.java @@ -24,8 +24,8 @@ import java.util.HashMap; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.EXECUTE_DRIVER_SCRIPT; +import static java.util.Objects.requireNonNull; public interface ExecutesDriverScript extends ExecutesMethod { @@ -46,7 +46,7 @@ public interface ExecutesDriverScript extends ExecutesMethod { */ default ScriptValue executeDriverScript(String script, @Nullable ScriptOptions options) { Map data = new HashMap<>(); - data.put("script", checkNotNull(script)); + data.put("script", requireNonNull(script)); if (options != null) { data.putAll(options.build()); } diff --git a/src/main/java/io/appium/java_client/HasAppStrings.java b/src/main/java/io/appium/java_client/HasAppStrings.java index 439e08bcd..1224b26f9 100644 --- a/src/main/java/io/appium/java_client/HasAppStrings.java +++ b/src/main/java/io/appium/java_client/HasAppStrings.java @@ -16,14 +16,11 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.UnsupportedCommandException; -import java.util.AbstractMap; import java.util.Map; import static io.appium.java_client.MobileCommand.GET_STRINGS; -import static io.appium.java_client.MobileCommand.prepareArguments; public interface HasAppStrings extends ExecutesMethod, CanRememberExtensionPresence { /** @@ -52,14 +49,14 @@ default Map getAppStringMap() { default Map getAppStringMap(String language) { final String extName = "mobile: getAppStrings"; try { - return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "language", language )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback return CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments("language", language)) + Map.entry(GET_STRINGS, Map.of("language", language)) ); } } @@ -75,18 +72,17 @@ default Map getAppStringMap(String language) { */ default Map getAppStringMap(String language, String stringFile) { final String extName = "mobile: getAppStrings"; + Map args = Map.of( + "language", language, + "stringFile", stringFile + ); try { - return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( - "language", language, - "stringFile", stringFile - )); + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - String[] parameters = new String[]{"language", "stringFile"}; - Object[] values = new Object[]{language, stringFile}; return CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments(parameters, values)) + Map.entry(GET_STRINGS, args) ); } } diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java index c5cd62cdb..76094b5ca 100644 --- a/src/main/java/io/appium/java_client/HasBrowserCheck.java +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -6,8 +6,8 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.isNullOrEmpty; +import static java.util.Objects.requireNonNull; public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { /** @@ -20,7 +20,7 @@ default boolean isBrowser() { CapabilityType.BROWSER_NAME, String.class); if (!isNullOrEmpty(browserName)) { try { - return checkNotNull( + return requireNonNull( CommandExecutionHelper.executeScript(this, "return !!window.navigator;") ); } catch (WebDriverException ign) { diff --git a/src/main/java/io/appium/java_client/HasDeviceTime.java b/src/main/java/io/appium/java_client/HasDeviceTime.java index f29e3f3f1..e450f28f1 100644 --- a/src/main/java/io/appium/java_client/HasDeviceTime.java +++ b/src/main/java/io/appium/java_client/HasDeviceTime.java @@ -16,7 +16,7 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; +import java.util.Map; public interface HasDeviceTime extends ExecutesMethod { @@ -32,7 +32,7 @@ public interface HasDeviceTime extends ExecutesMethod { */ default String getDeviceTime(String format) { return CommandExecutionHelper.executeScript( - this, "mobile: getDeviceTime", ImmutableMap.of("format", format) + this, "mobile: getDeviceTime", Map.of("format", format) ); } diff --git a/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java b/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java index d54c4a91f..b242d2b01 100644 --- a/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java +++ b/src/main/java/io/appium/java_client/HasOnScreenKeyboard.java @@ -2,8 +2,8 @@ import org.openqa.selenium.UnsupportedCommandException; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.isKeyboardShownCommand; +import static java.util.Objects.requireNonNull; public interface HasOnScreenKeyboard extends ExecutesMethod, CanRememberExtensionPresence { @@ -16,10 +16,10 @@ public interface HasOnScreenKeyboard extends ExecutesMethod, CanRememberExtensio default boolean isKeyboardShown() { final String extName = "mobile: isKeyboardShown"; try { - return checkNotNull(CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName)); + return requireNonNull(CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName)); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return checkNotNull( + return requireNonNull( CommandExecutionHelper.execute(markExtensionAbsence(extName), isKeyboardShownCommand()) ); } diff --git a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java index 4223ab814..c2a84bb11 100644 --- a/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java +++ b/src/main/java/io/appium/java_client/HidesKeyboardWithKeyName.java @@ -16,10 +16,11 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.UnsupportedCommandException; +import java.util.List; +import java.util.Map; + import static io.appium.java_client.MobileCommand.hideKeyboardCommand; public interface HidesKeyboardWithKeyName extends HidesKeyboard { @@ -37,8 +38,8 @@ public interface HidesKeyboardWithKeyName extends HidesKeyboard { default void hideKeyboard(String keyName) { final String extName = "mobile: hideKeyboard"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( - "keys", ImmutableList.of(keyName) + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( + "keys", List.of(keyName) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index d61f85b19..e254f6aa6 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -28,12 +28,10 @@ import javax.annotation.Nullable; import java.time.Duration; -import java.util.AbstractMap; import java.util.Collections; import java.util.Map; import java.util.Optional; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.ACTIVATE_APP; import static io.appium.java_client.MobileCommand.INSTALL_APP; import static io.appium.java_client.MobileCommand.IS_APP_INSTALLED; @@ -41,6 +39,7 @@ 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.TERMINATE_APP; +import static java.util.Objects.requireNonNull; @SuppressWarnings({"rawtypes", "unchecked"}) public interface InteractsWithApps extends ExecutesMethod, CanRememberExtensionPresence { @@ -75,11 +74,11 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions Map args = ImmutableMap.builder() .put("appPath", appPath) .putAll(Optional.ofNullable(options).map( - opts -> ImmutableMap.of("options", opts.build()) - ).orElseGet(ImmutableMap::of)) + opts -> Map.of("options", opts.build()) + ).orElseGet(Map::of)) .build(); CommandExecutionHelper.execute( - markExtensionAbsence(extName), new AbstractMap.SimpleEntry<>(INSTALL_APP, args) + markExtensionAbsence(extName), Map.entry(INSTALL_APP, args) ); } } @@ -93,18 +92,18 @@ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions default boolean isAppInstalled(String bundleId) { final String extName = "mobile: isAppInstalled"; try { - return checkNotNull( - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + return requireNonNull( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "bundleId", bundleId, "appId", bundleId )) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback - return checkNotNull( + return requireNonNull( CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, ImmutableMap.of("bundleId", bundleId)) + Map.entry(IS_APP_INSTALLED, Map.of("bundleId", bundleId)) ) ); } @@ -121,16 +120,14 @@ default boolean isAppInstalled(String bundleId) { default void runAppInBackground(Duration duration) { final String extName = "mobile: backgroundApp"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "seconds", duration.toMillis() / 1000.0 )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(RUN_APP_IN_BACKGROUND, ImmutableMap.of( - "seconds", duration.toMillis() / 1000.0) - ) + Map.entry(RUN_APP_IN_BACKGROUND, Map.of("seconds", duration.toMillis() / 1000.0)) ); } } @@ -161,7 +158,7 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption .put("appId", bundleId) .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) .build(); - return checkNotNull( + return requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { @@ -169,14 +166,14 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption Map args = ImmutableMap.builder() .put("bundleId", bundleId) .putAll(Optional.ofNullable(options).map( - opts -> ImmutableMap.of("options", opts.build()) - ).orElseGet(ImmutableMap::of)) + opts -> Map.of("options", opts.build()) + ).orElseGet(Map::of)) .build(); //noinspection RedundantCast - return checkNotNull( + return requireNonNull( (Boolean) CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(REMOVE_APP, args) + Map.entry(REMOVE_APP, args) ) ); } @@ -214,11 +211,11 @@ default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptio Map args = ImmutableMap.builder() .put("bundleId", bundleId) .putAll(Optional.ofNullable(options).map( - opts -> ImmutableMap.of("options", opts.build()) - ).orElseGet(ImmutableMap::of)) + opts -> Map.of("options", opts.build()) + ).orElseGet(Map::of)) .build(); CommandExecutionHelper.execute( - markExtensionAbsence(extName), new AbstractMap.SimpleEntry<>(ACTIVATE_APP, args) + markExtensionAbsence(extName), Map.entry(ACTIVATE_APP, args) ); } } @@ -233,10 +230,10 @@ default ApplicationState queryAppState(String bundleId) { final String extName = "mobile: queryAppState"; try { return ApplicationState.ofCode( - checkNotNull( + requireNonNull( CommandExecutionHelper.executeScript( assertExtensionExists(extName), - extName, ImmutableMap.of( + extName, Map.of( "bundleId", bundleId, "appId", bundleId ) @@ -246,10 +243,10 @@ default ApplicationState queryAppState(String bundleId) { } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback return ApplicationState.ofCode( - checkNotNull( + requireNonNull( CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(QUERY_APP_STATE, ImmutableMap.of("bundleId", bundleId)) + Map.entry(QUERY_APP_STATE, Map.of("bundleId", bundleId)) ) ) ); @@ -282,7 +279,7 @@ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplication .put("appId", bundleId) .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) .build(); - return checkNotNull( + return requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { @@ -290,13 +287,13 @@ default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplication Map args = ImmutableMap.builder() .put("bundleId", bundleId) .putAll(Optional.ofNullable(options).map( - opts -> ImmutableMap.of("options", opts.build()) - ).orElseGet(ImmutableMap::of)) + opts -> Map.of("options", opts.build()) + ).orElseGet(Map::of)) .build(); //noinspection RedundantCast - return checkNotNull( + return requireNonNull( (Boolean) CommandExecutionHelper.execute( - markExtensionAbsence(extName), new AbstractMap.SimpleEntry<>(TERMINATE_APP, args) + markExtensionAbsence(extName), Map.entry(TERMINATE_APP, args) ) ); } diff --git a/src/main/java/io/appium/java_client/LocksDevice.java b/src/main/java/io/appium/java_client/LocksDevice.java index 60ba88ffc..bd818b21b 100644 --- a/src/main/java/io/appium/java_client/LocksDevice.java +++ b/src/main/java/io/appium/java_client/LocksDevice.java @@ -16,15 +16,15 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.UnsupportedCommandException; import java.time.Duration; +import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.getIsDeviceLockedCommand; import static io.appium.java_client.MobileCommand.lockDeviceCommand; import static io.appium.java_client.MobileCommand.unlockDeviceCommand; +import static java.util.Objects.requireNonNull; public interface LocksDevice extends ExecutesMethod, CanRememberExtensionPresence { @@ -47,7 +47,7 @@ default void lockDevice() { default void lockDevice(Duration duration) { final String extName = "mobile: lock"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "seconds", duration.getSeconds() )); } catch (UnsupportedCommandException e) { @@ -82,12 +82,12 @@ default void unlockDevice() { default boolean isDeviceLocked() { final String extName = "mobile: isLocked"; try { - return checkNotNull( + return requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName) ); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - return checkNotNull( + return requireNonNull( CommandExecutionHelper.execute(markExtensionAbsence(extName), getIsDeviceLockedCommand()) ); } diff --git a/src/main/java/io/appium/java_client/LogsEvents.java b/src/main/java/io/appium/java_client/LogsEvents.java index 33f50d2db..6ae80bc0c 100644 --- a/src/main/java/io/appium/java_client/LogsEvents.java +++ b/src/main/java/io/appium/java_client/LogsEvents.java @@ -16,7 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.serverevents.CommandEvent; import io.appium.java_client.serverevents.CustomEvent; import io.appium.java_client.serverevents.ServerEvents; @@ -41,7 +40,7 @@ public interface LogsEvents extends ExecutesMethod { * @throws org.openqa.selenium.WebDriverException if there was a failure while executing the script */ default void logEvent(CustomEvent event) { - execute(LOG_EVENT, ImmutableMap.of("vendor", event.getVendor(), "event", event.getEventName())); + execute(LOG_EVENT, Map.of("vendor", event.getVendor(), "event", event.getEventName())); } /** diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 878c13c4d..ee08c289a 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -27,9 +27,9 @@ import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.time.Duration; -import java.util.AbstractMap; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import static com.google.common.base.Strings.isNullOrEmpty; @@ -389,8 +389,7 @@ public static AppiumCommandInfo deleteC(String url) { */ @Deprecated public static Map.Entry> hideKeyboardCommand(String keyName) { - return new AbstractMap.SimpleEntry<>( - HIDE_KEYBOARD, prepareArguments("keyName", keyName)); + return Map.entry(HIDE_KEYBOARD, Map.of("keyName", keyName)); } /** @@ -405,10 +404,10 @@ public static AppiumCommandInfo deleteC(String url) { @Deprecated public static Map.Entry> hideKeyboardCommand(String strategy, String keyName) { - String[] parameters = new String[]{"strategy", "key"}; - Object[] values = new Object[]{strategy, keyName}; - return new AbstractMap.SimpleEntry<>( - HIDE_KEYBOARD, prepareArguments(parameters, values)); + return Map.entry(HIDE_KEYBOARD, Map.of( + "strategy", strategy, + "key", keyName + )); } /** @@ -417,7 +416,9 @@ public static AppiumCommandInfo deleteC(String url) { * @param param is a parameter name. * @param value is the parameter value. * @return built {@link ImmutableMap}. + * @deprecated Use {@link Map#of(Object, Object)} */ + @Deprecated public static ImmutableMap prepareArguments(String param, Object value) { ImmutableMap.Builder builder = ImmutableMap.builder(); @@ -431,7 +432,9 @@ public static ImmutableMap prepareArguments(String param, * @param params is the array with parameter names. * @param values is the array with parameter values. * @return built {@link ImmutableMap}. + * @deprecated Use {@link Map#of(Object, Object, Object, Object)} */ + @Deprecated public static ImmutableMap prepareArguments(String[] params, Object[] values) { ImmutableMap.Builder builder = ImmutableMap.builder(); @@ -452,8 +455,7 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> pressKeyCodeCommand(int key) { - return new AbstractMap.SimpleEntry<>( - PRESS_KEY_CODE, prepareArguments("keycode", key)); + return Map.entry(PRESS_KEY_CODE, Map.of("keycode", key)); } /** @@ -467,10 +469,10 @@ public static ImmutableMap prepareArguments(String[] params, @Deprecated public static Map.Entry> pressKeyCodeCommand(int key, 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 Map.entry(PRESS_KEY_CODE, Map.of( + "keycode", key, + "metastate", metastate + )); } /** @@ -482,8 +484,7 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> longPressKeyCodeCommand(int key) { - return new AbstractMap.SimpleEntry<>( - LONG_PRESS_KEY_CODE, prepareArguments("keycode", key)); + return Map.entry(LONG_PRESS_KEY_CODE, Map.of("keycode", key)); } /** @@ -497,10 +498,10 @@ public static ImmutableMap prepareArguments(String[] params, @Deprecated public static Map.Entry> longPressKeyCodeCommand(int key, 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 Map.entry(LONG_PRESS_KEY_CODE, Map.of( + "keycode", key, + "metastate", metastate + )); } /** @@ -512,8 +513,7 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> lockDeviceCommand(Duration duration) { - return new AbstractMap.SimpleEntry<>( - LOCK, prepareArguments("seconds", duration.getSeconds())); + return Map.entry(LOCK, Map.of("seconds", duration.getSeconds())); } /** @@ -524,7 +524,7 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> unlockDeviceCommand() { - return new AbstractMap.SimpleEntry<>(UNLOCK, ImmutableMap.of()); + return Map.entry(UNLOCK, Map.of()); } /** @@ -535,19 +535,19 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> getIsDeviceLockedCommand() { - return new AbstractMap.SimpleEntry<>(IS_LOCKED, ImmutableMap.of()); + return Map.entry(IS_LOCKED, Map.of()); } public static Map.Entry> getSettingsCommand() { - return new AbstractMap.SimpleEntry<>(GET_SETTINGS, ImmutableMap.of()); + return Map.entry(GET_SETTINGS, Map.of()); } public static Map.Entry> setSettingsCommand(String setting, Object value) { - return setSettingsCommand(prepareArguments(setting, value)); + return setSettingsCommand(Map.of(setting, value)); } public static Map.Entry> setSettingsCommand(Map settings) { - return new AbstractMap.SimpleEntry<>(SET_SETTINGS, prepareArguments("settings", settings)); + return Map.entry(SET_SETTINGS, Map.of("settings", settings)); } /** @@ -560,19 +560,18 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> pushFileCommand(String remotePath, byte[] base64Data) { - String[] parameters = new String[]{"path", "data"}; - Object[] values = new Object[]{remotePath, new String(base64Data, StandardCharsets.UTF_8)}; - return new AbstractMap.SimpleEntry<>(PUSH_FILE, prepareArguments(parameters, values)); + return Map.entry(PUSH_FILE, Map.of( + "path", remotePath, + "data", new String(base64Data, StandardCharsets.UTF_8) + )); } public static Map.Entry> startRecordingScreenCommand(BaseStartScreenRecordingOptions opts) { - return new AbstractMap.SimpleEntry<>(START_RECORDING_SCREEN, - prepareArguments("options", opts.build())); + return Map.entry(START_RECORDING_SCREEN, Map.of("options", opts.build())); } public static Map.Entry> stopRecordingScreenCommand(BaseStopScreenRecordingOptions opts) { - return new AbstractMap.SimpleEntry<>(STOP_RECORDING_SCREEN, - prepareArguments("options", opts.build())); + return Map.entry(STOP_RECORDING_SCREEN, Map.of("options", opts.build())); } /** @@ -587,15 +586,12 @@ public static ImmutableMap prepareArguments(String[] params, public static Map.Entry> compareImagesCommand(ComparisonMode mode, byte[] img1Data, byte[] img2Data, @Nullable BaseComparisonOptions options) { - String[] parameters = options == null - ? new String[]{"mode", "firstImage", "secondImage"} - : new String[]{"mode", "firstImage", "secondImage", "options"}; - Object[] values = options == null - ? new Object[]{mode.toString(), new String(img1Data, StandardCharsets.UTF_8), - new String(img2Data, StandardCharsets.UTF_8)} - : new Object[]{mode.toString(), new String(img1Data, StandardCharsets.UTF_8), - new String(img2Data, StandardCharsets.UTF_8), options.build()}; - return new AbstractMap.SimpleEntry<>(COMPARE_IMAGES, prepareArguments(parameters, values)); + ImmutableMap.Builder argsBuilder = ImmutableMap.builder() + .put("mode", mode.toString()) + .put("firstImage", new String(img1Data, StandardCharsets.UTF_8)) + .put("secondImage", new String(img2Data, StandardCharsets.UTF_8)); + Optional.ofNullable(options).ifPresent(opts -> argsBuilder.put("options", options.build())); + return Map.entry(COMPARE_IMAGES, argsBuilder.build()); } /** @@ -606,6 +602,6 @@ public static ImmutableMap prepareArguments(String[] params, */ @Deprecated public static Map.Entry> isKeyboardShownCommand() { - return new AbstractMap.SimpleEntry<>(IS_KEYBOARD_SHOWN, ImmutableMap.of()); + return Map.entry(IS_KEYBOARD_SHOWN, Map.of()); } } diff --git a/src/main/java/io/appium/java_client/MultiTouchAction.java b/src/main/java/io/appium/java_client/MultiTouchAction.java index 1549fbdf5..0a133756e 100644 --- a/src/main/java/io/appium/java_client/MultiTouchAction.java +++ b/src/main/java/io/appium/java_client/MultiTouchAction.java @@ -17,7 +17,6 @@ package io.appium.java_client; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import java.util.List; import java.util.Map; @@ -89,10 +88,10 @@ public MultiTouchAction perform() { } protected Map> getParameters() { - ImmutableList touchActions = actions.build(); - return ImmutableMap.of("actions", - touchActions.stream().map(touchAction -> - touchAction.getParameters().get("actions")).collect(toList())); + return Map.of("actions", + actions.build().stream().map(touchAction -> + touchAction.getParameters().get("actions")).collect(toList()) + ); } /** diff --git a/src/main/java/io/appium/java_client/PullsFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java index c6d4e0898..3c1e7ccff 100644 --- a/src/main/java/io/appium/java_client/PullsFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -16,16 +16,15 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.UnsupportedCommandException; import java.nio.charset.StandardCharsets; -import java.util.AbstractMap; import java.util.Base64; +import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.PULL_FILE; import static io.appium.java_client.MobileCommand.PULL_FOLDER; +import static java.util.Objects.requireNonNull; public interface PullsFiles extends ExecutesMethod, CanRememberExtensionPresence { @@ -45,16 +44,16 @@ default byte[] pullFile(String remotePath) { final String extName = "mobile: pullFile"; String base64String; try { - base64String = checkNotNull( + base64String = requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, - ImmutableMap.of("remotePath", remotePath) + Map.of("remotePath", remotePath) ) ); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - base64String = checkNotNull( + base64String = requireNonNull( CommandExecutionHelper.execute(markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(PULL_FILE, ImmutableMap.of("path", remotePath)) + Map.entry(PULL_FILE, Map.of("path", remotePath)) ) ); } @@ -77,16 +76,16 @@ default byte[] pullFolder(String remotePath) { final String extName = "mobile: pullFolder"; String base64String; try { - base64String = checkNotNull( + base64String = requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, - ImmutableMap.of("remotePath", remotePath) + Map.of("remotePath", remotePath) ) ); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback - base64String = checkNotNull( + base64String = requireNonNull( CommandExecutionHelper.execute(markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(PULL_FOLDER, ImmutableMap.of("path", remotePath)) + Map.entry(PULL_FOLDER, Map.of("path", remotePath)) ) ); } diff --git a/src/main/java/io/appium/java_client/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java index b91aada90..a30bf0d3b 100644 --- a/src/main/java/io/appium/java_client/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -16,7 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.UnsupportedCommandException; import java.io.File; @@ -24,6 +23,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Base64; +import java.util.Map; import static io.appium.java_client.MobileCommand.pushFileCommand; @@ -41,7 +41,7 @@ public interface PushesFiles extends ExecutesMethod, CanRememberExtensionPresenc default void pushFile(String remotePath, byte[] base64Data) { final String extName = "mobile: pushFile"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "remotePath", remotePath, "payload", new String(base64Data, StandardCharsets.UTF_8) )); diff --git a/src/main/java/io/appium/java_client/ScreenshotState.java b/src/main/java/io/appium/java_client/ScreenshotState.java index 1747a1e41..f51add334 100644 --- a/src/main/java/io/appium/java_client/ScreenshotState.java +++ b/src/main/java/io/appium/java_client/ScreenshotState.java @@ -31,7 +31,7 @@ import java.util.function.Function; import java.util.function.Supplier; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; @Accessors(chain = true) @@ -81,7 +81,7 @@ public class ScreenshotState { * @param stateProvider lambda function, which returns a screenshot for further comparison */ public ScreenshotState(ComparesImages comparator, Supplier stateProvider) { - this.comparator = checkNotNull(comparator); + this.comparator = requireNonNull(comparator); this.stateProvider = stateProvider; } @@ -110,7 +110,7 @@ public ScreenshotState remember() { * @return self instance for chaining */ public ScreenshotState remember(BufferedImage customInitialState) { - this.previousScreenshot = checkNotNull(customInitialState); + this.previousScreenshot = requireNonNull(customInitialState); return this; } diff --git a/src/main/java/io/appium/java_client/TouchAction.java b/src/main/java/io/appium/java_client/TouchAction.java index 98abeaafb..be76d1610 100644 --- a/src/main/java/io/appium/java_client/TouchAction.java +++ b/src/main/java/io/appium/java_client/TouchAction.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableList.builder; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; /** @@ -58,7 +58,7 @@ public class TouchAction> implements PerformsActions private PerformsTouchActions performsTouchActions; public TouchAction(PerformsTouchActions performsTouchActions) { - this.performsTouchActions = checkNotNull(performsTouchActions); + this.performsTouchActions = requireNonNull(performsTouchActions); parameterBuilder = builder(); } @@ -204,9 +204,9 @@ public T perform() { * @return A map of parameters for this touch action to pass as part of mjsonwp. */ protected Map> getParameters() { - List actionList = parameterBuilder.build(); - return ImmutableMap.of("actions", actionList.stream() - .map(ActionParameter::getParameterMap).collect(toList())); + return Map.of("actions", + parameterBuilder.build().stream().map(ActionParameter::getParameterMap).collect(toList()) + ); } /** @@ -233,17 +233,18 @@ public ActionParameter(String actionName) { } public ActionParameter(String actionName, ActionOptions opts) { - checkNotNull(opts); + requireNonNull(opts); this.actionName = actionName; optionsBuilder = ImmutableMap.builder(); //noinspection unchecked optionsBuilder.putAll(opts.build()); } - public ImmutableMap getParameterMap() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.put("action", actionName).put("options", optionsBuilder.build()); - return builder.build(); + public Map getParameterMap() { + return Map.of( + "action", actionName, + "options", optionsBuilder.build() + ); } } } 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 a3b31f716..50a7256a5 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -16,11 +16,9 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.MobileCommand; import org.openqa.selenium.remote.RemoteWebElement; -import java.util.AbstractMap; import java.util.Map; /** @@ -36,7 +34,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> currentActivityCommand() { - return new AbstractMap.SimpleEntry<>(CURRENT_ACTIVITY, ImmutableMap.of()); + return Map.entry(CURRENT_ACTIVITY, Map.of()); } /** @@ -46,7 +44,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> currentPackageCommand() { - return new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()); + return Map.entry(GET_CURRENT_PACKAGE, Map.of()); } /** @@ -57,7 +55,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * */ public static Map.Entry> getSupportedPerformanceDataTypesCommand() { - return new AbstractMap.SimpleEntry<>(GET_SUPPORTED_PERFORMANCE_DATA_TYPES, ImmutableMap.of()); + return Map.entry(GET_SUPPORTED_PERFORMANCE_DATA_TYPES, Map.of()); } /** @@ -90,10 +88,11 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ public static Map.Entry> getPerformanceDataCommand( String packageName, String dataType, int dataReadTimeout) { - String[] parameters = new String[] {"packageName", "dataType", "dataReadTimeout"}; - Object[] values = new Object[] {packageName, dataType, dataReadTimeout}; - return new AbstractMap.SimpleEntry<>( - GET_PERFORMANCE_DATA, prepareArguments(parameters, values)); + return Map.entry(GET_PERFORMANCE_DATA, Map.of( + "packageName", packageName, + "dataType", dataType, + "dataReadTimeout", dataReadTimeout + )); } /** @@ -103,7 +102,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> getDisplayDensityCommand() { - return new AbstractMap.SimpleEntry<>(GET_DISPLAY_DENSITY, ImmutableMap.of()); + return Map.entry(GET_DISPLAY_DENSITY, Map.of()); } /** @@ -113,7 +112,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> getNetworkConnectionCommand() { - return new AbstractMap.SimpleEntry<>(GET_NETWORK_CONNECTION, ImmutableMap.of()); + return Map.entry(GET_NETWORK_CONNECTION, Map.of()); } /** @@ -124,7 +123,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> getSystemBarsCommand() { - return new AbstractMap.SimpleEntry<>(GET_SYSTEM_BARS, ImmutableMap.of()); + return Map.entry(GET_SYSTEM_BARS, Map.of()); } /** @@ -134,7 +133,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> isLockedCommand() { - return new AbstractMap.SimpleEntry<>(IS_LOCKED, ImmutableMap.of()); + return Map.entry(IS_LOCKED, Map.of()); } /** @@ -145,8 +144,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> fingerPrintCommand(int fingerPrintId) { - return new AbstractMap.SimpleEntry<>(FINGER_PRINT, - prepareArguments("fingerprintId", fingerPrintId)); + return Map.entry(FINGER_PRINT, Map.of("fingerprintId", fingerPrintId)); } /** @@ -156,7 +154,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> openNotificationsCommand() { - return new AbstractMap.SimpleEntry<>(OPEN_NOTIFICATIONS, ImmutableMap.of()); + return Map.entry(OPEN_NOTIFICATIONS, Map.of()); } /** @@ -167,10 +165,10 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> setConnectionCommand(long bitMask) { - String[] parameters = new String[] {"name", "parameters"}; - Object[] values = new Object[] {"network_connection", ImmutableMap.of("type", bitMask)}; - return new AbstractMap.SimpleEntry<>( - SET_NETWORK_CONNECTION, prepareArguments(parameters, values)); + return Map.entry(SET_NETWORK_CONNECTION, Map.of( + "name", "network_connection", + "parameters", Map.of("type", bitMask) + )); } /** @@ -180,7 +178,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> toggleLocationServicesCommand() { - return new AbstractMap.SimpleEntry<>(TOGGLE_LOCATION_SERVICES, ImmutableMap.of()); + return Map.entry(TOGGLE_LOCATION_SERVICES, Map.of()); } /** @@ -190,7 +188,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> unlockCommand() { - return new AbstractMap.SimpleEntry<>(UNLOCK, ImmutableMap.of()); + return Map.entry(UNLOCK, Map.of()); } @@ -205,12 +203,10 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> replaceElementValueCommand( RemoteWebElement remoteWebElement, String value) { - String[] parameters = new String[] {"id", "value"}; - Object[] values = - new Object[] {remoteWebElement.getId(), value}; - - return new AbstractMap.SimpleEntry<>( - REPLACE_VALUE, prepareArguments(parameters, values)); + return Map.entry(REPLACE_VALUE, Map.of( + "id", remoteWebElement.getId(), + "value", value + )); } /** @@ -225,12 +221,10 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> sendSMSCommand( String phoneNumber, String message) { - ImmutableMap parameters = ImmutableMap - .builder().put("phoneNumber", phoneNumber) - .put("message", message) - .build(); - - return new AbstractMap.SimpleEntry<>(SEND_SMS, parameters); + return Map.entry(SEND_SMS, Map.of( + "phoneNumber", phoneNumber, + "message", message + )); } /** @@ -245,9 +239,10 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> gsmCallCommand( String phoneNumber, GsmCallActions gsmCallActions) { - String[] parameters = new String[] {"phoneNumber", "action"}; - Object[] values = new Object[]{phoneNumber, gsmCallActions.name().toLowerCase()}; - return new AbstractMap.SimpleEntry<>(GSM_CALL, prepareArguments(parameters, values)); + return Map.entry(GSM_CALL, Map.of( + "phoneNumber", phoneNumber, + "action", gsmCallActions.name().toLowerCase() + )); } /** @@ -261,11 +256,11 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> gsmSignalStrengthCommand( GsmSignalStrength gsmSignalStrength) { - return new AbstractMap.SimpleEntry<>(GSM_SIGNAL, - prepareArguments( + return Map.entry(GSM_SIGNAL, + Map.of( // https://github.com/appium/appium/issues/12234 - new String[] {"signalStrengh", "signalStrength" }, - new Object[] {gsmSignalStrength.ordinal(), gsmSignalStrength.ordinal()} + "signalStrengh", gsmSignalStrength.ordinal(), + "signalStrength", gsmSignalStrength.ordinal() )); } @@ -280,8 +275,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> gsmVoiceCommand( GsmVoiceState gsmVoiceState) { - return new AbstractMap.SimpleEntry<>(GSM_VOICE, - prepareArguments("state", gsmVoiceState.name().toLowerCase())); + return Map.entry(GSM_VOICE, Map.of("state", gsmVoiceState.name().toLowerCase())); } /** @@ -295,8 +289,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> networkSpeedCommand( NetworkSpeed networkSpeed) { - return new AbstractMap.SimpleEntry<>(NETWORK_SPEED, - prepareArguments("netspeed", networkSpeed.name().toLowerCase())); + return Map.entry(NETWORK_SPEED, Map.of("netspeed", networkSpeed.name().toLowerCase())); } /** @@ -310,8 +303,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> powerCapacityCommand( int percent) { - return new AbstractMap.SimpleEntry<>(POWER_CAPACITY, - prepareArguments("percent", percent)); + return Map.entry(POWER_CAPACITY, Map.of("percent", percent)); } /** @@ -325,8 +317,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> powerACCommand( PowerACState powerACState) { - return new AbstractMap.SimpleEntry<>(POWER_AC_STATE, - prepareArguments("state", powerACState.name().toLowerCase())); + return Map.entry(POWER_AC_STATE, Map.of("state", powerACState.name().toLowerCase())); } /** @@ -336,7 +327,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> toggleWifiCommand() { - return new AbstractMap.SimpleEntry<>(TOGGLE_WIFI, ImmutableMap.of()); + return Map.entry(TOGGLE_WIFI, Map.of()); } /** @@ -346,7 +337,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> toggleAirplaneCommand() { - return new AbstractMap.SimpleEntry<>(TOGGLE_AIRPLANE_MODE, ImmutableMap.of()); + return Map.entry(TOGGLE_AIRPLANE_MODE, Map.of()); } /** @@ -356,6 +347,6 @@ public class AndroidMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> toggleDataCommand() { - return new AbstractMap.SimpleEntry<>(TOGGLE_DATA, ImmutableMap.of()); + return Map.entry(TOGGLE_DATA, Map.of()); } } diff --git a/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java index 2ef6cdc29..14c575208 100644 --- a/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java @@ -107,9 +107,9 @@ public AndroidStartScreenRecordingOptions withTimeLimit(Duration timeLimit) { public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); builder.putAll(super.build()); - ofNullable(bitRate).map(x -> builder.put("bitRate", x)); - ofNullable(videoSize).map(x -> builder.put("videoSize", x)); - ofNullable(isBugReportEnabled).map(x -> builder.put("bugReport", x)); + ofNullable(bitRate).ifPresent(x -> builder.put("bitRate", x)); + ofNullable(videoSize).ifPresent(x -> builder.put("videoSize", x)); + ofNullable(isBugReportEnabled).ifPresent(x -> builder.put("bugReport", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java index 178ec4206..611fb30ed 100644 --- a/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java +++ b/src/main/java/io/appium/java_client/android/AuthenticatesByFinger.java @@ -1,11 +1,12 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; +import java.util.Map; + import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand; public interface AuthenticatesByFinger extends ExecutesMethod, CanRememberExtensionPresence { @@ -18,7 +19,7 @@ public interface AuthenticatesByFinger extends ExecutesMethod, CanRememberExtens default void fingerPrint(int fingerPrintId) { final String extName = "mobile: fingerprint"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "fingerprintId", fingerPrintId )); } catch (UnsupportedCommandException e) { diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java index 2b48a9e29..447377633 100644 --- a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -1,6 +1,5 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; @@ -8,7 +7,7 @@ import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.remote.RemoteWebElement; -import java.util.AbstractMap; +import java.util.Map; public interface CanReplaceElementValue extends ExecutesMethod, CanRememberExtensionPresence { /** @@ -24,7 +23,7 @@ public interface CanReplaceElementValue extends ExecutesMethod, CanRememberExten default void replaceElementValue(RemoteWebElement element, String value) { final String extName = "mobile: replaceValue"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "elementId", element.getId(), "text", value )); @@ -32,7 +31,7 @@ default void replaceElementValue(RemoteWebElement element, String value) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(MobileCommand.REPLACE_VALUE, ImmutableMap.of( + Map.entry(MobileCommand.REPLACE_VALUE, Map.of( "id", element.getId(), "text", value, "value", value diff --git a/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java b/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java index 40fc24a83..49a657898 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java @@ -21,12 +21,11 @@ import io.appium.java_client.clipboard.HasClipboard; import java.nio.charset.StandardCharsets; -import java.util.AbstractMap; import java.util.Base64; +import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; -import static io.appium.java_client.MobileCommand.prepareArguments; +import static java.util.Objects.requireNonNull; public interface HasAndroidClipboard extends HasClipboard { /** @@ -37,11 +36,13 @@ public interface HasAndroidClipboard extends HasClipboard { * @param base64Content base64-encoded content to be set. */ default void setClipboard(String label, ClipboardContentType contentType, byte[] base64Content) { - String[] parameters = new String[]{"content", "contentType", "label"}; - Object[] values = new Object[]{new String(checkNotNull(base64Content), StandardCharsets.UTF_8), - contentType.name().toLowerCase(), checkNotNull(label)}; - CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(SET_CLIPBOARD, - prepareArguments(parameters, values))); + CommandExecutionHelper.execute(this, Map.entry(SET_CLIPBOARD, + Map.of( + "content", new String(requireNonNull(base64Content), StandardCharsets.UTF_8), + "contentType", contentType.name().toLowerCase(), + "label", requireNonNull(label) + ) + )); } /** diff --git a/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java b/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java index ee6a3bce8..9a175d14c 100644 --- a/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java +++ b/src/main/java/io/appium/java_client/android/HasSupportedPerformanceDataType.java @@ -1,12 +1,12 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; import java.util.List; +import java.util.Map; import static io.appium.java_client.android.AndroidMobileCommandHelper.getPerformanceDataCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.getSupportedPerformanceDataTypesCommand; @@ -63,7 +63,7 @@ default List getSupportedPerformanceDataTypes() { default List> getPerformanceData(String packageName, String dataType, int dataReadTimeout) { final String extName = "mobile: getPerformanceData"; try { - return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "packageName", packageName, "dataType", dataType )); 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 d4cb4258a..9f56d7b1a 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,6 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; @@ -24,7 +23,7 @@ import javax.annotation.Nullable; -import java.util.AbstractMap; +import java.util.Map; import static io.appium.java_client.MobileCommand.CURRENT_ACTIVITY; import static io.appium.java_client.MobileCommand.GET_CURRENT_PACKAGE; @@ -44,7 +43,7 @@ default String currentActivity() { // TODO: Remove the fallback return CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(CURRENT_ACTIVITY, ImmutableMap.of()) + Map.entry(CURRENT_ACTIVITY, Map.of()) ); } } @@ -63,7 +62,7 @@ default String getCurrentPackage() { // TODO: Remove the fallback return CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(GET_CURRENT_PACKAGE, ImmutableMap.of()) + Map.entry(GET_CURRENT_PACKAGE, Map.of()) ); } } diff --git a/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java index 14854412e..5c16bb293 100644 --- a/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java +++ b/src/main/java/io/appium/java_client/android/SupportsGpsStateManagement.java @@ -5,8 +5,8 @@ import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; +import static java.util.Objects.requireNonNull; public interface SupportsGpsStateManagement extends ExecutesMethod, CanRememberExtensionPresence { @@ -30,7 +30,7 @@ default void toggleLocationServices() { * @return true if GPS service is enabled. */ default boolean isLocationServicesEnabled() { - return checkNotNull( + return requireNonNull( CommandExecutionHelper.executeScript(this, "mobile: isGpsEnabled") ); } diff --git a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java index 8f4dfa246..2992e5847 100644 --- a/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java +++ b/src/main/java/io/appium/java_client/android/SupportsNetworkStateManagement.java @@ -1,6 +1,5 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; @@ -8,10 +7,10 @@ import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleAirplaneCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleDataCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleWifiCommand; +import static java.util.Objects.requireNonNull; public interface SupportsNetworkStateManagement extends ExecutesMethod, CanRememberExtensionPresence { @@ -21,10 +20,10 @@ public interface SupportsNetworkStateManagement extends ExecutesMethod, CanRemem default void toggleWifi() { final String extName = "mobile: setConnectivity"; try { - Map result = checkNotNull( + Map result = requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: getConnectivity") ); - CommandExecutionHelper.executeScript(this, extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(this, extName, Map.of( "wifi", !((Boolean) result.get("wifi")) )); } catch (UnsupportedCommandException e) { @@ -40,10 +39,10 @@ default void toggleWifi() { default void toggleAirplaneMode() { final String extName = "mobile: setConnectivity"; try { - Map result = checkNotNull( + Map result = requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: getConnectivity") ); - CommandExecutionHelper.executeScript(this, extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(this, extName, Map.of( "airplaneMode", !((Boolean) result.get("airplaneMode")) )); } catch (UnsupportedCommandException e) { @@ -59,10 +58,10 @@ default void toggleAirplaneMode() { default void toggleData() { final String extName = "mobile: setConnectivity"; try { - Map result = checkNotNull( + Map result = requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), "mobile: getConnectivity") ); - CommandExecutionHelper.executeScript(this, extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(this, extName, Map.of( "data", !((Boolean) result.get("data")) )); } catch (UnsupportedCommandException e) { diff --git a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java index 025f00b05..c7b9accaf 100644 --- a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java +++ b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java @@ -1,12 +1,11 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; -import java.util.AbstractMap; +import java.util.Map; import static io.appium.java_client.MobileCommand.GSM_CALL; import static io.appium.java_client.MobileCommand.GSM_SIGNAL; @@ -27,7 +26,7 @@ public interface SupportsSpecialEmulatorCommands extends ExecutesMethod, CanReme default void sendSMS(String phoneNumber, String message) { final String extName = "mobile: sendSms"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "phoneNumber", phoneNumber, "message", message )); @@ -35,7 +34,7 @@ default void sendSMS(String phoneNumber, String message) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(SEND_SMS, ImmutableMap.of( + Map.entry(SEND_SMS, Map.of( "phoneNumber", phoneNumber, "message", message )) @@ -52,7 +51,7 @@ default void sendSMS(String phoneNumber, String message) { default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { final String extName = "mobile: gsmCall"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "phoneNumber", phoneNumber, "action", gsmCallAction.toString().toLowerCase() )); @@ -60,7 +59,7 @@ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(GSM_CALL, ImmutableMap.of( + Map.entry(GSM_CALL, Map.of( "phoneNumber", phoneNumber, "action", gsmCallAction.toString().toLowerCase() )) @@ -76,14 +75,14 @@ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { default void setGsmSignalStrength(GsmSignalStrength gsmSignalStrength) { final String extName = "mobile: gsmSignal"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "strength", gsmSignalStrength.ordinal() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(GSM_SIGNAL, ImmutableMap.of( + Map.entry(GSM_SIGNAL, Map.of( "signalStrengh", gsmSignalStrength.ordinal(), "signalStrength", gsmSignalStrength.ordinal() )) @@ -99,14 +98,14 @@ default void setGsmSignalStrength(GsmSignalStrength gsmSignalStrength) { default void setGsmVoice(GsmVoiceState gsmVoiceState) { final String extName = "mobile: gsmVoice"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "state", gsmVoiceState.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(GSM_VOICE, ImmutableMap.of( + Map.entry(GSM_VOICE, Map.of( "state", gsmVoiceState.name().toLowerCase() )) ); @@ -121,14 +120,14 @@ default void setGsmVoice(GsmVoiceState gsmVoiceState) { default void setNetworkSpeed(NetworkSpeed networkSpeed) { final String extName = "mobile: networkSpeed"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "speed", networkSpeed.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(NETWORK_SPEED, ImmutableMap.of( + Map.entry(NETWORK_SPEED, Map.of( "netspeed", networkSpeed.name().toLowerCase() )) ); @@ -143,14 +142,14 @@ default void setNetworkSpeed(NetworkSpeed networkSpeed) { default void setPowerCapacity(int percent) { final String extName = "mobile: powerCapacity"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "percent", percent )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(POWER_CAPACITY, ImmutableMap.of( + Map.entry(POWER_CAPACITY, Map.of( "percent", percent )) ); @@ -165,14 +164,14 @@ default void setPowerCapacity(int percent) { default void setPowerAC(PowerACState powerACState) { final String extName = "mobile: powerAC"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "state", powerACState.toString().toLowerCase() )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(POWER_AC_STATE, ImmutableMap.of( + Map.entry(POWER_AC_STATE, Map.of( "state", powerACState.name().toLowerCase() )) ); diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java index 67f2e09db..27ce3e4a6 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java @@ -23,7 +23,7 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public class AndroidInstallApplicationOptions extends @@ -64,7 +64,7 @@ public AndroidInstallApplicationOptions withReplaceDisabled() { * @return self instance for chaining. */ public AndroidInstallApplicationOptions withTimeout(Duration timeout) { - checkArgument(!checkNotNull(timeout).isNegative(), "The timeout value cannot be negative"); + checkArgument(!requireNonNull(timeout).isNegative(), "The timeout value cannot be negative"); this.timeout = timeout; return this; } @@ -139,11 +139,11 @@ public AndroidInstallApplicationOptions withGrantPermissionsDisabled() { @Override public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(replace).map(x -> builder.put("replace", x)); - ofNullable(timeout).map(x -> builder.put("timeout", x.toMillis())); - ofNullable(allowTestPackages).map(x -> builder.put("allowTestPackages", x)); - ofNullable(useSdcard).map(x -> builder.put("useSdcard", x)); - ofNullable(grantPermissions).map(x -> builder.put("grantPermissions", x)); + ofNullable(replace).ifPresent(x -> builder.put("replace", x)); + ofNullable(timeout).ifPresent(x -> builder.put("timeout", x.toMillis())); + ofNullable(allowTestPackages).ifPresent(x -> builder.put("allowTestPackages", x)); + ofNullable(useSdcard).ifPresent(x -> builder.put("useSdcard", x)); + ofNullable(grantPermissions).ifPresent(x -> builder.put("grantPermissions", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java index 2a4899f13..9783d9fda 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java @@ -23,7 +23,7 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public class AndroidRemoveApplicationOptions extends @@ -39,7 +39,7 @@ public class AndroidRemoveApplicationOptions extends * @return self instance for chaining. */ public AndroidRemoveApplicationOptions withTimeout(Duration timeout) { - checkArgument(!checkNotNull(timeout).isNegative(), + checkArgument(!requireNonNull(timeout).isNegative(), "The timeout value cannot be negative"); this.timeout = timeout; return this; @@ -69,8 +69,8 @@ public AndroidRemoveApplicationOptions withKeepDataDisabled() { @Override public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(timeout).map(x -> builder.put("timeout", x.toMillis())); - ofNullable(keepData).map(x -> builder.put("keepData", x)); + ofNullable(timeout).ifPresent(x -> builder.put("timeout", x.toMillis())); + ofNullable(keepData).ifPresent(x -> builder.put("keepData", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java index 0e11e569d..c9a0a02d8 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java @@ -23,7 +23,7 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public class AndroidTerminateApplicationOptions extends @@ -38,7 +38,7 @@ public class AndroidTerminateApplicationOptions extends * @return self instance for chaining. */ public AndroidTerminateApplicationOptions withTimeout(Duration timeout) { - checkArgument(!checkNotNull(timeout).isNegative(), "The timeout value cannot be negative"); + checkArgument(!requireNonNull(timeout).isNegative(), "The timeout value cannot be negative"); this.timeout = timeout; return this; } @@ -46,7 +46,7 @@ public AndroidTerminateApplicationOptions withTimeout(Duration timeout) { @Override public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(timeout).map(x -> builder.put("timeout", x.toMillis())); + ofNullable(timeout).ifPresent(x -> builder.put("timeout", x.toMillis())); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java index 0774c74a2..03d1381f0 100644 --- a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java +++ b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java @@ -16,7 +16,6 @@ package io.appium.java_client.android.connection; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; @@ -24,9 +23,9 @@ import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand; +import static java.util.Objects.requireNonNull; public interface HasNetworkConnection extends ExecutesMethod, CanRememberExtensionPresence { @@ -39,7 +38,7 @@ public interface HasNetworkConnection extends ExecutesMethod, CanRememberExtensi default ConnectionState setConnection(ConnectionState connection) { final String extName = "mobile: setConnectivity"; try { - CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, ImmutableMap.of( + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "wifi", connection.isWiFiEnabled(), "data", connection.isDataEnabled(), "airplaneMode", connection.isAirplaneModeEnabled() @@ -48,7 +47,7 @@ default ConnectionState setConnection(ConnectionState connection) { } catch (UnsupportedCommandException e) { // TODO: Remove the fallback return new ConnectionState( - checkNotNull( + requireNonNull( CommandExecutionHelper.execute( markExtensionAbsence(extName), setConnectionCommand(connection.getBitMask()) @@ -66,7 +65,7 @@ default ConnectionState setConnection(ConnectionState connection) { default ConnectionState getConnection() { final String extName = "mobile: getConnectivity"; try { - Map result = checkNotNull( + Map result = requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName) ); return new ConnectionState( @@ -77,7 +76,7 @@ default ConnectionState getConnection() { } catch (UnsupportedCommandException e) { // TODO: Remove the fallback return new ConnectionState( - checkNotNull( + requireNonNull( CommandExecutionHelper.execute( markExtensionAbsence(extName), getNetworkConnectionCommand() diff --git a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java index f04a41fe2..7cd53e698 100644 --- a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java +++ b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java @@ -117,9 +117,9 @@ public AndroidGeoLocation withSpeed(double speed) { ofNullable(latitude).map(x -> builder.put("latitude", x)) .orElseThrow(() -> new IllegalArgumentException( "A valid 'latitude' must be provided")); - ofNullable(altitude).map(x -> builder.put("altitude", x)); - ofNullable(satellites).map(x -> builder.put("satellites", x)); - ofNullable(speed).map(x -> builder.put("speed", x)); + ofNullable(altitude).ifPresent(x -> builder.put("altitude", x)); + ofNullable(satellites).ifPresent(x -> builder.put("satellites", x)); + ofNullable(speed).ifPresent(x -> builder.put("speed", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java b/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java index 3587ad07e..d1ccf8e2c 100644 --- a/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java +++ b/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java @@ -16,12 +16,11 @@ package io.appium.java_client.android.geolocation; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.remote.DriverCommand; -import java.util.AbstractMap; +import java.util.Map; public interface SupportsExtendedGeolocationCommands extends ExecutesMethod { @@ -32,9 +31,8 @@ public interface SupportsExtendedGeolocationCommands extends ExecutesMethod { * @param location The location object to set. */ default void setLocation(AndroidGeoLocation location) { - ImmutableMap parameters = ImmutableMap - .of("location", location.build()); - CommandExecutionHelper.execute(this, - new AbstractMap.SimpleEntry<>(DriverCommand.SET_LOCATION, parameters)); + CommandExecutionHelper.execute(this, Map.entry(DriverCommand.SET_LOCATION, + Map.of("location", location.build()) + )); } } diff --git a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java index b262096c0..641087050 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java +++ b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java @@ -22,7 +22,6 @@ import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; -import java.util.AbstractMap; import java.util.Map; import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE; @@ -43,7 +42,7 @@ default void pressKey(KeyEvent keyEvent) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(PRESS_KEY_CODE, keyEvent.build()) + Map.entry(PRESS_KEY_CODE, keyEvent.build()) ); } } @@ -65,7 +64,7 @@ default void longPressKey(KeyEvent keyEvent) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - new AbstractMap.SimpleEntry<>(LONG_PRESS_KEY_CODE, keyEvent.build()) + Map.entry(LONG_PRESS_KEY_CODE, keyEvent.build()) ); } } diff --git a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java index 24adc5675..4cbc571da 100644 --- a/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java +++ b/src/main/java/io/appium/java_client/android/options/server/EspressoBuildConfig.java @@ -42,7 +42,7 @@ private EspressoBuildConfig assignToolsVersionsField(String name, Object value) Optional> toolsVersionsOptional = getOptionValue(TOOLS_VERSION); Map toolsVersions = toolsVersionsOptional.orElseGet(HashMap::new); toolsVersions.put(name, value); - if (!toolsVersionsOptional.isPresent()) { + if (toolsVersionsOptional.isEmpty()) { assignOptionValue(TOOLS_VERSION, toolsVersions); } return this; diff --git a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java index 637a35caf..a6ae3327c 100644 --- a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java +++ b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java @@ -20,13 +20,12 @@ import io.appium.java_client.ExecutesMethod; import java.nio.charset.StandardCharsets; -import java.util.AbstractMap; import java.util.Base64; +import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.GET_CLIPBOARD; import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; -import static io.appium.java_client.MobileCommand.prepareArguments; +import static java.util.Objects.requireNonNull; public interface HasClipboard extends ExecutesMethod { /** @@ -36,11 +35,12 @@ public interface HasClipboard extends ExecutesMethod { * @param base64Content base64-encoded content to be set. */ default void setClipboard(ClipboardContentType contentType, byte[] base64Content) { - String[] parameters = new String[]{"content", "contentType"}; - Object[] values = new Object[]{new String(checkNotNull(base64Content), StandardCharsets.UTF_8), - contentType.name().toLowerCase()}; - CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(SET_CLIPBOARD, - prepareArguments(parameters, values))); + CommandExecutionHelper.execute(this, Map.entry(SET_CLIPBOARD, + Map.of( + "content", new String(requireNonNull(base64Content), StandardCharsets.UTF_8), + "contentType", contentType.name().toLowerCase() + ) + )); } /** @@ -50,8 +50,8 @@ default void setClipboard(ClipboardContentType contentType, byte[] base64Content * @return the actual content of the clipboard as base64-encoded string or an empty string if the clipboard is empty */ default String getClipboard(ClipboardContentType contentType) { - return CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(GET_CLIPBOARD, - prepareArguments("contentType", contentType.name().toLowerCase()))); + return CommandExecutionHelper.execute(this, Map.entry(GET_CLIPBOARD, + Map.of("contentType", contentType.name().toLowerCase()))); } /** diff --git a/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java b/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java index 15d7ddf36..11c4f650a 100644 --- a/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java +++ b/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java @@ -20,7 +20,7 @@ import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; @@ -35,7 +35,7 @@ public class ScriptOptions { * @return self instance for chaining */ public ScriptOptions withScriptType(ScriptType type) { - this.scriptType = checkNotNull(type); + this.scriptType = requireNonNull(type); return this; } @@ -59,8 +59,8 @@ public ScriptOptions withTimeout(long timeoutMs) { */ public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(scriptType).map(x -> builder.put("type", x.name().toLowerCase())); - ofNullable(timeoutMs).map(x -> builder.put("timeout", x)); + ofNullable(scriptType).ifPresent(x -> builder.put("type", x.name().toLowerCase())); + ofNullable(timeoutMs).ifPresent(x -> builder.put("timeout", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java b/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java index 2563055cc..b91974009 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java @@ -46,7 +46,7 @@ public T withEnabledVisualization() { */ public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(visualize).map(x -> builder.put("visualize", x)); + ofNullable(visualize).ifPresent(x -> builder.put("visualize", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java index 5e72c6591..42e4cd976 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java @@ -70,9 +70,9 @@ public FeaturesMatchingOptions withGoodMatchesFactor(int factor) { public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); builder.putAll(super.build()); - ofNullable(detectorName).map(x -> builder.put("detectorName", x)); - ofNullable(matchFunc).map(x -> builder.put("matchFunc", x)); - ofNullable(goodMatchesFactor).map(x -> builder.put("goodMatchesFactor", x)); + ofNullable(detectorName).ifPresent(x -> builder.put("detectorName", x)); + ofNullable(matchFunc).ifPresent(x -> builder.put("matchFunc", x)); + ofNullable(goodMatchesFactor).ifPresent(x -> builder.put("goodMatchesFactor", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java index 818c9f2da..d75e1d7e1 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java @@ -68,9 +68,9 @@ public OccurrenceMatchingOptions withMatchNeighbourThreshold(int threshold) { public Map build() { final ImmutableMap.Builder builder = ImmutableMap.builder(); builder.putAll(super.build()); - ofNullable(threshold).map(x -> builder.put("threshold", x)); - ofNullable(matchNeighbourThreshold).map(x -> builder.put("matchNeighbourThreshold", x)); - ofNullable(multiple).map(x -> builder.put("multiple", x)); + ofNullable(threshold).ifPresent(x -> builder.put("threshold", x)); + ofNullable(matchNeighbourThreshold).ifPresent(x -> builder.put("matchNeighbourThreshold", x)); + ofNullable(multiple).ifPresent(x -> builder.put("multiple", x)); return builder.build(); } } diff --git a/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java b/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java index f1dd7300e..32f4c9df4 100644 --- a/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java +++ b/src/main/java/io/appium/java_client/ios/HasIOSClipboard.java @@ -29,7 +29,7 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; public interface HasIOSClipboard extends HasClipboard { /** @@ -40,7 +40,7 @@ public interface HasIOSClipboard extends HasClipboard { */ default void setClipboardImage(BufferedImage img) throws IOException { try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { - ImageIO.write(checkNotNull(img), "png", os); + ImageIO.write(requireNonNull(img), "png", os); setClipboard(ClipboardContentType.IMAGE, Base64 .getMimeEncoder() .encode(os.toByteArray())); @@ -68,7 +68,7 @@ default BufferedImage getClipboardImage() throws IOException { default void setClipboardUrl(URL url) { setClipboard(ClipboardContentType.URL, Base64 .getMimeEncoder() - .encode(checkNotNull(url).toString().getBytes(StandardCharsets.UTF_8))); + .encode(requireNonNull(url).toString().getBytes(StandardCharsets.UTF_8))); } /** 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 33c048710..995c196a6 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -49,8 +49,7 @@ import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; - -import static io.appium.java_client.MobileCommand.prepareArguments; +import java.util.Map; /** * iOS driver implementation. @@ -275,7 +274,7 @@ class IOSAlert implements Alert { } @Override public void sendKeys(String keysToSend) { - execute(DriverCommand.SET_ALERT_VALUE, prepareArguments("value", keysToSend)); + execute(DriverCommand.SET_ALERT_VALUE, Map.of("value", keysToSend)); } } 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 390079d19..ebdddaedc 100644 --- a/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java @@ -16,10 +16,8 @@ package io.appium.java_client.ios; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.MobileCommand; -import java.util.AbstractMap; import java.util.Map; @Deprecated @@ -32,8 +30,8 @@ public class IOSMobileCommandHelper extends MobileCommand { * @deprecated this helper is deprecated and will be removed in future versions. */ @Deprecated - public static Map.Entry> shakeCommand() { - return new AbstractMap.SimpleEntry<>(SHAKE, ImmutableMap.of()); + public static Map.Entry> shakeCommand() { + return Map.entry(SHAKE, Map.of()); } /** @@ -45,8 +43,7 @@ public class IOSMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> touchIdCommand(boolean match) { - return new AbstractMap.SimpleEntry<>( - TOUCH_ID, prepareArguments("match", match)); + return Map.entry(TOUCH_ID, Map.of("match", match)); } /** @@ -59,7 +56,6 @@ public class IOSMobileCommandHelper extends MobileCommand { */ @Deprecated public static Map.Entry> toggleTouchIdEnrollmentCommand(boolean enabled) { - return new AbstractMap.SimpleEntry<>( - TOUCH_ID_ENROLLMENT, prepareArguments("enabled", enabled)); + return Map.entry(TOUCH_ID_ENROLLMENT, Map.of("enabled", enabled)); } } diff --git a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java index a86dabac7..b0673a5e0 100644 --- a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java @@ -23,7 +23,7 @@ import java.time.Duration; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public class IOSStartScreenRecordingOptions @@ -56,7 +56,7 @@ public IOSStartScreenRecordingOptions withUploadOptions(ScreenRecordingUploadOpt * @return self instance for chaining. */ public IOSStartScreenRecordingOptions withVideoType(String videoType) { - this.videoType = checkNotNull(videoType); + this.videoType = requireNonNull(videoType); return this; } @@ -72,7 +72,7 @@ public enum VideoQuality { * @return self instance for chaining. */ public IOSStartScreenRecordingOptions withVideoQuality(VideoQuality videoQuality) { - this.videoQuality = checkNotNull(videoQuality).name().toLowerCase(); + this.videoQuality = requireNonNull(videoQuality).name().toLowerCase(); return this; } @@ -98,7 +98,7 @@ public IOSStartScreenRecordingOptions withFps(int fps) { * @return self instance for chaining. */ public IOSStartScreenRecordingOptions withVideoScale(String videoScale) { - this.videoScale = checkNotNull(videoScale); + this.videoScale = requireNonNull(videoScale); return this; } diff --git a/src/main/java/io/appium/java_client/ios/PerformsTouchID.java b/src/main/java/io/appium/java_client/ios/PerformsTouchID.java index af574bd2f..5829808bd 100644 --- a/src/main/java/io/appium/java_client/ios/PerformsTouchID.java +++ b/src/main/java/io/appium/java_client/ios/PerformsTouchID.java @@ -16,10 +16,11 @@ package io.appium.java_client.ios; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import java.util.Map; + public interface PerformsTouchID extends ExecutesMethod { /** @@ -29,7 +30,7 @@ public interface PerformsTouchID extends ExecutesMethod { * @param match If true, simulates a successful fingerprint scan. If false, simulates a failed fingerprint scan. */ default void performTouchID(boolean match) { - CommandExecutionHelper.executeScript(this, "mobile: sendBiometricMatch", ImmutableMap.of( + CommandExecutionHelper.executeScript(this, "mobile: sendBiometricMatch", Map.of( "type", "touchId", "match", match )); @@ -44,7 +45,7 @@ default void performTouchID(boolean match) { * Multiple calls of the method with the same argument value have no effect. */ default void toggleTouchIDEnrollment(boolean enabled) { - CommandExecutionHelper.executeScript(this, "mobile: enrollBiometric", ImmutableMap.of( + CommandExecutionHelper.executeScript(this, "mobile: enrollBiometric", Map.of( "isEnabled", enabled )); } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 63208ef1f..67af93096 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -16,7 +16,6 @@ package io.appium.java_client.pagefactory; -import com.google.common.collect.ImmutableList; import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; @@ -62,7 +61,7 @@ */ public class AppiumFieldDecorator implements FieldDecorator { - private static final List> AVAILABLE_ELEMENT_CLASSES = ImmutableList.of( + private static final List> AVAILABLE_ELEMENT_CLASSES = List.of( WebElement.class, RemoteWebElement.class ); diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java index 30bf58456..4bb1b1f4d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java @@ -25,8 +25,8 @@ import java.util.Map; import java.util.Objects; -import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; +import static java.util.Objects.requireNonNull; public class ContentMappedBy extends By { private final Map map; @@ -43,7 +43,7 @@ public ContentMappedBy(Map map) { * @return self-reference. */ public By useContent(@Nonnull ContentType type) { - checkNotNull(type); + requireNonNull(type); currentContent = type; return this; } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java index 9a4196f23..2f44463ec 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java @@ -16,7 +16,6 @@ package io.appium.java_client.pagefactory.bys.builder; -import io.appium.java_client.functions.AppiumFunction; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.SearchContext; @@ -25,14 +24,15 @@ import org.openqa.selenium.support.ui.FluentWait; import java.util.Optional; +import java.util.function.Function; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; public class ByChained extends org.openqa.selenium.support.pagefactory.ByChained { private final By[] bys; - private static AppiumFunction getSearchingFunction(By by) { + private static Function getSearchingFunction(By by) { return input -> { try { if (input == null) { @@ -51,8 +51,7 @@ private static AppiumFunction getSearchingFunction(By * @param bys is a set of {@link By} which forms the chain of the searching. */ public ByChained(By[] bys) { - super(bys); - checkNotNull(bys); + super(requireNonNull(bys)); if (bys.length == 0) { throw new IllegalArgumentException("By array should not be empty"); } @@ -61,7 +60,7 @@ public ByChained(By[] bys) { @Override public WebElement findElement(SearchContext context) { - AppiumFunction searchingFunction = null; + Function searchingFunction = null; for (By by: bys) { searchingFunction = Optional.ofNullable(searchingFunction != null @@ -71,7 +70,7 @@ public WebElement findElement(SearchContext context) { FluentWait waiting = new FluentWait<>(context); try { - checkNotNull(searchingFunction); + requireNonNull(searchingFunction); return waiting.until(searchingFunction); } catch (TimeoutException e) { throw new NoSuchElementException("Cannot locate an element using " + this); diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index 6ed19b7a4..9543073a8 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.Objects.requireNonNull; import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; public class Helpers { @@ -108,7 +109,7 @@ public static T createProxy( ) ); Preconditions.checkArgument(!listeners.isEmpty(), "The collection of listeners must not be empty"); - Preconditions.checkArgument(cls != null, "Class must not be null"); + requireNonNull(cls, "Class must not be null"); Preconditions.checkArgument(!cls.isInterface(), "Class must not be an interface"); ElementMatcher.Junction matcher = ElementMatchers.isPublic(); diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index d7dd90683..d3310f478 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -16,7 +16,6 @@ package io.appium.java_client.remote; -import com.google.common.base.Supplier; import com.google.common.base.Throwables; import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.internal.ReflectionHelpers; @@ -47,8 +46,8 @@ import java.util.Map; import java.util.Optional; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.throwIfUnchecked; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; @@ -85,14 +84,14 @@ public AppiumCommandExecutor( public AppiumCommandExecutor(Map additionalCommands, DriverService service, HttpClient.Factory httpClientFactory) { - this(additionalCommands, checkNotNull(service), httpClientFactory, - AppiumClientConfig.defaultConfig().baseUrl(checkNotNull(service).getUrl())); + this(additionalCommands, requireNonNull(service), httpClientFactory, + AppiumClientConfig.defaultConfig().baseUrl(requireNonNull(service).getUrl())); } public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { this(additionalCommands, null, httpClientFactory, - AppiumClientConfig.defaultConfig().baseUrl(checkNotNull(addressOfRemoteServer))); + AppiumClientConfig.defaultConfig().baseUrl(requireNonNull(addressOfRemoteServer))); } public AppiumCommandExecutor(Map additionalCommands, AppiumClientConfig appiumClientConfig) { @@ -101,13 +100,13 @@ public AppiumCommandExecutor(Map additionalCommands, Appium public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer) { this(additionalCommands, null, HttpClient.Factory.createDefault(), - AppiumClientConfig.defaultConfig().baseUrl(checkNotNull(addressOfRemoteServer))); + AppiumClientConfig.defaultConfig().baseUrl(requireNonNull(addressOfRemoteServer))); } public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, AppiumClientConfig appiumClientConfig) { this(additionalCommands, null, HttpClient.Factory.createDefault(), - appiumClientConfig.baseUrl(checkNotNull(addressOfRemoteServer))); + appiumClientConfig.baseUrl(requireNonNull(addressOfRemoteServer))); } public AppiumCommandExecutor(Map additionalCommands, DriverService service) { @@ -246,8 +245,7 @@ public Response execute(Command command) throws WebDriverException { } return new WebDriverException("The appium server has accidentally died!", rootCause); - }).orElseGet((Supplier) () -> - new WebDriverException(rootCause.getMessage(), rootCause)); + }).orElseGet(() -> new WebDriverException(rootCause.getMessage(), rootCause)); } throwIfUnchecked(t); throw new WebDriverException(t); diff --git a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java index a57170d6c..5f7655c2d 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java +++ b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java @@ -17,13 +17,13 @@ package io.appium.java_client.remote; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import io.appium.java_client.remote.options.BaseOptions; import org.openqa.selenium.Capabilities; import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.CommandPayload; import java.util.Map; +import java.util.Set; import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; @@ -50,8 +50,8 @@ private static Map makeW3CSafe(Capabilities possiblyInvalidCapab * @param capabilities User-provided capabilities. */ public AppiumNewSessionCommandPayload(Capabilities capabilities) { - super(NEW_SESSION, ImmutableMap.of( - "capabilities", ImmutableSet.of(makeW3CSafe(capabilities)), + super(NEW_SESSION, Map.of( + "capabilities", Set.of(makeW3CSafe(capabilities)), "desiredCapabilities", capabilities )); } diff --git a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java index 7f5f79956..b5c7e4b3b 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java +++ b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java @@ -16,7 +16,6 @@ package io.appium.java_client.remote; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.NoSuchContextException; import org.openqa.selenium.ContextAware; @@ -28,9 +27,10 @@ import javax.annotation.Nullable; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; public interface SupportsContextSwitching extends WebDriver, ContextAware, ExecutesMethod { /** @@ -40,9 +40,9 @@ public interface SupportsContextSwitching extends WebDriver, ContextAware, Execu * @return self instance for chaining. */ default WebDriver context(String name) { - checkNotNull(name, "Must supply a context name"); + requireNonNull(name, "Must supply a context name"); try { - execute(DriverCommand.SWITCH_TO_CONTEXT, ImmutableMap.of("name", name)); + execute(DriverCommand.SWITCH_TO_CONTEXT, Map.of("name", name)); return this; } catch (WebDriverException e) { throw new NoSuchContextException(e.getMessage(), e); @@ -55,7 +55,7 @@ default WebDriver context(String name) { * @return List list of context names. */ default Set getContextHandles() { - Response response = execute(DriverCommand.GET_CONTEXT_HANDLES, ImmutableMap.of()); + Response response = execute(DriverCommand.GET_CONTEXT_HANDLES, Map.of()); Object value = response.getValue(); try { //noinspection unchecked diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java index 6e1af3a58..4e8078707 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsRotation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -16,7 +16,6 @@ package io.appium.java_client.remote; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.DeviceRotation; import org.openqa.selenium.ScreenOrientation; @@ -44,7 +43,7 @@ default void rotate(DeviceRotation rotation) { default void rotate(ScreenOrientation orientation) { execute(DriverCommand.SET_SCREEN_ORIENTATION, - ImmutableMap.of("orientation", orientation.value().toUpperCase())); + Map.of("orientation", orientation.value().toUpperCase())); } /** diff --git a/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java b/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java index 308a9b05a..e4e3797ad 100644 --- a/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java @@ -20,7 +20,7 @@ import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public abstract class BaseScreenRecordingOptions> { @@ -34,7 +34,7 @@ public abstract class BaseScreenRecordingOptions> @@ -36,7 +36,7 @@ public abstract class BaseStartScreenRecordingOptions formFields) { - this.formFields = checkNotNull(formFields); + this.formFields = requireNonNull(formFields); return this; } @@ -112,7 +112,7 @@ public ScreenRecordingUploadOptions withFormFields(Map formField * @return self instance for chaining. */ public ScreenRecordingUploadOptions withHeaders(Map headers) { - this.headers = checkNotNull(headers); + this.headers = requireNonNull(headers); return this; } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index fa2ed6584..0bd223034 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -45,10 +45,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.isNullOrEmpty; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP6_ADDRESS; +import static java.util.Objects.requireNonNull; import static org.slf4j.event.Level.DEBUG; import static org.slf4j.event.Level.INFO; @@ -291,7 +291,7 @@ public String getStdOut() { * that is ready to accept server output */ public void addOutPutStream(OutputStream outputStream) { - checkNotNull(outputStream, "outputStream parameter is NULL!"); + requireNonNull(outputStream, "outputStream parameter is NULL!"); stream.add(outputStream); } @@ -302,7 +302,7 @@ public void addOutPutStream(OutputStream outputStream) { * that are ready to accept server output */ public void addOutPutStreams(List outputStreams) { - checkNotNull(outputStreams, "outputStreams parameter is NULL!"); + requireNonNull(outputStreams, "outputStreams parameter is NULL!"); for (OutputStream outputStream : outputStreams) { addOutPutStream(outputStream); } @@ -314,7 +314,7 @@ public void addOutPutStreams(List outputStreams) { * @return the outputStream has been removed if it is present */ public Optional removeOutPutStream(OutputStream outputStream) { - checkNotNull(outputStream, "outputStream parameter is NULL!"); + requireNonNull(outputStream, "outputStream parameter is NULL!"); return stream.remove(outputStream); } @@ -399,7 +399,7 @@ public void enableDefaultSlf4jLoggingOfOutputData() { * available. */ public void addSlf4jLogMessageConsumer(BiConsumer slf4jLogMessageConsumer) { - checkNotNull(slf4jLogMessageConsumer, "slf4jLogMessageConsumer parameter is NULL!"); + requireNonNull(slf4jLogMessageConsumer, "slf4jLogMessageConsumer parameter is NULL!"); addLogMessageConsumer(logMessage -> { slf4jLogMessageConsumer.accept(logMessage, parseSlf4jContextFromLogMessage(logMessage)); }); @@ -433,7 +433,7 @@ static Slf4jLogMessageContext parseSlf4jContextFromLogMessage(String logMessage) * @param consumer Consumer block to be executed when a log message is available. */ public void addLogMessageConsumer(Consumer consumer) { - checkNotNull(consumer, "consumer parameter is NULL!"); + requireNonNull(consumer, "consumer parameter is NULL!"); addOutPutStream(new OutputStream() { private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index a8879cc36..a8690c78b 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -49,8 +49,8 @@ import java.util.function.Function; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.isNullOrEmpty; +import static java.util.Objects.requireNonNull; import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; public final class AppiumServiceBuilder @@ -229,7 +229,7 @@ public AppiumServiceBuilder withArgument(ServerArgument argument, String value) } private static String sanitizeBasePath(String basePath) { - basePath = checkNotNull(basePath).trim(); + basePath = requireNonNull(basePath).trim(); checkArgument( !basePath.isEmpty(), "Given base path is not valid - blank or empty values are not allowed for base path" @@ -357,7 +357,7 @@ private String capabilitiesToCmdlineArg() { } @Override - protected ImmutableList createArgs() { + protected List createArgs() { List argList = new ArrayList<>(); loadPathToMainScript(); argList.add(appiumJS.getAbsolutePath()); diff --git a/src/main/java/io/appium/java_client/touch/LongPressOptions.java b/src/main/java/io/appium/java_client/touch/LongPressOptions.java index ac8600b49..9f9104b71 100644 --- a/src/main/java/io/appium/java_client/touch/LongPressOptions.java +++ b/src/main/java/io/appium/java_client/touch/LongPressOptions.java @@ -22,7 +22,7 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public class LongPressOptions extends AbstractOptionCombinedWithPosition { @@ -45,7 +45,7 @@ public static LongPressOptions longPressOptions() { * @return this instance for chaining. */ public LongPressOptions withDuration(Duration duration) { - checkNotNull(duration); + requireNonNull(duration); checkArgument(duration.toMillis() >= 0, "Duration value should be greater or equal to zero"); this.duration = duration; diff --git a/src/main/java/io/appium/java_client/touch/WaitOptions.java b/src/main/java/io/appium/java_client/touch/WaitOptions.java index 81aedd674..29d869b07 100644 --- a/src/main/java/io/appium/java_client/touch/WaitOptions.java +++ b/src/main/java/io/appium/java_client/touch/WaitOptions.java @@ -20,8 +20,8 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static java.time.Duration.ofMillis; +import static java.util.Objects.requireNonNull; public class WaitOptions extends ActionOptions { protected Duration duration = ofMillis(0); @@ -44,7 +44,7 @@ public static WaitOptions waitOptions(Duration duration) { * @return this instance for chaining. */ public WaitOptions withDuration(Duration duration) { - checkNotNull(duration); + requireNonNull(duration); checkArgument(duration.toMillis() >= 0, "Duration value should be greater or equal to zero"); this.duration = duration; diff --git a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java index 05b4684a3..16cf65f70 100644 --- a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java +++ b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java @@ -8,7 +8,7 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; public class ElementOption extends PointOption { @@ -82,7 +82,7 @@ public ElementOption withCoordinates(int xOffset, int yOffset) { * @return self-reference */ public ElementOption withElement(WebElement element) { - checkNotNull(element); + requireNonNull(element); checkArgument(true, "Element should be an instance of the class which " + "extends org.openqa.selenium.remote.RemoteWebElement", element instanceof RemoteWebElement); diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java index 21389d54a..5db7921a7 100644 --- a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java @@ -1,6 +1,5 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; import io.appium.java_client.functions.ActionSupplier; import io.appium.java_client.touch.offset.ElementOption; @@ -10,6 +9,7 @@ import org.openqa.selenium.WebElement; import java.util.List; +import java.util.Map; import static io.appium.java_client.TestUtils.getCenter; import static io.appium.java_client.touch.WaitOptions.waitOptions; @@ -59,8 +59,8 @@ public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { } @Test public void verticalSwipingWithSupplier() throws Exception { - driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); - driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: terminateApp", Map.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", Map.of("appId", APP_ID)); driver.findElement(AppiumBy.accessibilityId("Views")).click(); Point originalLocation = driver.findElement(AppiumBy.accessibilityId("Gallery")).getLocation(); diff --git a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java index 3db8ade05..83d8eabdf 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java @@ -16,8 +16,6 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.Test; import org.openqa.selenium.json.Json; @@ -25,6 +23,8 @@ import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; +import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -37,9 +37,9 @@ public void testFindByDataMatcher() { .elementToBeClickable(AppiumBy.accessibilityId("Graphics"))); driver.findElement(AppiumBy.accessibilityId("Graphics")).click(); - String selector = new Json().toJson(ImmutableMap.of( + String selector = new Json().toJson(Map.of( "name", "hasEntry", - "args", ImmutableList.of("title", "Sweep") + "args", List.of("title", "Sweep") )); assertNotNull(wait.until(ExpectedConditions diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index 095866e89..e1ff99d2e 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -16,7 +16,6 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; import org.apache.commons.io.FileUtils; import org.hamcrest.Matchers; @@ -29,6 +28,7 @@ import java.util.ArrayList; import java.util.Base64; import java.util.List; +import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -149,8 +149,8 @@ public void isAppNotInstalledTest() { @Test public void closeAppTest() { - driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); - driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: terminateApp", Map.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", Map.of("appId", APP_ID)); assertEquals(".ApiDemos", driver.currentActivity()); } diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java index 84cb15753..c24ed20fa 100644 --- a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidTouchTest.java @@ -1,6 +1,5 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; import io.appium.java_client.MultiTouchAction; import io.appium.java_client.TouchAction; @@ -11,6 +10,7 @@ import org.openqa.selenium.WebElement; import java.util.List; +import java.util.Map; import static io.appium.java_client.TestUtils.getCenter; import static io.appium.java_client.touch.LongPressOptions.longPressOptions; @@ -26,8 +26,8 @@ public class AndroidTouchTest extends BaseAndroidTest { @BeforeEach public void setUp() { - driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); - driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: terminateApp", Map.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", Map.of("appId", APP_ID)); } @Test public void dragNDropByElementTest() { diff --git a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java index 852723694..80b60ab28 100644 --- a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java @@ -16,8 +16,6 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumBy; import org.junit.jupiter.api.Test; import org.openqa.selenium.json.Json; @@ -25,6 +23,8 @@ import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; +import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -32,9 +32,9 @@ public class AndroidViewMatcherTest extends BaseEspressoTest { @Test public void testFindByViewMatcher() { - String selector = new Json().toJson(ImmutableMap.of( + String selector = new Json().toJson(Map.of( "name", "withText", - "args", ImmutableList.of("Animation"), + "args", List.of("Animation"), "class", "androidx.test.espresso.matcher.ViewMatchers" )); final WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java index 21142e631..e14343d75 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/test/java/io/appium/java_client/android/BaseAndroidTest.java @@ -16,13 +16,14 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import java.util.Map; + import static io.appium.java_client.TestResources.apiDemosApk; @SuppressWarnings("checkstyle:HideUtilityClassConstructor") @@ -65,7 +66,7 @@ public class BaseAndroidTest { public static void startActivity(String name) { driver.executeScript( "mobile: startActivity", - ImmutableMap.of( + Map.of( "component", String.format("%s/%s", APP_ID, name) ) ); diff --git a/src/test/java/io/appium/java_client/android/ClipboardTest.java b/src/test/java/io/appium/java_client/android/ClipboardTest.java index 7b576bcc2..8de3bda5c 100644 --- a/src/test/java/io/appium/java_client/android/ClipboardTest.java +++ b/src/test/java/io/appium/java_client/android/ClipboardTest.java @@ -16,17 +16,18 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.Map; + import static org.junit.jupiter.api.Assertions.assertEquals; public class ClipboardTest extends BaseAndroidTest { @BeforeEach public void setUp() { - driver.executeScript("mobile: terminateApp", ImmutableMap.of("appId", APP_ID)); - driver.executeScript("mobile: activateApp", ImmutableMap.of("appId", APP_ID)); + driver.executeScript("mobile: terminateApp", Map.of("appId", APP_ID)); + driver.executeScript("mobile: activateApp", Map.of("appId", APP_ID)); } @Test public void verifySetAndGetClipboardText() { diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java index 1c5848934..08bddc736 100644 --- a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java +++ b/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java @@ -1,12 +1,12 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.openqa.selenium.By.xpath; @@ -14,7 +14,7 @@ public class OpenNotificationsTest extends BaseAndroidTest { @Test public void openNotification() { - driver.executeScript("mobile: terminateApp", ImmutableMap.of( + driver.executeScript("mobile: terminateApp", Map.of( "appId", APP_ID )); driver.openNotifications(); diff --git a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java index 7a22ffd93..4ab700ca3 100644 --- a/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java +++ b/src/test/java/io/appium/java_client/drivers/options/OptionsBuildingTest.java @@ -16,8 +16,6 @@ package io.appium.java_client.drivers.options; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.options.EspressoOptions; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.android.options.localization.AppLocale; @@ -42,6 +40,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; +import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -60,7 +60,7 @@ public void canBuildXcuiTestOptions() throws MalformedURLException { .setWdaBaseUrl("http://localhost:8000") .setPermissions(new Permissions() .withAppPermissions("com.apple.MobileSafari", - ImmutableMap.of("calendar", "YES"))) + Map.of("calendar", "YES"))) .setSafariSocketChunkSize(10) .setCommandTimeouts(new CommandTimeouts() .withCommandTimeout("yolo", Duration.ofSeconds(1))); @@ -105,7 +105,7 @@ public void canBuildEspressoOptions() { .withLanguage("zh") .withVariant("hans")) .setEspressoBuildConfig(new EspressoBuildConfig() - .withAdditionalAppDependencies(ImmutableList.of( + .withAdditionalAppDependencies(List.of( "com.dep1:1.2.3", "com.dep2:1.2.3" )) @@ -154,7 +154,7 @@ public void canBuildGeckoOptions() { assertEquals(AutomationName.GECKO, options.getAutomationName().orElse(null)); options.setNewCommandTimeout(Duration.ofSeconds(10)) .setVerbosity(Verbosity.TRACE) - .setMozFirefoxOptions(ImmutableMap.of( + .setMozFirefoxOptions(Map.of( "profile", "yolo" )); assertEquals(Duration.ofSeconds(10), options.getNewCommandTimeout().orElse(null)); diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java index 9b6af0820..c07df5b68 100644 --- a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -16,7 +16,6 @@ package io.appium.java_client.events.stubs; -import com.google.common.collect.ImmutableList; import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; @@ -46,7 +45,7 @@ public EmptyWebDriver() { } private static List createStubList() { - return ImmutableList.of(new StubWebElement(), new StubWebElement()); + return List.of(new StubWebElement(), new StubWebElement()); } public WebDriver context(String name) { diff --git a/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java b/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java index 5a50dc58a..a84708083 100644 --- a/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java +++ b/src/test/java/io/appium/java_client/events/stubs/StubWebElement.java @@ -16,7 +16,6 @@ package io.appium.java_client.events.stubs; -import com.google.common.collect.ImmutableList; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.OutputType; @@ -33,7 +32,7 @@ public StubWebElement() { } private static List createStubSubElementList() { - return new ArrayList<>(ImmutableList.of(new StubWebElement(), new StubWebElement())); + return new ArrayList<>(List.of(new StubWebElement(), new StubWebElement())); } public void click() { diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index 6ead922b8..b5d718eb8 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -16,7 +16,6 @@ package io.appium.java_client.ios; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -30,6 +29,7 @@ import org.openqa.selenium.remote.http.HttpMethod; import java.time.Duration; +import java.util.Map; import static io.appium.java_client.TestUtils.waitUntilTrue; import static org.hamcrest.MatcherAssert.assertThat; @@ -71,7 +71,7 @@ public void addCustomCommandWithElementIdTest() { String.format("/session/%s/appium/element/%s/value", driver.getSessionId(), ((RemoteWebElement) intA).getId()), "setNewValue"); final Response setNewValue = driver.execute("setNewValue", - ImmutableMap.of("id", ((RemoteWebElement) intA).getId(), "text", "8")); + Map.of("id", ((RemoteWebElement) intA).getId(), "text", "8")); assertNotNull(setNewValue.getSessionId()); } @@ -82,8 +82,8 @@ public void getDeviceTimeTest() { } @Test public void resetTest() { - driver.executeScript("mobile: terminateApp", ImmutableMap.of("bundleId", BUNDLE_ID)); - driver.executeScript("mobile: activateApp", ImmutableMap.of("bundleId", BUNDLE_ID)); + driver.executeScript("mobile: terminateApp", Map.of("bundleId", BUNDLE_ID)); + driver.executeScript("mobile: activateApp", Map.of("bundleId", BUNDLE_ID)); } @Disabled diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index 6f7dbb1c9..636d33c4e 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -17,7 +17,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -import static com.google.common.collect.ImmutableList.of; import static io.appium.java_client.remote.AutomationName.ANDROID_UIAUTOMATOR2; import static io.appium.java_client.remote.AutomationName.IOS_XCUI_TEST; import static io.appium.java_client.remote.MobilePlatform.ANDROID; @@ -61,7 +60,7 @@ public String getTitle() { @Override public List findElements(By by) { - return of(new StubWebElement(this, by), new StubWebElement(this, by)); + return List.of(new StubWebElement(this, by), new StubWebElement(this, by)); } @Override diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java index 0e6bc08b7..5977646d7 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java @@ -1,6 +1,5 @@ package io.appium.java_client.pagefactory_tests.widget.tests; -import com.google.common.collect.ImmutableList; import io.appium.java_client.pagefactory.Widget; import org.openqa.selenium.WebElement; @@ -16,7 +15,7 @@ public T getSubWidget() { } public List getSubWidgets() { - return ImmutableList.of(); + return List.of(); } @Override diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java index 43f0864ac..94fd5a8db 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/StubWebElement.java @@ -12,16 +12,15 @@ import java.util.List; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.ImmutableList.of; +import static java.util.Objects.requireNonNull; public class StubWebElement implements WebElement, WrapsDriver { private final WebDriver driver; private final By by; public StubWebElement(WebDriver driver, By by) { - this.driver = checkNotNull(driver); - this.by = checkNotNull(by); + this.driver = requireNonNull(driver); + this.by = requireNonNull(by); } @Override @@ -70,8 +69,8 @@ public String getText() { } @Override - public List findElements(By by) { - return of(new StubWebElement(driver, by), new StubWebElement(driver, by)); + public List findElements(By by) { + return List.of(new StubWebElement(driver, by), new StubWebElement(driver, by)); } @Override diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java index aae940553..9822e9417 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -1,6 +1,5 @@ package io.appium.java_client.service.local; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.android.options.UiAutomator2Options; import io.github.bonigarcia.wdm.WebDriverManager; import org.junit.jupiter.api.AfterEach; @@ -14,6 +13,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static io.appium.java_client.TestResources.apiDemosApk; import static io.appium.java_client.TestUtils.getLocalIp4Address; @@ -179,7 +179,7 @@ void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { .amend("unixPath", "/selenium/app.apk") .amend("quotes", "\"'") .setChromeOptions( - ImmutableMap.of("env", ImmutableMap.of("test", "value"), "val2", 0) + Map.of("env", Map.of("test", "value"), "val2", 0) ); service = new AppiumServiceBuilder() From fac489f8cec390fbd3b6df7de28cc5e135a69a63 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 22 Oct 2023 19:29:12 +0200 Subject: [PATCH 279/501] fix: Properly unwrap driver instance if the ContextAware object is deeply nested (#2052) --- .../pagefactory/AppiumFieldDecorator.java | 47 ++++++------ .../utils/WebDriverUnpackUtility.java | 72 +++++++++++-------- 2 files changed, 65 insertions(+), 54 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 67af93096..280cd02d1 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -19,7 +19,6 @@ import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; -import org.openqa.selenium.Capabilities; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; @@ -46,7 +45,7 @@ import java.util.Map; import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; -import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; +import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackObjectFromSearchContext; import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; import static java.time.Duration.ofSeconds; @@ -82,23 +81,15 @@ public class AppiumFieldDecorator implements FieldDecorator { * @param duration is a desired duration of the waiting for an element presence. */ public AppiumFieldDecorator(SearchContext context, Duration duration) { - WebDriver wd = unpackWebDriverFromSearchContext(context); - this.webDriverReference = wd == null ? null : new WeakReference<>(wd); - if (wd instanceof HasCapabilities) { - Capabilities caps = ((HasCapabilities) wd).getCapabilities(); - this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); - this.automation = CapabilityHelpers.getCapability(caps, AUTOMATION_NAME_OPTION, String.class); - } else { - this.platform = null; - this.automation = null; - } - + this.webDriverReference = unpackObjectFromSearchContext(context, WebDriver.class) + .map(WeakReference::new).orElse(null); + this.platform = readStringCapability(context, CapabilityType.PLATFORM_NAME); + this.automation = readStringCapability(context, AUTOMATION_NAME_OPTION); this.duration = duration; defaultElementFieldDecorator = createFieldDecorator(new AppiumElementLocatorFactory( context, duration, new DefaultElementByBuilder(platform, automation) )); - widgetLocatorFactory = new AppiumElementLocatorFactory( context, duration, new WidgetByBuilder(platform, automation) ); @@ -117,28 +108,32 @@ public AppiumFieldDecorator(SearchContext context) { * @param duration is a desired duration of the waiting for an element presence. */ AppiumFieldDecorator(WeakReference contextReference, Duration duration) { - WebDriver wd = unpackWebDriverFromSearchContext(contextReference.get()); - this.webDriverReference = wd == null ? null : new WeakReference<>(wd); - if (wd instanceof HasCapabilities) { - Capabilities caps = ((HasCapabilities) wd).getCapabilities(); - this.platform = CapabilityHelpers.getCapability(caps, CapabilityType.PLATFORM_NAME, String.class); - this.automation = CapabilityHelpers.getCapability(caps, AUTOMATION_NAME_OPTION, String.class); - } else { - this.platform = null; - this.automation = null; - } - + var cr = contextReference.get(); + this.webDriverReference = unpackObjectFromSearchContext(cr, WebDriver.class) + .map(WeakReference::new).orElse(null); + this.platform = readStringCapability(cr, CapabilityType.PLATFORM_NAME); + this.automation = readStringCapability(cr, AUTOMATION_NAME_OPTION); this.duration = duration; defaultElementFieldDecorator = createFieldDecorator(new AppiumElementLocatorFactory( contextReference, duration, new DefaultElementByBuilder(platform, automation) )); - widgetLocatorFactory = new AppiumElementLocatorFactory( contextReference, duration, new WidgetByBuilder(platform, automation) ); } + @Nullable + private String readStringCapability(SearchContext searchContext, String capName) { + if (searchContext == null) { + return null; + } + return unpackObjectFromSearchContext(searchContext, HasCapabilities.class) + .map(HasCapabilities::getCapabilities) + .map(caps -> CapabilityHelpers.getCapability(caps, capName, String.class)) + .orElse(null); + } + private DefaultFieldDecorator createFieldDecorator(ElementLocatorFactory factory) { return new DefaultFieldDecorator(factory) { @Override diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 01cc25a7e..190f9c4ae 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -26,9 +26,10 @@ import javax.annotation.Nullable; +import java.util.Optional; + import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; -import static java.util.Optional.ofNullable; public final class WebDriverUnpackUtility { private static final String NATIVE_APP_PATTERN = "NATIVE_APP"; @@ -37,35 +38,53 @@ private WebDriverUnpackUtility() { } /** - * This method extract an instance of {@link WebDriver} from the given {@link SearchContext}. + * This method extracts an instance of the given interface from the given {@link SearchContext}. + * It is expected that the {@link SearchContext} itself or the object it wraps implements it. + * * @param searchContext is an instance of {@link SearchContext}. It may be the instance of * {@link WebDriver} or {@link org.openqa.selenium.WebElement} or some other * user's extension/implementation. * Note: if you want to use your own implementation then it should implement * {@link WrapsDriver} or {@link WrapsElement} - * @return the instance of {@link WebDriver}. - * Note: if the given {@link SearchContext} is not - * {@link WebDriver} and it doesn't implement - * {@link WrapsDriver} or {@link WrapsElement} then this method returns null. - * + * @param cls interface whose instance is going to be extracted. + * @return Either an instance of the given interface or Optional.empty(). */ - @Nullable - public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchContext) { - if (searchContext instanceof WebDriver) { - return (WebDriver) searchContext; + public static Optional unpackObjectFromSearchContext(@Nullable SearchContext searchContext, Class cls) { + if (searchContext == null) { + return Optional.empty(); } + if (cls.isAssignableFrom(searchContext.getClass())) { + return Optional.of(cls.cast(searchContext)); + } if (searchContext instanceof WrapsDriver) { - return unpackWebDriverFromSearchContext(((WrapsDriver) searchContext).getWrappedDriver()); + return unpackObjectFromSearchContext(((WrapsDriver) searchContext).getWrappedDriver(), cls); } - // Search context it is not only WebDriver. WebElement is search context too. // RemoteWebElement implements WrapsDriver if (searchContext instanceof WrapsElement) { - return unpackWebDriverFromSearchContext(((WrapsElement) searchContext).getWrappedElement()); + return unpackObjectFromSearchContext(((WrapsElement) searchContext).getWrappedElement(), cls); } - return null; + return Optional.empty(); + } + + /** + * This method extract an instance of {@link WebDriver} from the given {@link SearchContext}. + * @param searchContext is an instance of {@link SearchContext}. It may be the instance of + * {@link WebDriver} or {@link org.openqa.selenium.WebElement} or some other + * user's extension/implementation. + * Note: if you want to use your own implementation then it should implement + * {@link WrapsDriver} or {@link WrapsElement} + * @return the instance of {@link WebDriver}. + * Note: if the given {@link SearchContext} is not + * {@link WebDriver} and it doesn't implement + * {@link WrapsDriver} or {@link WrapsElement} then this method returns null. + * + */ + @Nullable + public static WebDriver unpackWebDriverFromSearchContext(@Nullable SearchContext searchContext) { + return unpackObjectFromSearchContext(searchContext, WebDriver.class).orElse(null); } /** @@ -83,20 +102,17 @@ public static WebDriver unpackWebDriverFromSearchContext(SearchContext searchCon * {@link SearchContext} instance doesn't implement {@link ContextAware} and {@link WrapsDriver} */ public static ContentType getCurrentContentType(SearchContext context) { - return ofNullable(unpackWebDriverFromSearchContext(context)).map(driver -> { - if (driver instanceof HasBrowserCheck && !((HasBrowserCheck) driver).isBrowser()) { - return NATIVE_MOBILE_SPECIFIC; - } + var browserCheckHolder = unpackObjectFromSearchContext(context, HasBrowserCheck.class); + if (browserCheckHolder.filter(hbc -> !hbc.isBrowser()).isPresent()) { + return NATIVE_MOBILE_SPECIFIC; + } - if (ContextAware.class.isAssignableFrom(driver.getClass())) { //it is desktop browser - ContextAware contextAware = (ContextAware) driver; - var currentContext = contextAware.getContext(); - if (currentContext != null && currentContext.toUpperCase().contains(NATIVE_APP_PATTERN)) { - return NATIVE_MOBILE_SPECIFIC; - } - } + var contextAware = unpackObjectFromSearchContext(context, ContextAware.class); + if (contextAware.map(ContextAware::getContext) + .filter(c -> c.toUpperCase().contains(NATIVE_APP_PATTERN)).isPresent()) { + return NATIVE_MOBILE_SPECIFIC; + } - return HTML_OR_DEFAULT; - }).orElse(HTML_OR_DEFAULT); + return HTML_OR_DEFAULT; } } From 735e9fbddc89cd5ffc383bd6163b9f8f92cc9717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 20:21:20 +0300 Subject: [PATCH 280/501] build(deps): Bump org.owasp.dependencycheck from 8.4.0 to 8.4.2 (#2053) Bumps org.owasp.dependencycheck from 8.4.0 to 8.4.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a5c3c2681..6db928d7a 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.4.0' + id 'org.owasp.dependencycheck' version '8.4.2' id 'com.github.johnrengelman.shadow' version '8.1.1' } From e7b2436875619993980d9eee61446c72222f72e4 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Oct 2023 09:18:25 +0300 Subject: [PATCH 281/501] chore: Optimize and clean up Gradle build script (#2056) --- build.gradle | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 6db928d7a..874bbf21b 100644 --- a/build.gradle +++ b/build.gradle @@ -67,12 +67,6 @@ dependencies { testRuntimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" } -ext { - Sources = fileTree("$buildDir/src/main/java").include('**/*.java') - Tests = fileTree("$buildDir/src/test/java").include('**/*.java') - Docs = file("$buildDir/doc") -} - dependencyCheck { failBuildOnCVSS=22 } @@ -81,7 +75,7 @@ jacoco { toolVersion = '0.8.8' } -tasks.withType(JacocoReport) { +tasks.withType(JacocoReport).configureEach { description = 'Generate Jacoco coverage reports after running tests' sourceSets sourceSets.main reports { @@ -209,7 +203,7 @@ test { finalizedBy jacocoTestReport } -task xcuiTest( type: Test ) { +tasks.register('xcuiTest', Test) { useJUnitPlatform() testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' @@ -224,7 +218,7 @@ task xcuiTest( type: Test ) { } } -task uiAutomationTest( type: Test ) { +tasks.register('uiAutomationTest', Test) { useJUnitPlatform() testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' From 2df9f5229ba58c1fada1533a0f8d438d4ceddad4 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 25 Oct 2023 14:03:26 +0300 Subject: [PATCH 282/501] build: Enable Checkstyle SingleSpaceSeparator check (#2057) --- config/checkstyle/appium-style.xml | 1 + .../java_client/android/AndroidMobileCommandHelper.java | 6 +++--- .../android/SupportsSpecialEmulatorCommands.java | 2 +- .../android/connection/HasNetworkConnection.java | 2 +- .../io/appium/java_client/functions/AppiumFunction.java | 2 +- .../ios/options/other/SupportsCommandTimeoutsOption.java | 2 +- .../io/appium/java_client/serverevents/ServerEvents.java | 2 +- .../io/appium/java_client/android/AndroidSearchingTest.java | 4 ++-- .../appium/java_client/pagefactory_tests/TimeoutTest.java | 2 +- 9 files changed, 12 insertions(+), 11 deletions(-) diff --git a/config/checkstyle/appium-style.xml b/config/checkstyle/appium-style.xml index 630949b66..b7473e937 100755 --- a/config/checkstyle/appium-style.xml +++ b/config/checkstyle/appium-style.xml @@ -63,6 +63,7 @@
+ 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 50a7256a5..8c294c4c0 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -91,7 +91,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { return Map.entry(GET_PERFORMANCE_DATA, Map.of( "packageName", packageName, "dataType", dataType, - "dataReadTimeout", dataReadTimeout + "dataReadTimeout", dataReadTimeout )); } @@ -201,7 +201,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments. */ @Deprecated - public static Map.Entry> replaceElementValueCommand( + public static Map.Entry> replaceElementValueCommand( RemoteWebElement remoteWebElement, String value) { return Map.entry(REPLACE_VALUE, Map.of( "id", remoteWebElement.getId(), @@ -241,7 +241,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { String phoneNumber, GsmCallActions gsmCallActions) { return Map.entry(GSM_CALL, Map.of( "phoneNumber", phoneNumber, - "action", gsmCallActions.name().toLowerCase() + "action", gsmCallActions.name().toLowerCase() )); } diff --git a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java index c7b9accaf..c60d8eaf9 100644 --- a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java +++ b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java @@ -34,7 +34,7 @@ default void sendSMS(String phoneNumber, String message) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), - Map.entry(SEND_SMS, Map.of( + Map.entry(SEND_SMS, Map.of( "phoneNumber", phoneNumber, "message", message )) diff --git a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java index 03d1381f0..a00693af3 100644 --- a/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java +++ b/src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java @@ -71,7 +71,7 @@ default ConnectionState getConnection() { return new ConnectionState( ((boolean) result.get("wifi") ? ConnectionState.WIFI_MASK : 0) | ((boolean) result.get("data") ? ConnectionState.DATA_MASK : 0) - | ((boolean) result.get("airplaneMode") ? ConnectionState.AIRPLANE_MODE_MASK : 0) + | ((boolean) result.get("airplaneMode") ? ConnectionState.AIRPLANE_MODE_MASK : 0) ); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback diff --git a/src/main/java/io/appium/java_client/functions/AppiumFunction.java b/src/main/java/io/appium/java_client/functions/AppiumFunction.java index de9069d37..cd621a803 100644 --- a/src/main/java/io/appium/java_client/functions/AppiumFunction.java +++ b/src/main/java/io/appium/java_client/functions/AppiumFunction.java @@ -30,7 +30,7 @@ * @param The return type */ @FunctionalInterface -public interface AppiumFunction extends Function, java.util.function.Function { +public interface AppiumFunction extends Function, java.util.function.Function { @Override default AppiumFunction compose(java.util.function.Function before) { Objects.requireNonNull(before); diff --git a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java index 4461985c1..d19e6272f 100644 --- a/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java +++ b/src/main/java/io/appium/java_client/ios/options/other/SupportsCommandTimeoutsOption.java @@ -62,7 +62,7 @@ default T setCommandTimeouts(Duration timeout) { default Optional> getCommandTimeouts() { return Optional.ofNullable(getCapability(COMMAND_TIMEOUTS_OPTION)) .map(String::valueOf) - .map(v -> v.trim().startsWith("{") + .map(v -> v.trim().startsWith("{") ? Either.left(new CommandTimeouts(v)) : Either.right(toDuration(v)) ); diff --git a/src/main/java/io/appium/java_client/serverevents/ServerEvents.java b/src/main/java/io/appium/java_client/serverevents/ServerEvents.java index 283aa3b66..624dd1707 100644 --- a/src/main/java/io/appium/java_client/serverevents/ServerEvents.java +++ b/src/main/java/io/appium/java_client/serverevents/ServerEvents.java @@ -14,7 +14,7 @@ public class ServerEvents { public final List events; public final String jsonData; - public void save(Path output) throws IOException { + public void save(Path output) throws IOException { Files.write(output, this.jsonData.getBytes()); } } \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java index 64390962d..fb9275943 100644 --- a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java @@ -33,12 +33,12 @@ public void setup() { startActivity(".ApiDemos"); } - @Test public void findByAccessibilityIdTest() { + @Test public void findByAccessibilityIdTest() { assertNotEquals(driver.findElement(AppiumBy.accessibilityId("Graphics")).getText(), null); assertEquals(driver.findElements(AppiumBy.accessibilityId("Graphics")).size(), 1); } - @Test public void findByAndroidUIAutomatorTest() { + @Test public void findByAndroidUIAutomatorTest() { assertNotEquals(driver .findElement(AppiumBy .androidUIAutomator("new UiSelector().clickable(true)")).getText(), null); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java index 1ae9157a3..a9d44562d 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java @@ -69,7 +69,7 @@ private static long getPerformanceDiff(long expectedMs, Runnable runnable) { long startMark = currentTimeMillis(); runnable.run(); long endMark = currentTimeMillis(); - return abs(expectedMs - (endMark - startMark)); + return abs(expectedMs - (endMark - startMark)); } private static String assertionMessage(Duration expectedDuration) { From 6ca79e4ceea7b5f80ca7cac0b15fa251bb313fff Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 26 Oct 2023 12:04:54 +0300 Subject: [PATCH 283/501] refactor: Migrate to new Selenium API for process management (#2054) --- .../local/AppiumDriverLocalService.java | 71 +++++-------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 0bd223034..45f611eab 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -17,10 +17,9 @@ package io.appium.java_client.service.local; import com.google.common.annotations.VisibleForTesting; -import io.appium.java_client.internal.ReflectionHelpers; import lombok.SneakyThrows; import org.openqa.selenium.net.UrlChecker; -import org.openqa.selenium.os.CommandLine; +import org.openqa.selenium.os.ExternalProcess; import org.openqa.selenium.remote.service.DriverService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,6 +48,7 @@ import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP6_ADDRESS; import static java.util.Objects.requireNonNull; +import static java.util.Optional.ofNullable; import static org.slf4j.event.Level.DEBUG; import static org.slf4j.event.Level.INFO; @@ -70,7 +70,7 @@ public final class AppiumDriverLocalService extends DriverService { private final URL url; private String basePath; - private CommandLine process = null; + private ExternalProcess process = null; AppiumDriverLocalService(String ipAddress, File nodeJSExec, int nodeJSPort, Duration startupTimeout, @@ -126,7 +126,7 @@ public URL getUrl() { public boolean isRunning() { lock.lock(); try { - if (process == null || !process.isRunning()) { + if (process == null || !process.isAlive()) { return false; } @@ -172,17 +172,15 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { } try { - process = new CommandLine( - this.nodeJSExec.getCanonicalPath(), - nodeJSArgs.toArray(new String[]{}) - ); - process.setEnvironmentVariables(nodeJSEnvironment); - process.copyOutputTo(stream); - process.executeAsync(); + ExternalProcess.Builder processBuilder = ExternalProcess.builder() + .command(this.nodeJSExec.getCanonicalPath(), nodeJSArgs) + .copyOutputTo(stream); + nodeJSEnvironment.forEach(processBuilder::environment); + process = processBuilder.start(); ping(startupTimeout); } catch (Exception e) { - final Optional output = Optional.ofNullable(process) - .map(CommandLine::getStdOut) + final Optional output = ofNullable(process) + .map(ExternalProcess::getOutput) .filter(o -> !isNullOrEmpty(o)); destroyProcess(); List errorLines = new ArrayList<>(); @@ -227,47 +225,16 @@ public void stop() { } } - /** - * Destroys the service if it is running. - * - * @param timeout The maximum time to wait before the process will be force-killed. - * @return The exit code of the process or zero if the process was not running. - */ - private int destroyProcess(Duration timeout) { - if (process == null || !process.isRunning()) { - return 0; - } - - // This all magic is necessary, because Selenium does not publicly expose - // process killing timeouts. By default a process is killed forcibly if - // it does not exit after two seconds, which is in most cases not enough for - // Appium - try { - Object osProcess = ReflectionHelpers.getPrivateFieldValue( - process.getClass(), process, "process", Object.class - ); - Object watchdog = ReflectionHelpers.getPrivateFieldValue( - osProcess.getClass(), osProcess, "executeWatchdog", Object.class - ); - Process nativeProcess = ReflectionHelpers.getPrivateFieldValue( - watchdog.getClass(), watchdog, "process", Process.class - ); - nativeProcess.destroy(); - nativeProcess.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS); - } catch (Exception e) { - LOG.warn("No explicit timeout could be applied to the process termination", e); - } - - return process.destroy(); - } - /** * Destroys the service. - * This methods waits up to `DESTROY_TIMEOUT` seconds for the Appium service + * This method waits up to `DESTROY_TIMEOUT` seconds for the Appium service * to exit gracefully. */ private void destroyProcess() { - destroyProcess(DESTROY_TIMEOUT); + if (process == null || !process.isAlive()) { + return; + } + process.shutdown(DESTROY_TIMEOUT); } /** @@ -277,11 +244,7 @@ private void destroyProcess() { */ @Nullable public String getStdOut() { - if (process != null) { - return process.getStdOut(); - } - - return null; + return ofNullable(process).map(ExternalProcess::getOutput).orElse(null); } /** From a6ebbeb7957bcb116714e76a5a357d50e02bd51d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 26 Oct 2023 12:06:12 +0300 Subject: [PATCH 284/501] refactor: Deprecate custom functional interfaces (#2055) --- .../io/appium/java_client/functions/ActionSupplier.java | 6 ++++++ .../io/appium/java_client/functions/AppiumFunction.java | 2 ++ .../io/appium/java_client/functions/ExpectedCondition.java | 2 ++ 3 files changed, 10 insertions(+) diff --git a/src/main/java/io/appium/java_client/functions/ActionSupplier.java b/src/main/java/io/appium/java_client/functions/ActionSupplier.java index 9554bf6ff..67ea8b888 100644 --- a/src/main/java/io/appium/java_client/functions/ActionSupplier.java +++ b/src/main/java/io/appium/java_client/functions/ActionSupplier.java @@ -20,6 +20,12 @@ import java.util.function.Supplier; +/** + * Represents a supplier of actions. + * + * @deprecated Use {@link Supplier} instead + */ +@Deprecated @FunctionalInterface public interface ActionSupplier> extends Supplier { } diff --git a/src/main/java/io/appium/java_client/functions/AppiumFunction.java b/src/main/java/io/appium/java_client/functions/AppiumFunction.java index cd621a803..e23dcb298 100644 --- a/src/main/java/io/appium/java_client/functions/AppiumFunction.java +++ b/src/main/java/io/appium/java_client/functions/AppiumFunction.java @@ -28,7 +28,9 @@ * * @param The input type * @param The return type + * @deprecated Use {@link java.util.function.Function} instead */ +@Deprecated @FunctionalInterface public interface AppiumFunction extends Function, java.util.function.Function { diff --git a/src/main/java/io/appium/java_client/functions/ExpectedCondition.java b/src/main/java/io/appium/java_client/functions/ExpectedCondition.java index 885952525..926577c53 100644 --- a/src/main/java/io/appium/java_client/functions/ExpectedCondition.java +++ b/src/main/java/io/appium/java_client/functions/ExpectedCondition.java @@ -23,7 +23,9 @@ * with {@link java.util.function.Function}. * * @param The return type + * @deprecated Use {@link org.openqa.selenium.support.ui.ExpectedCondition} instead */ +@Deprecated @FunctionalInterface public interface ExpectedCondition extends org.openqa.selenium.support.ui.ExpectedCondition, AppiumFunction { From 5ab1117d16b78e8a13bb42a2b6b10d0c54b0af55 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 1 Nov 2023 22:35:11 +0100 Subject: [PATCH 285/501] ci: Skip Android emulator caching (#2065) --- .github/workflows/gradle.yml | 48 ++++++++++-------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5d15dfbc2..f5f601dd4 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -5,25 +5,26 @@ on: branches: - master paths-ignore: - - 'docs/**' - - '*.md' + - 'docs/**' + - '*.md' pull_request: branches: - master paths-ignore: - - 'docs/**' - - '*.md' + - 'docs/**' + - '*.md' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: - ANDROID_SDK_VERSION: 28 + ANDROID_SDK_VERSION: "28" ANDROID_EMU_NAME: test - XCODE_VERSION: 14.2 + ANDROID_EMU_TARGET: default + XCODE_VERSION: "14.2" IOS_DEVICE_NAME: iPhone 12 - IOS_PLATFORM_VERSION: 16.2 + IOS_PLATFORM_VERSION: "16.2" jobs: build: @@ -59,7 +60,7 @@ jobs: run: ./gradlew clean build - name: Install Node.js - if: ${{ matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' }} + if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' uses: actions/setup-node@v3 with: node-version: 'lts/*' @@ -71,50 +72,28 @@ jobs: - name: Install UIA2 driver if: matrix.e2e-tests == 'android' run: appium driver install uiautomator2 - - - name: AVD cache - if: matrix.e2e-tests == 'android' - uses: actions/cache@v3 - id: avd-cache - with: - path: | - ~/.android/avd/* - ~/.android/adb* - key: avd-${{ env.ANDROID_SDK_VERSION }} - - - name: Generate AVD snapshot for caching - if: matrix.e2e-tests == 'android' && steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: ${{ env.ANDROID_SDK_VERSION }} - avd-name: ${{ env.ANDROID_EMU_NAME }} - force-avd-creation: false - script: echo "Generated AVD snapshot for caching." - - name: Run Android E2E tests if: matrix.e2e-tests == 'android' uses: reactivecircus/android-emulator-runner@v2 with: + script: ./gradlew uiAutomationTest api-level: ${{ env.ANDROID_SDK_VERSION }} avd-name: ${{ env.ANDROID_EMU_NAME }} - force-avd-creation: false - emulator-options: -no-snapshot -delay-adb - script: ./gradlew uiAutomationTest + sdcard-path-or-size: 1500M + disable-spellchecker: true + target: ${{ env.ANDROID_EMU_TARGET }} - name: Select Xcode if: matrix.e2e-tests == 'ios' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: "${{ env.XCODE_VERSION }}" - - name: Install XCUITest driver if: matrix.e2e-tests == 'ios' run: appium driver install xcuitest - - name: Prebuild XCUITest driver if: matrix.e2e-tests == 'ios' run: appium driver run xcuitest build-wda - - name: Prepare iOS simulator if: matrix.e2e-tests == 'ios' run: | @@ -122,7 +101,6 @@ jobs: target_sim_id=$(xcrun simctl list devices available | grep "$IOS_DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) open -Fn "/Applications/Xcode_$XCODE_VERSION.app/Contents/Developer/Applications/Simulator.app" xcrun simctl bootstatus $target_sim_id -b - - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' run: ./gradlew xcuiTest From 9748d77457fca034de0bead993462e802ad97a68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:20:56 +0300 Subject: [PATCH 286/501] build(deps): Bump org.seleniumhq.selenium:selenium-bom (#2064) Bumps [org.seleniumhq.selenium:selenium-bom](https://github.com/SeleniumHQ/selenium) from 4.14.1 to 4.15.0. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Commits](https://github.com/SeleniumHQ/selenium/commits/selenium-4.15.0) --- updated-dependencies: - dependency-name: org.seleniumhq.selenium:selenium-bom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 874bbf21b..20647239f 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { exclude group: 'org.seleniumhq.selenium' } - testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.14.1') + testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.15.0') testImplementation 'org.seleniumhq.selenium:selenium-api' testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' testImplementation 'org.seleniumhq.selenium:selenium-support' From c17f77d467befcfbaccf23ae839cc9e7354f8a91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 23:37:07 +0300 Subject: [PATCH 287/501] build(deps): Bump actions/setup-node from 3 to 4 (#2060) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index f5f601dd4..2ee43a743 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -61,7 +61,7 @@ jobs: - name: Install Node.js if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 'lts/*' From 89046d543e4e8016727105c7fc00fadd91f12901 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 15:06:09 +0200 Subject: [PATCH 288/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2068) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.5.3 to 5.6.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.5.3...webdrivermanager-5.6.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 20647239f..67cb55f98 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.5.3') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.1') { exclude group: 'org.seleniumhq.selenium' } testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.15.0') From 5298e9c7be7893e1c879245f6e6bb5133f3a5fa5 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 6 Nov 2023 17:50:50 +0100 Subject: [PATCH 289/501] chore: Introduce better constructor argument validation for the AppiumFieldDecorator class (#2070) --- .../pagefactory/AppiumFieldDecorator.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 280cd02d1..05fa41a42 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -30,6 +30,7 @@ import org.openqa.selenium.support.pagefactory.ElementLocatorFactory; import org.openqa.selenium.support.pagefactory.FieldDecorator; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; @@ -44,6 +45,7 @@ import java.util.List; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackObjectFromSearchContext; import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; @@ -81,8 +83,7 @@ public class AppiumFieldDecorator implements FieldDecorator { * @param duration is a desired duration of the waiting for an element presence. */ public AppiumFieldDecorator(SearchContext context, Duration duration) { - this.webDriverReference = unpackObjectFromSearchContext(context, WebDriver.class) - .map(WeakReference::new).orElse(null); + this.webDriverReference = requireWebDriverReference(context); this.platform = readStringCapability(context, CapabilityType.PLATFORM_NAME); this.automation = readStringCapability(context, AUTOMATION_NAME_OPTION); this.duration = duration; @@ -109,8 +110,7 @@ public AppiumFieldDecorator(SearchContext context) { */ AppiumFieldDecorator(WeakReference contextReference, Duration duration) { var cr = contextReference.get(); - this.webDriverReference = unpackObjectFromSearchContext(cr, WebDriver.class) - .map(WeakReference::new).orElse(null); + this.webDriverReference = requireWebDriverReference(cr); this.platform = readStringCapability(cr, CapabilityType.PLATFORM_NAME); this.automation = readStringCapability(cr, AUTOMATION_NAME_OPTION); this.duration = duration; @@ -123,6 +123,22 @@ contextReference, duration, new WidgetByBuilder(platform, automation) ); } + @Nonnull + private static WeakReference requireWebDriverReference(SearchContext searchContext) { + var wd = unpackObjectFromSearchContext( + checkNotNull(searchContext, "The provided search context cannot be null"), + WebDriver.class + ); + return wd.map(WeakReference::new) + .orElseThrow(() -> new IllegalArgumentException( + String.format( + "No driver implementing %s interface could be extracted from the %s instance. " + + "Is the provided search context valid?", + WebDriver.class.getName(), searchContext.getClass().getName() + ) + )); + } + @Nullable private String readStringCapability(SearchContext searchContext, String capName) { if (searchContext == null) { From 4914ab86dc826f860488e7e30b5e0e6fc754216a Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 7 Nov 2023 10:01:23 +0200 Subject: [PATCH 290/501] build(deps): Bump JaCoCo from `0.8.8` to `0.8.11` (#2071) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 67cb55f98..b1b3b8843 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ dependencyCheck { } jacoco { - toolVersion = '0.8.8' + toolVersion = '0.8.11' } tasks.withType(JacocoReport).configureEach { From 482748c912acfbcb51192bd8b91e4198e28e6d06 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 7 Nov 2023 12:27:56 +0100 Subject: [PATCH 291/501] fix: Update hashing and iteration logic of page object items (#2067) --- .github/workflows/gradle.yml | 11 ++-- build.gradle | 50 +++++++++++-------- .../pagefactory/bys/builder/ByChained.java | 12 ++--- .../InterceptorOfAListOfElements.java | 4 +- .../InterceptorOfASingleElement.java | 16 +++++- .../pagefactory/utils/ProxyFactory.java | 5 +- .../AndroidPageObjectTest.java | 25 +++++++++- 7 files changed, 86 insertions(+), 37 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2ee43a743..282526a5f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -57,7 +57,12 @@ jobs: cache: 'gradle' - name: Build with Gradle - run: ./gradlew clean build + run: | + latest_snapshot=$(curl -sf https://oss.sonatype.org/content/repositories/snapshots/org/seleniumhq/selenium/selenium-api/ | \ + python -c "import sys,re; print(re.findall(r'\d+\.\d+\.\d+-SNAPSHOT', sys.stdin.read())[-1])") + echo ">>> $latest_snapshot" + echo "latest_snapshot=$latest_snapshot" >> "$GITHUB_ENV" + ./gradlew clean build -PisCI -Pselenium.version=$latest_snapshot - name: Install Node.js if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' @@ -76,7 +81,7 @@ jobs: if: matrix.e2e-tests == 'android' uses: reactivecircus/android-emulator-runner@v2 with: - script: ./gradlew uiAutomationTest + script: ./gradlew uiAutomationTest -PisCI -Pselenium.version=$latest_snapshot api-level: ${{ env.ANDROID_SDK_VERSION }} avd-name: ${{ env.ANDROID_EMU_NAME }} sdcard-path-or-size: 1500M @@ -103,4 +108,4 @@ jobs: xcrun simctl bootstatus $target_sim_id -b - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' - run: ./gradlew xcuiTest + run: ./gradlew xcuiTest -PisCI -Pselenium.version=$latest_snapshot diff --git a/build.gradle b/build.gradle index b1b3b8843..603ab21e7 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,15 @@ plugins { repositories { mavenCentral() + + if (project.hasProperty("isCI")) { + maven { + url uri('https://oss.sonatype.org/content/repositories/snapshots/') + mavenContent { + snapshotsOnly() + } + } + } } java { @@ -32,22 +41,28 @@ dependencies { compileOnly 'org.projectlombok:lombok:1.18.30' annotationProcessor 'org.projectlombok:lombok:1.18.30' - api ('org.seleniumhq.selenium:selenium-api') { - version { - strictly "[${seleniumVersion}, 5.0)" - prefer "${seleniumVersion}" + if (project.hasProperty("isCI")) { + api "org.seleniumhq.selenium:selenium-api:${seleniumVersion}" + api "org.seleniumhq.selenium:selenium-remote-driver:${seleniumVersion}" + api "org.seleniumhq.selenium:selenium-support:${seleniumVersion}" + } else { + api('org.seleniumhq.selenium:selenium-api') { + version { + strictly "[${seleniumVersion}, 5.0)" + prefer "${seleniumVersion}" + } } - } - api ('org.seleniumhq.selenium:selenium-remote-driver') { - version { - strictly "[${seleniumVersion}, 5.0)" - prefer "${seleniumVersion}" + api('org.seleniumhq.selenium:selenium-remote-driver') { + version { + strictly "[${seleniumVersion}, 5.0)" + prefer "${seleniumVersion}" + } } - } - api ('org.seleniumhq.selenium:selenium-support') { - version { - strictly "[${seleniumVersion}, 5.0)" - prefer "${seleniumVersion}" + api('org.seleniumhq.selenium:selenium-support') { + version { + strictly "[${seleniumVersion}, 5.0)" + prefer "${seleniumVersion}" + } } } implementation 'com.google.code.gson:gson:2.10.1' @@ -59,11 +74,7 @@ dependencies { testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.1') { exclude group: 'org.seleniumhq.selenium' } - testImplementation platform(group: 'org.seleniumhq.selenium', name: 'selenium-bom', version: '4.15.0') - testImplementation 'org.seleniumhq.selenium:selenium-api' - testImplementation 'org.seleniumhq.selenium:selenium-remote-driver' - testImplementation 'org.seleniumhq.selenium:selenium-support' - testImplementation 'org.seleniumhq.selenium:selenium-chrome-driver' + testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" testRuntimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" } @@ -228,7 +239,6 @@ tasks.register('uiAutomationTest', Test) { includeTestsMatching 'io.appium.java_client.android.OpenNotificationsTest' includeTestsMatching '*.AndroidAppStringsTest' includeTestsMatching '*.pagefactory_tests.widget.tests.android.*' - includeTestsMatching '*.pagefactory_tests.widget.tests.AndroidPageObjectTest' includeTestsMatching 'io.appium.java_client.service.local.StartingAppLocallyAndroidTest' includeTestsMatching 'io.appium.java_client.service.local.ServerBuilderTest' includeTestsMatching 'io.appium.java_client.service.local.ThreadSafetyTest' diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java index 2f44463ec..b92d2eb10 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java @@ -61,17 +61,15 @@ public ByChained(By[] bys) { @Override public WebElement findElement(SearchContext context) { Function searchingFunction = null; - for (By by: bys) { - searchingFunction = Optional.ofNullable(searchingFunction != null - ? searchingFunction.andThen(getSearchingFunction(by)) : null).orElse(getSearchingFunction(by)); + searchingFunction = Optional.ofNullable(searchingFunction) + .map(sf -> sf.andThen(getSearchingFunction(by))) + .orElseGet(() -> getSearchingFunction(by)); } - - FluentWait waiting = new FluentWait<>(context); + requireNonNull(searchingFunction); try { - requireNonNull(searchingFunction); - return waiting.until(searchingFunction); + return new FluentWait<>(context).until(searchingFunction); } catch (TimeoutException e) { throw new NoSuchElementException("Cannot locate an element using " + this); } diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java index 62e1442aa..fc35f9992 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java @@ -39,11 +39,11 @@ protected abstract Object getObject( @Override public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { - if (locator == null || Object.class.equals(method.getDeclaringClass())) { + if (locator == null || Object.class == method.getDeclaringClass()) { return original.call(); } - List realElements = new ArrayList<>(locator.findElements()); + final var realElements = new ArrayList<>(locator.findElements()); return getObject(realElements, method, args); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java index 7eea82233..738f49823 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java @@ -20,11 +20,13 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.WrapsDriver; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Method; +import java.util.Objects; import java.util.concurrent.Callable; public abstract class InterceptorOfASingleElement implements MethodCallListener { @@ -42,6 +44,15 @@ public InterceptorOfASingleElement( protected abstract Object getObject(WebElement element, Method method, Object[] args) throws Throwable; + private static boolean areElementsEqual(Object we1, Object we2) { + if (!(we1 instanceof RemoteWebElement) || !(we2 instanceof RemoteWebElement)) { + return false; + } + + return we1 == we2 + || (Objects.equals(((RemoteWebElement) we1).getId(), ((RemoteWebElement) we2).getId())); + } + @Override public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { if (locator == null) { @@ -52,7 +63,7 @@ public Object call(Object obj, Method method, Object[] args, Callable origina return locator.toString(); } - if (Object.class.equals(method.getDeclaringClass())) { + if (Object.class == method.getDeclaringClass()) { return original.call(); } @@ -62,6 +73,9 @@ public Object call(Object obj, Method method, Object[] args, Callable origina } WebElement realElement = locator.findElement(); + if ("equals".equals(method.getName()) && args.length == 1) { + return areElementsEqual(realElement, args[0]); + } return getObject(realElement, method, args); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java index 3cf725bd6..9e33276e5 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/ProxyFactory.java @@ -37,9 +37,8 @@ * proxy object here. */ public final class ProxyFactory { - private static final Set NON_PROXYABLE_METHODS = setWith( - setWithout(OBJECT_METHOD_NAMES, "toString"), - "iterator" + private static final Set NON_PROXYABLE_METHODS = setWithout( + OBJECT_METHOD_NAMES, "toString", "equals", "hashCode" ); @SafeVarargs diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index abcd92c80..68e89ddb6 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -24,6 +24,7 @@ import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; @@ -34,16 +35,19 @@ import org.openqa.selenium.support.PageFactory; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static java.time.Duration.ofSeconds; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +@SuppressWarnings({"unused", "MismatchedQueryAndUpdateOfCollection"}) public class AndroidPageObjectTest extends BaseAndroidTest { private boolean populated = false; @@ -149,6 +153,10 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @FindBy(id = "fakeId") private List fakeElements; + @FindBy(className = "android.widget.TextView") + @CacheLookup + private List cachedViews; + @CacheLookup @FindBy(className = "android.widget.TextView") private WebElement cached; @@ -343,8 +351,22 @@ public class AndroidPageObjectTest extends BaseAndroidTest { assertNotEquals(ArrayList.class, fakeElements.getClass()); } - @Test public void checkCached() { + @Test public void checkCachedElements() { assertEquals(((RemoteWebElement) cached).getId(), ((RemoteWebElement) cached).getId()); + assertEquals(cached.hashCode(), cached.hashCode()); + //noinspection SimplifiableAssertion,EqualsWithItself + assertTrue(cached.equals(cached)); + } + + @Test public void checkCachedLists() { + assertEquals(cachedViews.hashCode(), cachedViews.hashCode()); + //noinspection SimplifiableAssertion,EqualsWithItself + assertTrue(cachedViews.equals(cachedViews)); + } + + @Test public void checkListHashing() { + assertFalse(cachedViews.isEmpty()); + assertEquals(cachedViews.size(), new HashSet<>(cachedViews).size()); } @Test @@ -364,6 +386,7 @@ public void checkThatElementSearchingThrowsExpectedExceptionIfChainedLocatorIsIn assertNotEquals(0, androidElementsViewFoundByMixedSearching.size()); } + @Disabled("FIXME") @Test public void checkMixedElementSearching2() { assertNotNull(androidElementViewFoundByMixedSearching2.getAttribute("text")); } From a8737ab7860ffc3ede3c2a73f0fa5cfca9d0c134 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:09:31 +0200 Subject: [PATCH 292/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.10.0 to 5.10.1 (#2069) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.0 to 5.10.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.10.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 603ab21e7..efe9265c2 100644 --- a/build.gradle +++ b/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" - testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.1') { From 9be1936fbd541ee07d793e68f60889fd8a21c334 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 22:26:26 +0200 Subject: [PATCH 293/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2074) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.6.1 to 5.6.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.6.1...webdrivermanager-5.6.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index efe9265c2..e8939419a 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.1') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.2') { exclude group: 'org.seleniumhq.selenium' } testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" From b082b379b6d782197a90710e3b5a95ea8b27f631 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 16 Nov 2023 13:20:12 -0800 Subject: [PATCH 294/501] chore: add toString as AppiumClientConfig (#2076) --- .../java_client/AppiumClientConfig.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java index bb77b4ec9..e6ebfd0bb 100644 --- a/src/main/java/io/appium/java_client/AppiumClientConfig.java +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -205,4 +205,28 @@ public AppiumClientConfig directConnect(boolean directConnect) { public boolean isDirectConnectEnabled() { return directConnect; } + + @Override + public String toString() { + return "AppiumClientConfig{" + + "baseUri=" + + this.baseUri() + + ", connectionTimeout=" + + this.connectionTimeout() + + ", readTimeout=" + + this.readTimeout() + + ", filters=" + + this.filter() + + ", proxy=" + + this.proxy() + + ", credentials=" + + this.credentials() + + ", sslcontext=" + + this.sslContext() + + ", version=" + + this.version() + + ", directConnect=" + + this.directConnect + + '}'; + } } From 2bd448009ef78fc36df7fc45f95e4a2e8cdae024 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 17 Nov 2023 16:02:57 +0100 Subject: [PATCH 295/501] chore: Perform listeners cleanup periodically (#2077) --- .../proxy/ProxyListenersContainer.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java index 8ba4d734b..4d93ebefb 100644 --- a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java +++ b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java @@ -16,21 +16,23 @@ package io.appium.java_client.proxy; -import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; import java.lang.ref.WeakReference; +import java.time.Duration; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.Semaphore; -@NoArgsConstructor(access = AccessLevel.PRIVATE) class ProxyListenersContainer { + private static final Duration LISTENERS_CLEANUP_INTERVAL = Duration.ofMinutes(1); + private static ProxyListenersContainer INSTANCE; public static synchronized ProxyListenersContainer getInstance() { @@ -40,6 +42,21 @@ public static synchronized ProxyListenersContainer getInstance() { return INSTANCE; } + private ProxyListenersContainer() { + var task = new TimerTask() { + @Override + public void run() { + getListeners(null); + } + }; + // Listeners are cleaned up lazily, e.g. every time getListeners API + // is called we also remove garbage-collected items. Although, due to an + // unpredictable nature of the garbage collector and no guarantees about the + // frequency of getListeners API calls we schedule the below loop to be executed every + // minute, and make sure there are no extra references to obsolete listeners + new Timer().scheduleAtFixedRate(task, 0, LISTENERS_CLEANUP_INTERVAL.toMillis()); + } + private final Semaphore listenersGuard = new Semaphore(1); private final List, Collection>> listenerPairs = new LinkedList<>(); @@ -55,7 +72,7 @@ private static class Pair { * Assign listeners for the particular proxied instance. * * @param proxyInstance The proxied instance. - * @param listeners Collection of listeners. + * @param listeners Collection of listeners. * @return The same given instance. */ public T setListeners(T proxyInstance, Collection listeners) { From 18ea9f4337ed330bbba2cbd932b44a16833b31a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:28:03 +0200 Subject: [PATCH 296/501] build(deps): Bump org.owasp.dependencycheck from 8.4.2 to 8.4.3 (#2078) Bumps org.owasp.dependencycheck from 8.4.2 to 8.4.3. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e8939419a..ac6aa6d80 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.4.2' + id 'org.owasp.dependencycheck' version '8.4.3' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 5e2a6efde8995f97a07442751c54a26d6ca09d49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 15:46:21 +0200 Subject: [PATCH 297/501] build(deps): Bump org.owasp.dependencycheck from 8.4.3 to 9.0.1 (#2079) Bumps org.owasp.dependencycheck from 8.4.3 to 9.0.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ac6aa6d80..ccb08f4bc 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '8.4.3' + id 'org.owasp.dependencycheck' version '9.0.1' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 5cd439ae63af9dbadc54e16cece123457bfd5c10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:13:07 +0200 Subject: [PATCH 298/501] build(deps): Bump actions/setup-java from 3 to 4 (#2081) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 282526a5f..c293b7b40 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -50,7 +50,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.java }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 71837dd3c..96fcfce38 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,7 +8,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'zulu' From fa56ff7941b71f6556043a3709d2aa5ebb191adb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:24:11 +0200 Subject: [PATCH 299/501] build(deps): Bump org.owasp.dependencycheck from 9.0.1 to 9.0.2 (#2080) Bumps org.owasp.dependencycheck from 9.0.1 to 9.0.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ccb08f4bc..280c67fab 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.1' + id 'org.owasp.dependencycheck' version '9.0.2' id 'com.github.johnrengelman.shadow' version '8.1.1' } From b2ee385dd1f151c76ea15ecdf5eeea167e7fde18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:40:36 +0200 Subject: [PATCH 300/501] build(deps): Bump org.owasp.dependencycheck from 9.0.2 to 9.0.4 (#2082) Bumps org.owasp.dependencycheck from 9.0.2 to 9.0.4. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 280c67fab..c13ac9254 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.2' + id 'org.owasp.dependencycheck' version '9.0.4' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 1d22f0c59d2dd70189cf8075914494c4f3b382fe Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 14 Dec 2023 08:05:50 +0200 Subject: [PATCH 301/501] fix: Use JDK 11 to build Jitpack snapshots (#2083) --- jitpack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jitpack.yml b/jitpack.yml index 8e5135fbb..e5b145a9d 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,4 @@ jdk: - - openjdk8 + - openjdk11 install: - ./gradlew clean build publishToMavenLocal -PsigningDisabled=true From 4ab6b5397cc52bc5f078791a91fc0972b3309efa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 14:58:41 +0200 Subject: [PATCH 302/501] build(deps): Bump org.owasp.dependencycheck from 9.0.4 to 9.0.6 (#2084) Bumps org.owasp.dependencycheck from 9.0.4 to 9.0.6. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c13ac9254..69120dcbf 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.4' + id 'org.owasp.dependencycheck' version '9.0.6' id 'com.github.johnrengelman.shadow' version '8.1.1' } From f8080a2205029591da3fa4d6779a11d56146c308 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:37:25 +0200 Subject: [PATCH 303/501] build(deps): Bump org.owasp.dependencycheck from 9.0.6 to 9.0.7 (#2087) Bumps org.owasp.dependencycheck from 9.0.6 to 9.0.7. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 69120dcbf..9ad264d04 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.6' + id 'org.owasp.dependencycheck' version '9.0.7' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 2a39582d6f1a27859de785c9ef68c27b3212333b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 15:49:02 +0300 Subject: [PATCH 304/501] build(deps): Bump slf4jVersion from 2.0.9 to 2.0.10 (#2091) Bumps `slf4jVersion` from 2.0.9 to 2.0.10. Updates `org.slf4j:slf4j-api` from 2.0.9 to 2.0.10 Updates `org.slf4j:slf4j-simple` from 2.0.9 to 2.0.10 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9ad264d04..f37e5d5ea 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.9' + slf4jVersion = '2.0.10' } dependencies { From f2537947db3bc4e21499f14b8ed95ffcc6b54136 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 15:49:29 +0300 Subject: [PATCH 305/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2092) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.6.2 to 5.6.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.6.2...webdrivermanager-5.6.3) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f37e5d5ea..43c00e5ed 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.2') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.3') { exclude group: 'org.seleniumhq.selenium' } testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" From 3ab5bf92f028432b0daecec5492b2db1238057c4 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sun, 7 Jan 2024 23:21:12 +0300 Subject: [PATCH 306/501] chore: Add non-W3C endpoints removed from Selenium client (#2093) --- .../io/appium/java_client/MobileCommand.java | 18 ++++++++++++++++++ .../remote/SupportsContextSwitching.java | 8 ++++---- .../java_client/remote/SupportsRotation.java | 10 +++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index ee08c289a..15704ec40 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -178,6 +178,15 @@ public class MobileCommand { protected static final String GET_ALLSESSION; protected static final String EXECUTE_GOOGLE_CDP_COMMAND; + public static final String GET_SCREEN_ORIENTATION = "getScreenOrientation"; + public static final String SET_SCREEN_ORIENTATION = "setScreenOrientation"; + public static final String GET_SCREEN_ROTATION = "getScreenRotation"; + public static final String SET_SCREEN_ROTATION = "setScreenRotation"; + + public static final String GET_CONTEXT_HANDLES = "getContextHandles"; + public static final String GET_CURRENT_CONTEXT_HANDLE = "getCurrentContextHandle"; + public static final String SWITCH_TO_CONTEXT = "switchToContext"; + public static final Map commandRepository; static { @@ -347,6 +356,15 @@ public class MobileCommand { commandRepository.put(EXECUTE_DRIVER_SCRIPT, postC("/session/:sessionId/appium/execute_driver")); commandRepository.put(GET_ALLSESSION, getC("/sessions")); commandRepository.put(EXECUTE_GOOGLE_CDP_COMMAND, postC("/session/:sessionId/goog/cdp/execute")); + + commandRepository.put(GET_SCREEN_ORIENTATION, getC("/session/:sessionId/orientation")); + commandRepository.put(SET_SCREEN_ORIENTATION, postC("/session/:sessionId/orientation")); + commandRepository.put(GET_SCREEN_ROTATION, getC("/session/:sessionId/rotation")); + commandRepository.put(SET_SCREEN_ROTATION, postC("/session/:sessionId/rotation")); + + commandRepository.put(GET_CONTEXT_HANDLES, getC("/session/:sessionId/contexts")); + commandRepository.put(GET_CURRENT_CONTEXT_HANDLE, getC("/session/:sessionId/context")); + commandRepository.put(SWITCH_TO_CONTEXT, postC("/session/:sessionId/context")); } /** diff --git a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java index b5c7e4b3b..b126e4fa1 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java +++ b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java @@ -17,11 +17,11 @@ package io.appium.java_client.remote; import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.MobileCommand; import io.appium.java_client.NoSuchContextException; import org.openqa.selenium.ContextAware; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; @@ -42,7 +42,7 @@ public interface SupportsContextSwitching extends WebDriver, ContextAware, Execu default WebDriver context(String name) { requireNonNull(name, "Must supply a context name"); try { - execute(DriverCommand.SWITCH_TO_CONTEXT, Map.of("name", name)); + execute(MobileCommand.SWITCH_TO_CONTEXT, Map.of("name", name)); return this; } catch (WebDriverException e) { throw new NoSuchContextException(e.getMessage(), e); @@ -55,7 +55,7 @@ default WebDriver context(String name) { * @return List list of context names. */ default Set getContextHandles() { - Response response = execute(DriverCommand.GET_CONTEXT_HANDLES, Map.of()); + Response response = execute(MobileCommand.GET_CONTEXT_HANDLES, Map.of()); Object value = response.getValue(); try { //noinspection unchecked @@ -75,7 +75,7 @@ default Set getContextHandles() { @Nullable default String getContext() { String contextName = - String.valueOf(execute(DriverCommand.GET_CURRENT_CONTEXT_HANDLE).getValue()); + String.valueOf(execute(MobileCommand.GET_CURRENT_CONTEXT_HANDLE).getValue()); return "null".equalsIgnoreCase(contextName) ? null : contextName; } } diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java index 4e8078707..74397a3e0 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsRotation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -17,10 +17,10 @@ package io.appium.java_client.remote; import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.MobileCommand; import org.openqa.selenium.DeviceRotation; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.Response; import java.util.Map; @@ -32,17 +32,17 @@ public interface SupportsRotation extends WebDriver, ExecutesMethod { * @return The rotation value. */ default DeviceRotation rotation() { - Response response = execute(DriverCommand.GET_SCREEN_ROTATION); + Response response = execute(MobileCommand.GET_SCREEN_ROTATION); //noinspection unchecked return new DeviceRotation((Map) response.getValue()); } default void rotate(DeviceRotation rotation) { - execute(DriverCommand.SET_SCREEN_ROTATION, rotation.parameters()); + execute(MobileCommand.SET_SCREEN_ROTATION, rotation.parameters()); } default void rotate(ScreenOrientation orientation) { - execute(DriverCommand.SET_SCREEN_ORIENTATION, + execute(MobileCommand.SET_SCREEN_ORIENTATION, Map.of("orientation", orientation.value().toUpperCase())); } @@ -52,7 +52,7 @@ default void rotate(ScreenOrientation orientation) { * @return The orientation value. */ default ScreenOrientation getOrientation() { - Response response = execute(DriverCommand.GET_SCREEN_ORIENTATION); + Response response = execute(MobileCommand.GET_SCREEN_ORIENTATION); String orientation = String.valueOf(response.getValue()); return ScreenOrientation.valueOf(orientation.toUpperCase()); } From 2ec056e442addb268de668bf63689fbcb0b6f478 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sun, 7 Jan 2024 23:21:39 +0300 Subject: [PATCH 307/501] docs: Add recent versions of Selenium client to compatibility matrix (#2095) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c79742f12..a20f242cd 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ---------------------------|----------------- - `9.0.0` | `4.14.1` + `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` N/A | `4.14.0` `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` From 3c35a42f7fc7d2d4f48072783b6ae86c885f2fa9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 8 Jan 2024 00:07:17 +0300 Subject: [PATCH 308/501] chore: bump Gradle from `8.4` to `8.5` (#2094) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 43c00e5ed..42711ef5d 100644 --- a/build.gradle +++ b/build.gradle @@ -188,7 +188,7 @@ signing { } wrapper { - gradleVersion = '8.4' + gradleVersion = '8.5' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8838ba97b..e6aba2515 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 43bbd488ffafe43eb354a7df1a031b72aeea2043 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:06:49 +0200 Subject: [PATCH 309/501] build(deps): Bump org.owasp.dependencycheck from 9.0.7 to 9.0.8 (#2096) Bumps org.owasp.dependencycheck from 9.0.7 to 9.0.8. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 42711ef5d..9088c3820 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.7' + id 'org.owasp.dependencycheck' version '9.0.8' id 'com.github.johnrengelman.shadow' version '8.1.1' } From c4b4b27f039ee8b521cb35d1e28e0a26671285f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:01:52 +0200 Subject: [PATCH 310/501] build(deps): Bump slf4jVersion from 2.0.10 to 2.0.11 (#2099) Bumps `slf4jVersion` from 2.0.10 to 2.0.11. Updates `org.slf4j:slf4j-api` from 2.0.10 to 2.0.11 Updates `org.slf4j:slf4j-simple` from 2.0.10 to 2.0.11 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9088c3820..54db6c5fb 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.10' + slf4jVersion = '2.0.11' } dependencies { From 6ac3d9b8e64c617181fcf8cf24fced5144de3096 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 15 Jan 2024 21:18:05 +0200 Subject: [PATCH 311/501] chore: Add non-W3C Location-management endpoints deprecated in Selenium client (#2098) --- .../io/appium/java_client/AppiumDriver.java | 1 + .../java/io/appium/java_client/Location.java | 58 +++++++++++++++++ .../io/appium/java_client/MobileCommand.java | 6 ++ .../java_client/android/AndroidDriver.java | 9 +++ .../SupportsExtendedGeolocationCommands.java | 4 +- .../io/appium/java_client/ios/IOSDriver.java | 9 +++ .../java_client/remote/SupportsLocation.java | 65 ++++++++++++++++++- 7 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/main/java/io/appium/java_client/Location.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index f4721dbf5..6d66639c9 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -73,6 +73,7 @@ public class AppiumDriver extends RemoteWebDriver implements // frequently used command parameters @Getter private final URL remoteAddress; + @Deprecated(forRemoval = true) protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; private final Set absentExtensionNames = new HashSet<>(); diff --git a/src/main/java/io/appium/java_client/Location.java b/src/main/java/io/appium/java_client/Location.java new file mode 100644 index 000000000..336c09797 --- /dev/null +++ b/src/main/java/io/appium/java_client/Location.java @@ -0,0 +1,58 @@ +/* + * 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 lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import javax.annotation.Nullable; + +/** + * Represents the physical location. + */ +@Getter +@ToString +@EqualsAndHashCode +public class Location { + private final double latitude; + private final double longitude; + @Nullable private final Double altitude; + + /** + * Create {@link Location} with latitude, longitude and altitude values. + * + * @param latitude latitude value. + * @param longitude longitude value. + * @param altitude altitude value (can be null). + */ + public Location(double latitude, double longitude, @Nullable Double altitude) { + this.latitude = latitude; + this.longitude = longitude; + this.altitude = altitude; + } + + /** + * Create {@link Location} with latitude and longitude values. + * + * @param latitude latitude value. + * @param longitude longitude value. + */ + public Location(double latitude, double longitude) { + this(latitude, longitude, null); + } +} diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 15704ec40..6f7eafb34 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -187,6 +187,9 @@ public class MobileCommand { public static final String GET_CURRENT_CONTEXT_HANDLE = "getCurrentContextHandle"; public static final String SWITCH_TO_CONTEXT = "switchToContext"; + public static final String GET_LOCATION = "getLocation"; + public static final String SET_LOCATION = "setLocation"; + public static final Map commandRepository; static { @@ -365,6 +368,9 @@ public class MobileCommand { commandRepository.put(GET_CONTEXT_HANDLES, getC("/session/:sessionId/contexts")); commandRepository.put(GET_CURRENT_CONTEXT_HANDLE, getC("/session/:sessionId/context")); commandRepository.put(SWITCH_TO_CONTEXT, postC("/session/:sessionId/context")); + + commandRepository.put(GET_LOCATION, getC("/session/:sessionId/location")); + commandRepository.put(SET_LOCATION, postC("/session/:sessionId/location")); } /** 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 584dde1a7..dfd9a879a 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -251,7 +251,16 @@ public AndroidBatteryInfo getBatteryInfo() { return new AndroidBatteryInfo(CommandExecutionHelper.executeScript(this, "mobile: batteryInfo")); } + /** + * Provides the location context. + * + * @return instance of {@link RemoteLocationContext} + * @deprecated This method, {@link org.openqa.selenium.html5.LocationContext} and {@link RemoteLocationContext} + * interface are deprecated, use {@link #getLocation()} and + * {@link #setLocation(io.appium.java_client.Location)} instead. + */ @Override + @Deprecated(forRemoval = true) public RemoteLocationContext getLocationContext() { return locationContext; } diff --git a/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java b/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java index d1ccf8e2c..0472a5bab 100644 --- a/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java +++ b/src/main/java/io/appium/java_client/android/geolocation/SupportsExtendedGeolocationCommands.java @@ -18,7 +18,7 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; -import org.openqa.selenium.remote.DriverCommand; +import io.appium.java_client.MobileCommand; import java.util.Map; @@ -31,7 +31,7 @@ public interface SupportsExtendedGeolocationCommands extends ExecutesMethod { * @param location The location object to set. */ default void setLocation(AndroidGeoLocation location) { - CommandExecutionHelper.execute(this, Map.entry(DriverCommand.SET_LOCATION, + CommandExecutionHelper.execute(this, Map.entry(MobileCommand.SET_LOCATION, Map.of("location", location.build()) )); } 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 995c196a6..6cc48469e 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -279,7 +279,16 @@ class IOSAlert implements Alert { } + /** + * Provides the location context. + * + * @return instance of {@link RemoteLocationContext} + * @deprecated This method, {@link org.openqa.selenium.html5.LocationContext} and {@link RemoteLocationContext} + * interface are deprecated, use {@link #getLocation()} and + * {@link #setLocation(io.appium.java_client.Location)} instead. + */ @Override + @Deprecated(forRemoval = true) public RemoteLocationContext getLocationContext() { return locationContext; } diff --git a/src/main/java/io/appium/java_client/remote/SupportsLocation.java b/src/main/java/io/appium/java_client/remote/SupportsLocation.java index b2211dfda..504f418b6 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsLocation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsLocation.java @@ -16,19 +16,80 @@ package io.appium.java_client.remote; +import com.google.common.collect.ImmutableMap; +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.MobileCommand; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriverException; import org.openqa.selenium.html5.Location; import org.openqa.selenium.html5.LocationContext; import org.openqa.selenium.remote.html5.RemoteLocationContext; -public interface SupportsLocation extends WebDriver, LocationContext { - public RemoteLocationContext getLocationContext(); +import java.util.Map; +import java.util.Optional; +public interface SupportsLocation extends WebDriver, ExecutesMethod, LocationContext { + + /** + * Provides the location context. + * + * @return instance of {@link RemoteLocationContext} + * @deprecated This method, {@link LocationContext} and {@link RemoteLocationContext} interface are deprecated, use + * {@link #getLocation()} and {@link #setLocation(io.appium.java_client.Location)} instead. + */ + @Deprecated(forRemoval = true) + RemoteLocationContext getLocationContext(); + + /** + * Gets the current device's geolocation coordinates. + * + * @return A {@link Location} containing the location information. Returns null if the location is not available + * @deprecated This method and whole {@link LocationContext} interface are deprecated, use {@link #getLocation()} + * instead. + */ + @Deprecated(forRemoval = true) default Location location() { return getLocationContext().location(); } + /** + * Gets the current device's geolocation coordinates. + * + * @return A {@link Location} containing the location information. Throws {@link WebDriverException} if the + * location is not available. + */ + default io.appium.java_client.Location getLocation() { + Map result = CommandExecutionHelper.execute(this, MobileCommand.GET_LOCATION); + return new io.appium.java_client.Location( + result.get("latitude").doubleValue(), + result.get("longitude").doubleValue(), + Optional.ofNullable(result.get("altitude")).map(Number::doubleValue).orElse(null) + ); + } + + /** + * Sets the current device's geolocation coordinates. + * + * @param location A {@link Location} containing the new location information. + * @deprecated This method and whole {@link LocationContext} interface are deprecated, use + * {@link #setLocation(io.appium.java_client.Location)} instead. + */ + @Deprecated(forRemoval = true) default void setLocation(Location location) { getLocationContext().setLocation(location); } + + /** + * Sets the current device's geolocation coordinates. + * + * @param location A {@link Location} containing the new location information. + */ + default void setLocation(io.appium.java_client.Location location) { + ImmutableMap.Builder locationParameters = ImmutableMap.builder(); + locationParameters.put("latitude", location.getLatitude()); + locationParameters.put("longitude", location.getLongitude()); + Optional.ofNullable(location.getAltitude()).ifPresent(altitude -> locationParameters.put("altitude", altitude)); + execute(MobileCommand.SET_LOCATION, Map.of("location", locationParameters)); + } } From a2e839decc61f8378b32892cba9a73239608e35a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 21 Jan 2024 17:40:33 +0100 Subject: [PATCH 312/501] fix: Assign method call listeners directly to the proxy instance (#2102) --- .../proxy/HasMethodCallListeners.java | 35 +++++ .../io/appium/java_client/proxy/Helpers.java | 12 +- .../appium/java_client/proxy/Interceptor.java | 45 +++--- .../java_client/proxy/MethodCallListener.java | 8 +- .../proxy/ProxyListenersContainer.java | 145 ------------------ 5 files changed, 74 insertions(+), 171 deletions(-) create mode 100644 src/main/java/io/appium/java_client/proxy/HasMethodCallListeners.java delete mode 100644 src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java diff --git a/src/main/java/io/appium/java_client/proxy/HasMethodCallListeners.java b/src/main/java/io/appium/java_client/proxy/HasMethodCallListeners.java new file mode 100644 index 000000000..b5807f71b --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/HasMethodCallListeners.java @@ -0,0 +1,35 @@ +/* + * 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.proxy; + +public interface HasMethodCallListeners { + /** + * The setter is dynamically created by ByteBuddy to store + * method call listeners on the instrumented proxy instance. + * + * @param methodCallListeners Array of method call listeners assigned to the proxy instance. + */ + void setMethodCallListeners(MethodCallListener[] methodCallListeners); + + /** + * The getter is dynamically created by ByteBuddy to access + * method call listeners on the instrumented proxy instance. + * + * @return Array of method call listeners assigned the proxy instance. + */ + MethodCallListener[] getMethodCallListeners(); +} diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index 9543073a8..1b0c7a6d4 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -19,7 +19,9 @@ import com.google.common.base.Preconditions; import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.FieldAccessor; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatchers; @@ -118,16 +120,18 @@ public static T createProxy( .subclass(cls) .method(extraMethodMatcher == null ? matcher : matcher.and(extraMethodMatcher)) .intercept(MethodDelegation.to(Interceptor.class)) + // https://github.com/raphw/byte-buddy/blob/2caef35c172897cbdd21d163c55305a64649ce41/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java#L346 + .defineField("methodCallListeners", MethodCallListener[].class, Visibility.PRIVATE) + .implement(HasMethodCallListeners.class).intercept(FieldAccessor.ofBeanProperty()) .make() .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded() .asSubclass(cls); try { - return ProxyListenersContainer.getInstance().setListeners( - cls.cast(proxy.getConstructor(constructorArgTypes).newInstance(constructorArgs)), - listeners - ); + T result = cls.cast(proxy.getConstructor(constructorArgTypes).newInstance(constructorArgs)); + ((HasMethodCallListeners) result).setMethodCallListeners(listeners.toArray(MethodCallListener[]::new)); + return result; } catch (SecurityException | ReflectiveOperationException e) { throw new IllegalStateException(String.format("Unable to create a proxy of %s", cls.getName()), e); } diff --git a/src/main/java/io/appium/java_client/proxy/Interceptor.java b/src/main/java/io/appium/java_client/proxy/Interceptor.java index b8417e14b..f4ece1668 100644 --- a/src/main/java/io/appium/java_client/proxy/Interceptor.java +++ b/src/main/java/io/appium/java_client/proxy/Interceptor.java @@ -25,10 +25,10 @@ import org.slf4j.LoggerFactory; import java.lang.reflect.Method; -import java.util.Collection; -import java.util.UUID; import java.util.concurrent.Callable; +import static io.appium.java_client.proxy.MethodCallListener.UNSET; + public class Interceptor { private static final Logger LOGGER = LoggerFactory.getLogger(Interceptor.class); @@ -37,7 +37,9 @@ private Interceptor() { /** * A magic method used to wrap public method calls in classes - * patched by ByteBuddy and acting as proxies. + * patched by ByteBuddy and acting as proxies. The performance + * of this method is mission-critical as it gets called upon + * every invocation of any method of the proxied class. * * @param self The reference to the original instance. * @param method The reference to the original method. @@ -53,12 +55,12 @@ public static Object intercept( @AllArguments Object[] args, @SuperCall Callable callable ) throws Throwable { - Collection listeners = ProxyListenersContainer.getInstance().getListeners(self); - if (listeners.isEmpty()) { + var listeners = ((HasMethodCallListeners) self).getMethodCallListeners(); + if (listeners == null || listeners.length == 0) { return callable.call(); } - listeners.forEach(listener -> { + for (var listener : listeners) { try { listener.beforeCall(self, method, args); } catch (NotImplementedException e) { @@ -68,32 +70,39 @@ public static Object intercept( self.getClass().getName(), method.getName(), e ); } - }); + } - final UUID noResult = UUID.randomUUID(); - Object result = noResult; - for (MethodCallListener listener : listeners) { + Object result = UNSET; + for (var listener : listeners) { try { result = listener.call(self, method, args, callable); - break; + if (result != UNSET) { + break; + } } catch (NotImplementedException e) { // ignore } catch (Exception e) { try { - return listener.onError(self, method, args, e); + result = listener.onError(self, method, args, e); + if (result != UNSET) { + return result; + } } catch (NotImplementedException ignore) { // ignore } throw e; } } - if (noResult.equals(result)) { + if (UNSET == result) { try { result = callable.call(); } catch (Exception e) { - for (MethodCallListener listener : listeners) { + for (var listener : listeners) { try { - return listener.onError(self, method, args, e); + result = listener.onError(self, method, args, e); + if (result != UNSET) { + return result; + } } catch (NotImplementedException ignore) { // ignore } @@ -102,8 +111,8 @@ public static Object intercept( } } - final Object endResult = result == noResult ? null : result; - listeners.forEach(listener -> { + final Object endResult = result == UNSET ? null : result; + for (var listener : listeners) { try { listener.afterCall(self, method, args, endResult); } catch (NotImplementedException e) { @@ -113,7 +122,7 @@ public static Object intercept( self.getClass().getName(), method.getName(), e ); } - }); + } return endResult; } } diff --git a/src/main/java/io/appium/java_client/proxy/MethodCallListener.java b/src/main/java/io/appium/java_client/proxy/MethodCallListener.java index f0cc1be7a..7dfb5b299 100644 --- a/src/main/java/io/appium/java_client/proxy/MethodCallListener.java +++ b/src/main/java/io/appium/java_client/proxy/MethodCallListener.java @@ -17,9 +17,11 @@ package io.appium.java_client.proxy; import java.lang.reflect.Method; +import java.util.UUID; import java.util.concurrent.Callable; public interface MethodCallListener { + UUID UNSET = UUID.randomUUID(); /** * The callback to be invoked before any public method of the proxy is called. @@ -31,7 +33,6 @@ public interface MethodCallListener { * @param args Array of method arguments */ default void beforeCall(Object obj, Method method, Object[] args) { - throw new NotImplementedException(); } /** @@ -48,7 +49,7 @@ default void beforeCall(Object obj, Method method, Object[] args) { * @return The type of the returned result should be castable to the returned type of the original method. */ default Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { - throw new NotImplementedException(); + return UNSET; } /** @@ -61,7 +62,6 @@ default Object call(Object obj, Method method, Object[] args, Callable origin * @param args Array of method arguments */ default void afterCall(Object obj, Method method, Object[] args, Object result) { - throw new NotImplementedException(); } /** @@ -77,6 +77,6 @@ default void afterCall(Object obj, Method method, Object[] args, Object result) * type of the returned argument could be cast to the returned type of the original method. */ default Object onError(Object obj, Method method, Object[] args, Throwable e) throws Throwable { - throw new NotImplementedException(); + return UNSET; } } diff --git a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java b/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java deleted file mode 100644 index 4d93ebefb..000000000 --- a/src/main/java/io/appium/java_client/proxy/ProxyListenersContainer.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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.proxy; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.lang.ref.WeakReference; -import java.time.Duration; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.Semaphore; - -class ProxyListenersContainer { - private static final Duration LISTENERS_CLEANUP_INTERVAL = Duration.ofMinutes(1); - - private static ProxyListenersContainer INSTANCE; - - public static synchronized ProxyListenersContainer getInstance() { - if (INSTANCE == null) { - INSTANCE = new ProxyListenersContainer(); - } - return INSTANCE; - } - - private ProxyListenersContainer() { - var task = new TimerTask() { - @Override - public void run() { - getListeners(null); - } - }; - // Listeners are cleaned up lazily, e.g. every time getListeners API - // is called we also remove garbage-collected items. Although, due to an - // unpredictable nature of the garbage collector and no guarantees about the - // frequency of getListeners API calls we schedule the below loop to be executed every - // minute, and make sure there are no extra references to obsolete listeners - new Timer().scheduleAtFixedRate(task, 0, LISTENERS_CLEANUP_INTERVAL.toMillis()); - } - - private final Semaphore listenersGuard = new Semaphore(1); - private final List, Collection>> listenerPairs = new LinkedList<>(); - - @Getter - @AllArgsConstructor - private static class Pair { - private final K key; - @Setter - private V value; - } - - /** - * Assign listeners for the particular proxied instance. - * - * @param proxyInstance The proxied instance. - * @param listeners Collection of listeners. - * @return The same given instance. - */ - public T setListeners(T proxyInstance, Collection listeners) { - try { - listenersGuard.acquire(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - try { - int i = 0; - boolean wasInstancePresent = false; - while (i < listenerPairs.size()) { - var pair = listenerPairs.get(i); - Object key = pair.getKey().get(); - if (key == null) { - // The instance has been garbage-collected - listenerPairs.remove(i); - continue; - } - - if (key == proxyInstance) { - pair.setValue(List.copyOf(listeners)); - wasInstancePresent = true; - } - i++; - } - if (!wasInstancePresent) { - listenerPairs.add(new Pair<>(new WeakReference<>(proxyInstance), List.copyOf(listeners))); - } - } finally { - listenersGuard.release(); - } - return proxyInstance; - } - - /** - * Fetches listeners for the particular proxied instance. - * - * @param proxyInstance The proxied instance. - */ - public Collection getListeners(Object proxyInstance) { - try { - listenersGuard.acquire(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - try { - int i = 0; - Collection result = Collections.emptyList(); - while (i < listenerPairs.size()) { - var pair = listenerPairs.get(i); - Object key = pair.getKey().get(); - if (key == null) { - // The instance has been garbage-collected - listenerPairs.remove(i); - continue; - } - - if (key == proxyInstance) { - result = pair.getValue(); - } - i++; - } - return result; - } finally { - listenersGuard.release(); - } - } - -} From c83013f340e06500e3bb5bcc9fd8d4b5ca2ee969 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:22:09 +0200 Subject: [PATCH 313/501] build(deps): Bump org.owasp.dependencycheck from 9.0.8 to 9.0.9 (#2103) Bumps org.owasp.dependencycheck from 9.0.8 to 9.0.9. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 54db6c5fb..3596d3e28 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.8' + id 'org.owasp.dependencycheck' version '9.0.9' id 'com.github.johnrengelman.shadow' version '8.1.1' } From a0b0f61db5cc5c9c91b0914dc53510538e318124 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 26 Jan 2024 16:04:54 +0100 Subject: [PATCH 314/501] docs: Describe the release procedure (#2104) * docs: Describe the release procedure * Add note about gradle * Address comments --- docs/release.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/release.md diff --git a/docs/release.md b/docs/release.md new file mode 100644 index 000000000..ec4927a75 --- /dev/null +++ b/docs/release.md @@ -0,0 +1,25 @@ +# Appium Java Client Release Procedure + +This document describes the process of releasing this client to the Maven repository. +Its target auditory is project maintainers. + +## Release Steps + +1. Update the [Changelog](../CHANGELOG.md) for the given version based on previous commits. +1. Bump the `appiumClient.version` number in [gradle.properties](../gradle.properties). +1. Create a pull request to approve the changelog and version bump. +1. Merge the pull request after it is approved. +1. Create and push a new repository tag. The tag name should look like + `v..`. +1. Open [Sonatype](https://oss.sonatype.org/#welcome) in your browser. +1. Login to Nexus using 1Password credentials. Ask Appium maintainers + if you need access to the team's 1Password vault. +1. Navigate to `Staging Repositories`. +1. Select the corresponding release and click `Close`. +1. Wait until checks are completed. +1. Click `Release`. +1. After the new release is published, it becomes available in + [Maven Central](https://repo1.maven.org/maven2/io/appium/java-client/) + within 30 minutes. Once artifacts are in Maven Central, it normally + takes 1-2 hours before they appear in + [search results](https://central.sonatype.com/artifact/io.appium/java-client). From 38c96a271a2b509d15b959a2215d7f4a0c5d472a Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 26 Jan 2024 21:49:19 +0200 Subject: [PATCH 315/501] release: v9.1.0 and update release notes (#2106) --- CHANGELOG.md | 23 +++++++++++++++++++++++ gradle.properties | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a16add346..9b3f9b0d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.1.0_ +- **[ENHANCEMENTS]** + - Introduce better constructor argument validation for the `AppiumFieldDecorator` class. [#2070](https://github.com/appium/java-client/pull/2070) + - Add `toString` to `AppiumClientConfig`. [#2076](https://github.com/appium/java-client/pull/2076) + - Perform listeners cleanup periodically. [#2077](https://github.com/appium/java-client/pull/2077) + - Add non-W3C context, orientation and rotation management endpoints removed from Selenium client. [#2093](https://github.com/appium/java-client/pull/2093) + - Add non-W3C Location-management endpoints deprecated in Selenium client. [#2098](https://github.com/appium/java-client/pull/2098) +- **[BUG FIX]** + - Properly unwrap driver instance if the `ContextAware` object is deeply nested. [#2052](https://github.com/appium/java-client/pull/2052) + - Update hashing and iteration logic of page object items. [#2067](https://github.com/appium/java-client/pull/2067) + - Assign method call listeners directly to the proxy instance. [#2102](https://github.com/appium/java-client/pull/2102) + - Use JDK 11 to build Jitpack snapshots. [#2083](https://github.com/appium/java-client/pull/2083) +- **[DEPRECATION]** + - Deprecate custom functional interfaces. [#2055](https://github.com/appium/java-client/pull/2055) +- **[REFACTOR]** + - Use Java 9+ APIs instead of outdated/3rd-party APIs. [#2048](https://github.com/appium/java-client/pull/2048) + - Migrate to new Selenium API for process management. [#2054](https://github.com/appium/java-client/pull/2054) +- **[DEPENDENCY CHANGE]** + - Bump minimum supported Selenium version from `4.14.1` to `4.17.0`. + - Bump SLF4J from `2.0.9` to `2.0.11`. [#2091](https://github.com/appium/java-client/pull/2091), [#2099](https://github.com/appium/java-client/pull/2099) +- **[DOCUMENTATION]** + - Describe the release procedure. [#2104](https://github.com/appium/java-client/pull/2104) + _9.0.0_ - **[DOCUMENTATION]** - Add 8 to 9 migration guide. [#2039](https://github.com/appium/java-client/pull/2039) diff --git a/gradle.properties b/gradle.properties index 6e923bc15..16c8cc317 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.14.1 +selenium.version=4.17.0 # Please increment the value in a release -appiumClient.version=9.0.0 +appiumClient.version=9.1.0 From d90df884ecc1802dadd3a2b3cebb81cc0d8397b2 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 27 Jan 2024 14:40:04 +0100 Subject: [PATCH 316/501] docs: Update release steps (#2107) --- docs/release.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/release.md b/docs/release.md index ec4927a75..f2a6c1ae6 100644 --- a/docs/release.md +++ b/docs/release.md @@ -10,12 +10,16 @@ Its target auditory is project maintainers. 1. Create a pull request to approve the changelog and version bump. 1. Merge the pull request after it is approved. 1. Create and push a new repository tag. The tag name should look like - `v..`. + `v..`. +1. Create a new [Release](https://github.com/appium/java-client/releases/new) in GitHub. + Paste the above changelist into the release notes. Make sure the name of the new release + matches to the name of the above tag. 1. Open [Sonatype](https://oss.sonatype.org/#welcome) in your browser. 1. Login to Nexus using 1Password credentials. Ask Appium maintainers - if you need access to the team's 1Password vault. + if you need access to the team's 1Password vault. 1. Navigate to `Staging Repositories`. -1. Select the corresponding release and click `Close`. +1. Select the corresponding release and click `Close`. Note that it may take + some minutes until Sonatype picks up the GitHub release. 1. Wait until checks are completed. 1. Click `Release`. 1. After the new release is published, it becomes available in From 4623e1138ca19c388ac2f636a30a4320c00b7fb5 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 30 Jan 2024 14:09:13 +0200 Subject: [PATCH 317/501] fix: Set correct geolocation coordinates of the current device (#2109) --- .../java/io/appium/java_client/remote/SupportsLocation.java | 2 +- .../java/io/appium/java_client/android/AndroidDriverTest.java | 4 ++-- src/test/java/io/appium/java_client/ios/IOSDriverTest.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/SupportsLocation.java b/src/main/java/io/appium/java_client/remote/SupportsLocation.java index 504f418b6..45d81f36c 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsLocation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsLocation.java @@ -90,6 +90,6 @@ default void setLocation(io.appium.java_client.Location location) { locationParameters.put("latitude", location.getLatitude()); locationParameters.put("longitude", location.getLongitude()); Optional.ofNullable(location.getAltitude()).ifPresent(altitude -> locationParameters.put("altitude", altitude)); - execute(MobileCommand.SET_LOCATION, Map.of("location", locationParameters)); + execute(MobileCommand.SET_LOCATION, Map.of("location", locationParameters.build())); } } diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java index e1ff99d2e..76753d75d 100644 --- a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidDriverTest.java @@ -16,12 +16,12 @@ package io.appium.java_client.android; +import io.appium.java_client.Location; import io.appium.java_client.appmanagement.ApplicationState; import org.apache.commons.io.FileUtils; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.openqa.selenium.ScreenOrientation; -import org.openqa.selenium.html5.Location; import java.io.File; import java.time.Duration; @@ -192,7 +192,7 @@ public void toggleLocationServicesTest() { @Test public void geolocationTest() { - Location location = new Location(45, 45, 100); + Location location = new Location(45, 45, 100.0); driver.setLocation(location); } diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java index b5d718eb8..438178e36 100644 --- a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/test/java/io/appium/java_client/ios/IOSDriverTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.ios; +import io.appium.java_client.Location; import io.appium.java_client.appmanagement.ApplicationState; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -23,7 +24,6 @@ import org.openqa.selenium.By; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebElement; -import org.openqa.selenium.html5.Location; import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.http.HttpMethod; @@ -88,7 +88,7 @@ public void getDeviceTimeTest() { @Disabled @Test public void geolocationTest() { - Location location = new Location(45, 45, 100); + Location location = new Location(45, 45, 100.0); try { driver.setLocation(location); } catch (Exception e) { From 38636226d1a07e2ee849cfa4e8f0625152085f72 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 2 Feb 2024 14:25:51 +0200 Subject: [PATCH 318/501] docs: add Appium Java client `9.1.0` to Compatibility Matrix (#2110) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a20f242cd..08bf82124 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ---------------------------|----------------- + `9.1.0` | `4.17.0` `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` N/A | `4.14.0` `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` From 3f211fa095a30883193f40afefefc4243b830bce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:37:14 +0200 Subject: [PATCH 319/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.10.1 to 5.10.2 (#2113) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.1 to 5.10.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.1...r5.10.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3596d3e28..487e02e64 100644 --- a/build.gradle +++ b/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" - testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.3') { From 2e6a74b4fb0dd6ff6f6feb0608491e517b803243 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:37:34 +0200 Subject: [PATCH 320/501] build(deps): Bump gradle/wrapper-validation-action from 1 to 2 (#2114) Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 1 to 2. - [Release notes](https://github.com/gradle/wrapper-validation-action/releases) - [Commits](https://github.com/gradle/wrapper-validation-action/compare/v1...v2) --- updated-dependencies: - dependency-name: gradle/wrapper-validation-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index f6851f4b1..531000b79 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -24,4 +24,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v1 + - uses: gradle/wrapper-validation-action@v2 From b7ec2f3fe25e2db964455d8296cd1bbcfc948b39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:57:28 +0300 Subject: [PATCH 321/501] build(deps): Bump slf4jVersion from 2.0.11 to 2.0.12 (#2115) Bumps `slf4jVersion` from 2.0.11 to 2.0.12. Updates `org.slf4j:slf4j-api` from 2.0.11 to 2.0.12 Updates `org.slf4j:slf4j-simple` from 2.0.11 to 2.0.12 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 487e02e64..ae9e02882 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.11' + slf4jVersion = '2.0.12' } dependencies { From 36752de5736da21a896631ca5a7f0724be0983c4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 16 Feb 2024 16:52:13 +0100 Subject: [PATCH 322/501] test: Remove obsolete tests (#2120) --- .../appium/java_client/ios/IOSTouchTest.java | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 src/test/java/io/appium/java_client/ios/IOSTouchTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java b/src/test/java/io/appium/java_client/ios/IOSTouchTest.java deleted file mode 100644 index 38e66359f..000000000 --- a/src/test/java/io/appium/java_client/ios/IOSTouchTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package io.appium.java_client.ios; - -import io.appium.java_client.AppiumBy; -import io.appium.java_client.MultiTouchAction; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.WebDriverWait; - -import java.time.Duration; - -import static io.appium.java_client.ios.touch.IOSPressOptions.iosPressOptions; -import static io.appium.java_client.touch.TapOptions.tapOptions; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static java.time.Duration.ofMillis; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.openqa.selenium.support.ui.ExpectedConditions.alertIsPresent; - -@TestMethodOrder(MethodOrderer.MethodName.class) -public class IOSTouchTest extends AppIOSTest { - - @Test - public void tapTest() { - WebElement intA = driver.findElement(By.id("IntegerA")); - WebElement intB = driver.findElement(By.id("IntegerB")); - intA.clear(); - intB.clear(); - intA.sendKeys("2"); - intB.sendKeys("4"); - - WebElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); - new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))).perform(); - assertEquals(driver.findElement(By.xpath("//*[@name = \"Answer\"]")).getText(), "6"); - } - - @Test - public void touchWithPressureTest() { - WebElement intA = driver.findElement(By.id("IntegerA")); - WebElement intB = driver.findElement(By.id("IntegerB")); - intA.clear(); - intB.clear(); - intA.sendKeys("2"); - intB.sendKeys("4"); - - WebElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); - new IOSTouchAction(driver) - .press(iosPressOptions() - .withElement(element(e)) - .withPressure(1)) - .waitAction(waitOptions(ofMillis(100))) - .release() - .perform(); - assertEquals(driver.findElement(By.xpath("//*[@name = \"Answer\"]")).getText(), "6"); - } - - @Test public void multiTouchTest() { - WebElement e = driver.findElement(AppiumBy.accessibilityId("ComputeSumButton")); - WebElement e2 = driver.findElement(AppiumBy.accessibilityId("show alert")); - - IOSTouchAction tap1 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e))); - IOSTouchAction tap2 = new IOSTouchAction(driver).tap(tapOptions().withElement(element(e2))); - - new MultiTouchAction(driver).add(tap1).add(tap2).perform(); - - WebDriverWait waiting = new WebDriverWait(driver, Duration.ofSeconds(10)); - assertNotNull(waiting.until(alertIsPresent())); - driver.switchTo().alert().accept(); - } - - @Test public void doubleTapTest() { - WebElement firstField = driver.findElement(By.id("IntegerA")); - firstField.sendKeys("2"); - - IOSTouchAction iosTouchAction = new IOSTouchAction(driver); - iosTouchAction.doubleTap(element(firstField)); - WebElement editingMenu = driver.findElement(AppiumBy.className("XCUIElementTypeTextField")); - assertNotNull(editingMenu); - } -} From 63bcbf5d6bd823aeef81f47e4ac302bf37b212ca Mon Sep 17 00:00:00 2001 From: AlessandroMiccoli <57630383+AlessandroMiccoli@users.noreply.github.com> Date: Mon, 19 Feb 2024 11:53:56 +0000 Subject: [PATCH 323/501] feat: add pollDelay mechanism into AppiumFluentWait (#2116) --- .../appium/java_client/AppiumFluentWait.java | 90 ++++++++++++++----- 1 file changed, 67 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumFluentWait.java b/src/main/java/io/appium/java_client/AppiumFluentWait.java index 9061600a0..6361a5652 100644 --- a/src/main/java/io/appium/java_client/AppiumFluentWait.java +++ b/src/main/java/io/appium/java_client/AppiumFluentWait.java @@ -29,12 +29,16 @@ import java.time.Duration; import java.time.Instant; import java.util.List; +import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; public class AppiumFluentWait extends FluentWait { private Function pollingStrategy = null; + private static final Duration DEFAULT_POLL_DELAY_DURATION = Duration.ZERO; + private Duration pollDelay = DEFAULT_POLL_DELAY_DURATION; + public static class IterationInfo { /** * The current iteration number. @@ -98,6 +102,18 @@ public AppiumFluentWait(T input, Clock clock, Sleeper sleeper) { super(input, clock, sleeper); } + /** + * Sets how long to wait before starting to evaluate condition to be true. + * The default pollDelay is {@link #DEFAULT_POLL_DELAY_DURATION}. + * + * @param pollDelay The pollDelay duration. + * @return A self reference. + */ + public AppiumFluentWait withPollDelay(Duration pollDelay) { + this.pollDelay = pollDelay; + return this; + } + private B getPrivateFieldValue(String fieldName, Class fieldType) { return ReflectionHelpers.getPrivateFieldValue(FluentWait.class, this, fieldName, fieldType); } @@ -200,10 +216,19 @@ public AppiumFluentWait withPollingStrategy(Function */ @Override public V until(Function isTrue) { - final Instant start = getClock().instant(); - final Instant end = getClock().instant().plus(getTimeout()); - long iterationNumber = 1; + final var start = getClock().instant(); + // Adding pollDelay to end instant will allow to verify the condition for the expected timeout duration. + final var end = start.plus(getTimeout()).plus(pollDelay); + + return performIteration(isTrue, start, end); + } + + private V performIteration(Function isTrue, Instant start, Instant end) { + var iterationNumber = 1; Throwable lastException; + + sleepInterruptibly(pollDelay); + while (true) { try { V value = isTrue.apply(getInput()); @@ -222,32 +247,51 @@ public V until(Function isTrue) { // Check the timeout after evaluating the function to ensure conditions // with a zero timeout can succeed. if (end.isBefore(getClock().instant())) { - String message = getMessageSupplier() != null ? getMessageSupplier().get() : null; - - String timeoutMessage = String.format( - "Expected condition failed: %s (tried for %d second(s) with %s interval)", - message == null ? "waiting for " + isTrue : message, - getTimeout().getSeconds(), getInterval()); - throw timeoutException(timeoutMessage, lastException); + handleTimeoutException(lastException, isTrue); } - try { - Duration interval = getInterval(); - if (pollingStrategy != null) { - final IterationInfo info = new IterationInfo(iterationNumber, - Duration.between(start, getClock().instant()), getTimeout(), - interval); - interval = pollingStrategy.apply(info); - } - getSleeper().sleep(interval); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new WebDriverException(e); - } + var interval = getIntervalWithPollingStrategy(start, iterationNumber); + sleepInterruptibly(interval); + ++iterationNumber; } } + private void handleTimeoutException(Throwable lastException, Function isTrue) { + var message = Optional.ofNullable(getMessageSupplier()) + .map(Supplier::get) + .orElseGet(() -> "waiting for " + isTrue); + + var timeoutMessage = String.format( + "Expected condition failed: %s (tried for %s ms with an interval of %s ms)", + message, + getTimeout().toMillis(), + getInterval().toMillis() + ); + + throw timeoutException(timeoutMessage, lastException); + } + + private Duration getIntervalWithPollingStrategy(Instant start, long iterationNumber) { + var interval = getInterval(); + return Optional.ofNullable(pollingStrategy) + .map(strategy -> strategy.apply(new IterationInfo( + iterationNumber, + Duration.between(start, getClock().instant()), getTimeout(), interval))) + .orElse(interval); + } + + private void sleepInterruptibly(Duration duration) { + try { + if (!duration.isZero() && !duration.isNegative()) { + getSleeper().sleep(duration); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new WebDriverException(e); + } + } + protected Throwable propagateIfNotIgnored(Throwable e) { for (Class ignoredException : getIgnoredExceptions()) { if (ignoredException.isInstance(e)) { From 6075c9d6d5757708e9f09af53c98b738ba08dd28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:50:42 +0200 Subject: [PATCH 324/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2125) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.6.3 to 5.7.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.6.3...webdrivermanager-5.7.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ae9e02882..0eb9997c9 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.6.3') { + testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.7.0') { exclude group: 'org.seleniumhq.selenium' } testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" From 7ba6ef91c3769f212a229dc8d43af3725db4a4a6 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 4 Mar 2024 15:46:59 +0100 Subject: [PATCH 325/501] fix: Always release annotated element reference from the builder instance (#2128) --- .../AppiumElementLocatorFactory.java | 21 ++++++++++++------- .../pagefactory/WidgetByBuilder.java | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java index 787e34e9e..77b3120fc 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -19,7 +19,6 @@ import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder; import io.appium.java_client.pagefactory.locator.CacheableElementLocatorFactory; import io.appium.java_client.pagefactory.locator.CacheableLocator; -import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; import javax.annotation.Nullable; @@ -90,12 +89,18 @@ public CacheableLocator createLocator(AnnotatedElement annotatedElement) { customDuration = duration; } builder.setAnnotated(annotatedElement); - By byResult = builder.buildBy(); - return ofNullable(byResult) - .map(by -> searchContextReference != null - ? new AppiumElementLocator(searchContextReference, by, builder.isLookupCached(), customDuration) - : new AppiumElementLocator(searchContext, by, builder.isLookupCached(), customDuration) - ) - .orElse(null); + try { + return ofNullable(builder.buildBy()) + .map(by -> { + var isLookupCached = builder.isLookupCached(); + return searchContextReference != null + ? new AppiumElementLocator(searchContextReference, by, isLookupCached, customDuration) + : new AppiumElementLocator(searchContext, by, isLookupCached, customDuration); + }) + .orElse(null); + } finally { + // unleak element reference after the locator is built + builder.setAnnotated(null); + } } } diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java index 905844e4a..b87996357 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetByBuilder.java @@ -51,7 +51,7 @@ private static Class getClassFromAListField(Field field) { @SuppressWarnings("unchecked") private By getByFromDeclaredClass(WhatIsNeeded whatIsNeeded) { AnnotatedElement annotatedElement = annotatedElementContainer.getAnnotated(); - Field field = Field.class.cast(annotatedElement); + Field field = (Field) annotatedElement; Class declaredClass; By result = null; From 6144fb2cae2948c2abe9d792375baa4136c8e941 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 4 Mar 2024 15:47:14 +0100 Subject: [PATCH 326/501] fix: Cache dynamic proxy classes created by ByteBuddy (#2129) --- .../io/appium/java_client/proxy/Helpers.java | 66 ++++++++++++------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index 1b0c7a6d4..af724ae43 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -17,6 +17,7 @@ package io.appium.java_client.proxy; import com.google.common.base.Preconditions; +import lombok.Value; import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.modifier.Visibility; @@ -31,6 +32,8 @@ import java.util.Collection; import java.util.Collections; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -42,6 +45,13 @@ public class Helpers { .map(Method::getName) .collect(Collectors.toSet()); + // Each proxy class created by ByteBuddy gets automatically cached by the + // given class loader. It is important to have this cache here in order to improve + // the performance and to avoid extensive memory usage for our case, where + // the amount of instrumented proxy classes we create is low in comparison to the amount + // of proxy instances. + private static final ConcurrentMap> CACHED_PROXY_CLASSES = new ConcurrentHashMap<>(); + private Helpers() { } @@ -104,32 +114,35 @@ public static T createProxy( Collection listeners, @Nullable ElementMatcher extraMethodMatcher ) { - Preconditions.checkArgument(constructorArgs.length == constructorArgTypes.length, - String.format( - "Constructor arguments array length %d must be equal to the types array length %d", - constructorArgs.length, constructorArgTypes.length - ) - ); - Preconditions.checkArgument(!listeners.isEmpty(), "The collection of listeners must not be empty"); - requireNonNull(cls, "Class must not be null"); - Preconditions.checkArgument(!cls.isInterface(), "Class must not be an interface"); + var signature = ProxyClassSignature.of(cls, constructorArgTypes, extraMethodMatcher); + var proxyClass = CACHED_PROXY_CLASSES.computeIfAbsent(signature, k -> { + Preconditions.checkArgument(constructorArgs.length == constructorArgTypes.length, + String.format( + "Constructor arguments array length %d must be equal to the types array length %d", + constructorArgs.length, constructorArgTypes.length + ) + ); + Preconditions.checkArgument(!listeners.isEmpty(), "The collection of listeners must not be empty"); + requireNonNull(cls, "Class must not be null"); + Preconditions.checkArgument(!cls.isInterface(), "Class must not be an interface"); - ElementMatcher.Junction matcher = ElementMatchers.isPublic(); - //noinspection resource - Class proxy = new ByteBuddy() - .subclass(cls) - .method(extraMethodMatcher == null ? matcher : matcher.and(extraMethodMatcher)) - .intercept(MethodDelegation.to(Interceptor.class)) - // https://github.com/raphw/byte-buddy/blob/2caef35c172897cbdd21d163c55305a64649ce41/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java#L346 - .defineField("methodCallListeners", MethodCallListener[].class, Visibility.PRIVATE) - .implement(HasMethodCallListeners.class).intercept(FieldAccessor.ofBeanProperty()) - .make() - .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER) - .getLoaded() - .asSubclass(cls); + ElementMatcher.Junction matcher = ElementMatchers.isPublic(); + //noinspection resource + return new ByteBuddy() + .subclass(cls) + .method(extraMethodMatcher == null ? matcher : matcher.and(extraMethodMatcher)) + .intercept(MethodDelegation.to(Interceptor.class)) + // https://github.com/raphw/byte-buddy/blob/2caef35c172897cbdd21d163c55305a64649ce41/byte-buddy-dep/src/test/java/net/bytebuddy/ByteBuddyTutorialExamplesTest.java#L346 + .defineField("methodCallListeners", MethodCallListener[].class, Visibility.PRIVATE) + .implement(HasMethodCallListeners.class).intercept(FieldAccessor.ofBeanProperty()) + .make() + .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER) + .getLoaded() + .asSubclass(cls); + }); try { - T result = cls.cast(proxy.getConstructor(constructorArgTypes).newInstance(constructorArgs)); + T result = cls.cast(proxyClass.getConstructor(constructorArgTypes).newInstance(constructorArgs)); ((HasMethodCallListeners) result).setMethodCallListeners(listeners.toArray(MethodCallListener[]::new)); return result; } catch (SecurityException | ReflectiveOperationException e) { @@ -201,4 +214,11 @@ public static T createProxy( ) { return createProxy(cls, constructorArgs, constructorArgTypes, Collections.singletonList(listener)); } + + @Value(staticConstructor = "of") + private static class ProxyClassSignature { + Class cls; + Class[] constructorArgTypes; + ElementMatcher extraMethodMatcher; + } } From 41769295f6af68da7721be8cfd3a59ee01fd01d4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 10 Mar 2024 13:52:37 +0100 Subject: [PATCH 327/501] chore: Make server startup error messages more useful (#2130) --- .../local/AppiumDriverLocalService.java | 117 ++++++++----- .../AppiumServerAvailabilityChecker.java | 158 ++++++++++++++++++ ...rverHasNotBeenStartedLocallyException.java | 14 +- 3 files changed, 241 insertions(+), 48 deletions(-) create mode 100644 src/main/java/io/appium/java_client/service/local/AppiumServerAvailabilityChecker.java diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 45f611eab..666f2ba06 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -17,8 +17,8 @@ package io.appium.java_client.service.local; import com.google.common.annotations.VisibleForTesting; +import lombok.Getter; import lombok.SneakyThrows; -import org.openqa.selenium.net.UrlChecker; import org.openqa.selenium.os.ExternalProcess; import org.openqa.selenium.remote.service.DriverService; import org.slf4j.Logger; @@ -30,14 +30,12 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; -import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -67,7 +65,9 @@ public final class AppiumDriverLocalService extends DriverService { private final Duration startupTimeout; private final ReentrantLock lock = new ReentrantLock(true); //uses "fair" thread ordering policy private final ListOutputStream stream = new ListOutputStream().add(System.out); + private final AppiumServerAvailabilityChecker availabilityChecker = new AppiumServerAvailabilityChecker(); private final URL url; + @Getter private String basePath; private ExternalProcess process = null; @@ -97,10 +97,6 @@ public AppiumDriverLocalService withBasePath(String basePath) { return this; } - public String getBasePath() { - return this.basePath; - } - @SneakyThrows private static URL addSuffix(URL url, String suffix) { return url.toURI().resolve("." + (suffix.startsWith("/") ? suffix : "/" + suffix)).toURL(); @@ -131,36 +127,40 @@ public boolean isRunning() { } try { - ping(IS_RUNNING_PING_TIMEOUT); - return true; - } catch (UrlChecker.TimeoutException e) { + return ping(IS_RUNNING_PING_TIMEOUT); + } catch (AppiumServerAvailabilityChecker.ConnectionTimeout + | AppiumServerAvailabilityChecker.ConnectionError e) { return false; - } catch (MalformedURLException e) { - throw new AppiumServerHasNotBeenStartedLocallyException(e.getMessage(), e); + } catch (InterruptedException e) { + throw new RuntimeException(e); } } finally { lock.unlock(); } + } + private boolean ping(Duration timeout) throws InterruptedException { + var baseURL = fixBroadcastAddresses(getUrl()); + var statusUrl = addSuffix(baseURL, "/status"); + return availabilityChecker.waitUntilAvailable(statusUrl, timeout); } - private void ping(Duration timeout) throws UrlChecker.TimeoutException, MalformedURLException { - URL baseURL = getUrl(); - String host = baseURL.getHost(); + private URL fixBroadcastAddresses(URL url) { + var host = url.getHost(); // The operating system will block direct access to the universal broadcast IP address if (host.equals(BROADCAST_IP4_ADDRESS)) { - baseURL = replaceHost(baseURL, BROADCAST_IP4_ADDRESS, "127.0.0.1"); - } else if (host.equals(BROADCAST_IP6_ADDRESS)) { - baseURL = replaceHost(baseURL, BROADCAST_IP6_ADDRESS, "::1"); + return replaceHost(url, BROADCAST_IP4_ADDRESS, "127.0.0.1"); + } + if (host.equals(BROADCAST_IP6_ADDRESS)) { + return replaceHost(url, BROADCAST_IP6_ADDRESS, "::1"); } - URL status = addSuffix(baseURL, "/status"); - new UrlChecker().waitUntilAvailable(timeout.toMillis(), TimeUnit.MILLISECONDS, status); + return url; } /** * Starts the defined appium server. * - * @throws AppiumServerHasNotBeenStartedLocallyException If an error occurs while spawning the child process. + * @throws AppiumServerHasNotBeenStartedLocallyException If an error occurs on Appium server startup. * @see #stop() */ @Override @@ -172,40 +172,75 @@ public void start() throws AppiumServerHasNotBeenStartedLocallyException { } try { - ExternalProcess.Builder processBuilder = ExternalProcess.builder() + var processBuilder = ExternalProcess.builder() .command(this.nodeJSExec.getCanonicalPath(), nodeJSArgs) .copyOutputTo(stream); nodeJSEnvironment.forEach(processBuilder::environment); process = processBuilder.start(); + } catch (IOException e) { + throw new AppiumServerHasNotBeenStartedLocallyException(e); + } + + var didPingSucceed = false; + try { ping(startupTimeout); - } catch (Exception e) { - final Optional output = ofNullable(process) - .map(ExternalProcess::getOutput) - .filter(o -> !isNullOrEmpty(o)); - destroyProcess(); - List errorLines = new ArrayList<>(); - errorLines.add("The local appium server has not been started"); - errorLines.add(String.format("Reason: %s", e.getMessage())); - if (e instanceof UrlChecker.TimeoutException) { - errorLines.add(String.format( - "Consider increasing the server startup timeout value (currently %sms)", - startupTimeout.toMillis() - )); - } - errorLines.add( - String.format("Node.js executable path: %s", nodeJSExec.getAbsolutePath()) - ); - errorLines.add(String.format("Arguments: %s", nodeJSArgs)); - output.ifPresent(o -> errorLines.add(String.format("Output: %s", o))); + didPingSucceed = true; + } catch (AppiumServerAvailabilityChecker.ConnectionTimeout + | AppiumServerAvailabilityChecker.ConnectionError e) { + var errorLines = new ArrayList<>(generateDetailedErrorMessagePrefix(e)); + errorLines.addAll(retrieveServerDebugInfo()); throw new AppiumServerHasNotBeenStartedLocallyException( String.join("\n", errorLines), e ); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + if (!didPingSucceed) { + destroyProcess(); + } } } finally { lock.unlock(); } } + private List generateDetailedErrorMessagePrefix(RuntimeException e) { + var errorLines = new ArrayList(); + if (e instanceof AppiumServerAvailabilityChecker.ConnectionTimeout) { + errorLines.add(String.format( + "Appium HTTP server is not listening at %s after %s ms timeout. " + + "Consider increasing the server startup timeout value and " + + "check the server log for possible error messages occurrences.", getUrl(), + ((AppiumServerAvailabilityChecker.ConnectionTimeout) e).getTimeout().toMillis() + )); + } else if (e instanceof AppiumServerAvailabilityChecker.ConnectionError) { + var connectionError = (AppiumServerAvailabilityChecker.ConnectionError) e; + var statusCode = connectionError.getResponseCode(); + var statusUrl = connectionError.getStatusUrl(); + var payload = connectionError.getPayload(); + errorLines.add(String.format( + "Appium HTTP server has started and is listening although we were " + + "unable to get an OK response from %s. Make sure both the client " + + "and the server use the same base path '%s' and check the server log for possible " + + "error messages occurrences.", statusUrl, Optional.ofNullable(basePath).orElse("/") + )); + errorLines.add(String.format("Response status code: %s", statusCode)); + payload.ifPresent(p -> errorLines.add(String.format("Response payload: %s", p))); + } + return errorLines; + } + + private List retrieveServerDebugInfo() { + var result = new ArrayList(); + result.add(String.format("Node.js executable path: %s", nodeJSExec.getAbsolutePath())); + result.add(String.format("Arguments: %s", nodeJSArgs)); + ofNullable(process) + .map(ExternalProcess::getOutput) + .filter(o -> !isNullOrEmpty(o)) + .ifPresent(o -> result.add(String.format("Server log: %s", o))); + return result; + } + /** * Stops this service is it is currently running. This method will attempt to block until the * server has been fully shutdown. diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServerAvailabilityChecker.java b/src/main/java/io/appium/java_client/service/local/AppiumServerAvailabilityChecker.java new file mode 100644 index 000000000..2876c3707 --- /dev/null +++ b/src/main/java/io/appium/java_client/service/local/AppiumServerAvailabilityChecker.java @@ -0,0 +1,158 @@ +/* + * 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.service.local; + +import lombok.Getter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.time.Duration; +import java.time.Instant; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +public class AppiumServerAvailabilityChecker { + private static final Duration CONNECT_TIMEOUT = Duration.ofMillis(500); + private static final Duration READ_TIMEOUT = Duration.ofSeconds(1); + private static final Duration MAX_POLL_INTERVAL = Duration.ofMillis(320); + private static final Duration MIN_POLL_INTERVAL = Duration.ofMillis(10); + + /** + * Verifies a possibility of establishing a connection + * to a running Appium server. + * + * @param serverStatusUrl The URL of /status endpoint. + * @param timeout Wait timeout. If the server responds with non-200 error + * code then we are not going to retry, but throw an exception + * immediately. + * @return true in case of success + * @throws InterruptedException If the API is interrupted + * @throws ConnectionTimeout If it is not possible to successfully open + * an HTTP connection to the server's /status endpoint. + * @throws ConnectionError If an HTTP connection was opened successfully, + * but non-200 error code was received. + */ + public boolean waitUntilAvailable(URL serverStatusUrl, Duration timeout) throws InterruptedException { + var interval = MIN_POLL_INTERVAL; + var start = Instant.now(); + IOException lastError = null; + while (Duration.between(start, Instant.now()).compareTo(timeout) <= 0) { + HttpURLConnection connection = null; + try { + connection = connectToUrl(serverStatusUrl); + return checkResponse(connection); + } catch (IOException e) { + lastError = e; + } finally { + Optional.ofNullable(connection).ifPresent(HttpURLConnection::disconnect); + } + //noinspection BusyWait + Thread.sleep(interval.toMillis()); + interval = interval.compareTo(MAX_POLL_INTERVAL) >= 0 ? interval : interval.multipliedBy(2); + } + throw new ConnectionTimeout(timeout, lastError); + } + + private HttpURLConnection connectToUrl(URL url) throws IOException { + var connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout((int) CONNECT_TIMEOUT.toMillis()); + connection.setReadTimeout((int) READ_TIMEOUT.toMillis()); + connection.connect(); + return connection; + } + + private boolean checkResponse(HttpURLConnection connection) throws IOException { + var responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + return true; + } + var is = responseCode < HttpURLConnection.HTTP_BAD_REQUEST + ? connection.getInputStream() + : connection.getErrorStream(); + throw new ConnectionError(connection.getURL(), responseCode, is); + } + + @Getter + public static class ConnectionError extends RuntimeException { + private static final int MAX_PAYLOAD_LEN = 1024; + + private final URL statusUrl; + private final int responseCode; + private final Optional payload; + + /** + * Thrown on server connection errors. + * + * @param statusUrl Appium server status URL. + * @param responseCode The response code received from the URL above. + * @param body The response body stream received from the URL above. + */ + public ConnectionError(URL statusUrl, int responseCode, InputStream body) { + super(ConnectionError.class.getSimpleName()); + this.statusUrl = statusUrl; + this.responseCode = responseCode; + this.payload = readResponseStreamSafely(body); + } + + private static Optional readResponseStreamSafely(InputStream is) { + try (var br = new BufferedReader(new InputStreamReader(is))) { + var result = new LinkedList(); + String currentLine; + var payloadSize = 0L; + while ((currentLine = br.readLine()) != null) { + result.addFirst(currentLine); + payloadSize += currentLine.length(); + while (payloadSize > MAX_PAYLOAD_LEN && result.size() > 1) { + payloadSize -= result.removeLast().length(); + } + } + var s = abbreviate(result); + return s.isEmpty() ? Optional.empty() : Optional.of(s); + } catch (IOException e) { + return Optional.empty(); + } + } + + private static String abbreviate(List filo) { + var result = String.join("\n", filo).trim(); + return result.length() > MAX_PAYLOAD_LEN + ? "…" + result.substring(0, MAX_PAYLOAD_LEN) + : result; + } + } + + @Getter + public static class ConnectionTimeout extends RuntimeException { + private final Duration timeout; + + /** + * Thrown on server timeout errors. + * + * @param timeout Timeout value. + * @param cause Timeout cause. + */ + public ConnectionTimeout(Duration timeout, Throwable cause) { + super(ConnectionTimeout.class.getSimpleName(), cause); + this.timeout = timeout; + } + } +} diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServerHasNotBeenStartedLocallyException.java b/src/main/java/io/appium/java_client/service/local/AppiumServerHasNotBeenStartedLocallyException.java index 664e6a602..9c0afb248 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServerHasNotBeenStartedLocallyException.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServerHasNotBeenStartedLocallyException.java @@ -16,16 +16,16 @@ package io.appium.java_client.service.local; - public class AppiumServerHasNotBeenStartedLocallyException extends RuntimeException { + public AppiumServerHasNotBeenStartedLocallyException(String message, Throwable cause) { + super(message, cause); + } - private static final long serialVersionUID = 1L; - - public AppiumServerHasNotBeenStartedLocallyException(String messege, Throwable t) { - super(messege, t); + public AppiumServerHasNotBeenStartedLocallyException(String message) { + super(message); } - public AppiumServerHasNotBeenStartedLocallyException(String messege) { - super(messege); + public AppiumServerHasNotBeenStartedLocallyException(Throwable cause) { + super(cause); } } From 36a865326abe316fb4a719b63724cb6a086034d8 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 14 Mar 2024 18:18:17 +0200 Subject: [PATCH 328/501] release: v9.2.0 (#2131) --- CHANGELOG.md | 13 +++++++++++++ README.md | 24 ++++++++++++------------ gradle.properties | 2 +- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b3f9b0d5..62b862e69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.2.0_ +- **[ENHANCEMENTS]** + - Incorporate poll delay mechanism into `AppiumFluentWait` [#2116](https://github.com/appium/java-client/pull/2116) (Closes [#2111](https://github.com/appium/java-client/pull/2111)) + - Make server startup error messages more useful [#2130](https://github.com/appium/java-client/pull/2130) +- **[BUG FIX]** + - Set correct geolocation coordinates of the current device [#2109](https://github.com/appium/java-client/pull/2109) (Fixes [#2108](https://github.com/appium/java-client/pull/2108)) + - Always release annotated element reference from the builder instance [#2128](https://github.com/appium/java-client/pull/2128) + - Cache dynamic proxy classes created by ByteBuddy [#2129](https://github.com/appium/java-client/pull/2129) (Fixes [#2119](https://github.com/appium/java-client/pull/2119)) +- **[DEPENDENCY CHANGE]** + - Bump SLF4J from `2.0.11` to `2.0.12` [#2115](https://github.com/appium/java-client/pull/2115) +- **[DOCUMENTATION]** + - Improve release steps [#2107](https://github.com/appium/java-client/pull/2107) + _9.1.0_ - **[ENHANCEMENTS]** - Introduce better constructor argument validation for the `AppiumFieldDecorator` class. [#2070](https://github.com/appium/java-client/pull/2070) diff --git a/README.md b/README.md index 08bf82124..a20c5218e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Follow the [v8 to v9 Migration Guide](./docs/v8-to-v9-migration-guide.md) in ord ## v7 to v8 Migration -Since version 8 Appium Java Client had several major changes, which might require to +Since version 8 Appium Java Client had several major changes, which might require to update your client code. Make sure to follow the [v7 to v8 Migration Guide](./docs/v7-to-v8-migration-guide.md) in order to streamline the migration process. @@ -21,7 +21,7 @@ in order to streamline the migration process. ### Stable -#### Maven +#### Maven Add the following to pom.xml: @@ -62,19 +62,19 @@ Add the following to pom.xml: ``` Add the dependency: - + ```xml com.github.appium java-client latest commit ID from master branch -``` +``` #### Gradle Add the JitPack repository to your build file. Add it in your root build.gradle at the end of repositories: - + ```groovy allprojects { repositories { @@ -85,7 +85,7 @@ allprojects { ``` Add the dependency: - + ```groovy dependencies { implementation 'com.github.appium:java-client:latest commit id from master branch' @@ -95,7 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ---------------------------|----------------- - `9.1.0` | `4.17.0` + `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` N/A | `4.14.0` `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` @@ -126,7 +126,7 @@ Appium java client has dedicated classes to support the following Appium drivers - [Gecko](https://github.com/appium/appium-geckodriver): [GeckoDriver](src/main/java/io/appium/java_client/gecko/GeckoDriver.java) - [Mac2](https://github.com/appium/appium-mac2-driver): [Mac2Driver](src/main/java/io/appium/java_client/mac/Mac2Driver.java) -To automate other platforms that are not listed above you could use +To automate other platforms that are not listed above you could use [AppiumDriver](src/main/java/io/appium/java_client/AppiumDriver.java) or its custom derivatives. Appium java client is built on top of Selenium and implements same interfaces that the foundation @@ -225,7 +225,7 @@ try { Check the corresponding driver's READMEs to know the list of capabilities and features it supports. -You could find much more code examples by checking client's +You could find much more code examples by checking client's [unit and integration tests](src/test/java/io/appium/java_client). ## Troubleshooting @@ -235,7 +235,7 @@ You could find much more code examples by checking client's Appium Java client uses reflective access to private members of other modules to ensure proper functionality of several features, like Page Object model. If you get a runtime exception and `InaccessibleObjectException` is present in -the stacktrace, and your Java runtime is at version 16 or higher, then consider following +the stacktrace, and your Java runtime is at version 16 or higher, then consider following [Oracle's tutorial](https://docs.oracle.com/en/java/javase/16/migrate/migrating-jdk-8-later-jdk-releases.html#GUID-7BB28E4D-99B3-4078-BDC4-FC24180CE82B) and/or checking [existing issues](https://github.com/appium/java-client/search?q=InaccessibleObjectException&type=issues) for possible solutions. Basically, the idea there would be to explicitly allow @@ -251,9 +251,9 @@ framework code rather than run separately by a script or manually. Depending on the way the server process is started it may or may not inherit the currently active shell environment. That is why you may still receive errors about variables presence even though these variables ar actually defined for your command line interpreter. -Again, there is no universal solution to that, as there are many ways to spin up a new +Again, there is no universal solution to that, as there are many ways to spin up a new server process. Consider checking the [Appium Environment Troubleshooting](docs/environment.md) -document for more information on how to debug and fix process environment issues. +document for more information on how to debug and fix process environment issues. ## Changelog diff --git a/gradle.properties b/gradle.properties index 16c8cc317..fb33c2c1a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.17.0 # Please increment the value in a release -appiumClient.version=9.1.0 +appiumClient.version=9.2.0 From c7dfd5d159b13dbf7d0d2e06811cc9d087592097 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 16:42:11 +0200 Subject: [PATCH 329/501] build(deps): Bump org.owasp.dependencycheck from 9.0.9 to 9.0.10 (#2133) Bumps org.owasp.dependencycheck from 9.0.9 to 9.0.10. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0eb9997c9..3e8bd75ab 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.9' + id 'org.owasp.dependencycheck' version '9.0.10' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 79c6c0ce87cabc8ca5cfd3f047083a43203f5915 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:09:57 +0200 Subject: [PATCH 330/501] build(deps): Bump org.projectlombok:lombok from 1.18.30 to 1.18.32 (#2135) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.30 to 1.18.32. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.30...v1.18.32) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 3e8bd75ab..1372dae1f 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.30' - annotationProcessor 'org.projectlombok:lombok:1.18.30' + compileOnly 'org.projectlombok:lombok:1.18.32' + annotationProcessor 'org.projectlombok:lombok:1.18.32' if (project.hasProperty("isCI")) { api "org.seleniumhq.selenium:selenium-api:${seleniumVersion}" From 75e726229c899014b3af0aacce047b095e353a24 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 26 Mar 2024 23:20:43 +0400 Subject: [PATCH 331/501] refactor: Replace private usages of Guava Collections API with Java Collections API (#2136) --- .../appium/java_client/ExecuteCDPCommand.java | 3 +- .../appium/java_client/InteractsWithApps.java | 85 +++++++------------ .../io/appium/java_client/MobileCommand.java | 13 +-- .../appium/java_client/MultiTouchAction.java | 19 ++--- .../io/appium/java_client/TouchAction.java | 56 +++++------- .../AndroidStartScreenRecordingOptions.java | 14 +-- .../AndroidInstallApplicationOptions.java | 17 ++-- .../AndroidRemoveApplicationOptions.java | 11 +-- .../AndroidTerminateApplicationOptions.java | 9 +- .../geolocation/AndroidGeoLocation.java | 24 +++--- .../android/nativekey/KeyEvent.java | 17 ++-- .../android/nativekey/PressesKey.java | 8 +- .../driverscripts/ScriptOptions.java | 12 +-- .../BaseComparisonOptions.java | 10 +-- .../FeaturesMatchingOptions.java | 15 ++-- .../OccurrenceMatchingOptions.java | 15 ++-- .../ios/IOSStartScreenRecordingOptions.java | 18 ++-- .../java_client/ios/IOSTouchAction.java | 6 +- .../mac/Mac2StartScreenRecordingOptions.java | 20 ++--- .../AppiumNewSessionCommandPayload.java | 4 +- .../java_client/remote/SupportsLocation.java | 6 +- .../BaseScreenRecordingOptions.java | 7 +- .../BaseStartScreenRecordingOptions.java | 13 ++- .../ScreenRecordingUploadOptions.java | 22 ++--- .../service/local/AppiumServiceBuilder.java | 4 +- .../WindowsStartScreenRecordingOptions.java | 20 ++--- 26 files changed, 201 insertions(+), 247 deletions(-) diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java index 5af5e1f83..8b9f18317 100644 --- a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -16,7 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; @@ -44,7 +43,7 @@ default Map executeCdpCommand(String command, @Nullable Map) response.getValue()); + return Collections.unmodifiableMap((Map) response.getValue()); } /** diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index e254f6aa6..9fe25dc24 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -16,7 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.ApplicationState; import io.appium.java_client.appmanagement.BaseActivateApplicationOptions; import io.appium.java_client.appmanagement.BaseInstallApplicationOptions; @@ -28,9 +27,8 @@ import javax.annotation.Nullable; import java.time.Duration; -import java.util.Collections; +import java.util.HashMap; import java.util.Map; -import java.util.Optional; import static io.appium.java_client.MobileCommand.ACTIVATE_APP; import static io.appium.java_client.MobileCommand.INSTALL_APP; @@ -40,6 +38,7 @@ import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; import static io.appium.java_client.MobileCommand.TERMINATE_APP; import static java.util.Objects.requireNonNull; +import static java.util.Optional.ofNullable; @SuppressWarnings({"rawtypes", "unchecked"}) public interface InteractsWithApps extends ExecutesMethod, CanRememberExtensionPresence { @@ -63,23 +62,17 @@ default void installApp(String appPath) { default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) { final String extName = "mobile: installApp"; try { - Map args = ImmutableMap.builder() - .put("app", appPath) - .put("appPath", appPath) - .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) - .build(); + var args = new HashMap(); + args.put("app", appPath); + args.put("appPath", appPath); + ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback - Map args = ImmutableMap.builder() - .put("appPath", appPath) - .putAll(Optional.ofNullable(options).map( - opts -> Map.of("options", opts.build()) - ).orElseGet(Map::of)) - .build(); - CommandExecutionHelper.execute( - markExtensionAbsence(extName), Map.entry(INSTALL_APP, args) - ); + var args = new HashMap(); + args.put("appPath", appPath); + ofNullable(options).map(BaseOptions::build).ifPresent(opts -> args.put("options", opts)); + CommandExecutionHelper.execute(markExtensionAbsence(extName), Map.entry(INSTALL_APP, args)); } } @@ -153,22 +146,18 @@ default boolean removeApp(String bundleId) { default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOptions options) { final String extName = "mobile: removeApp"; try { - Map args = ImmutableMap.builder() - .put("bundleId", bundleId) - .put("appId", bundleId) - .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) - .build(); + var args = new HashMap(); + args.put("bundleId", bundleId); + args.put("appId", bundleId); + ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); return requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback - Map args = ImmutableMap.builder() - .put("bundleId", bundleId) - .putAll(Optional.ofNullable(options).map( - opts -> Map.of("options", opts.build()) - ).orElseGet(Map::of)) - .build(); + var args = new HashMap(); + args.put("bundleId", bundleId); + ofNullable(options).map(BaseOptions::build).ifPresent(opts -> args.put("options", opts)); //noinspection RedundantCast return requireNonNull( (Boolean) CommandExecutionHelper.execute( @@ -200,23 +189,17 @@ default void activateApp(String bundleId) { default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptions options) { final String extName = "mobile: activateApp"; try { - Map args = ImmutableMap.builder() - .put("bundleId", bundleId) - .put("appId", bundleId) - .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) - .build(); + var args = new HashMap(); + args.put("bundleId", bundleId); + args.put("appId", bundleId); + ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback - Map args = ImmutableMap.builder() - .put("bundleId", bundleId) - .putAll(Optional.ofNullable(options).map( - opts -> Map.of("options", opts.build()) - ).orElseGet(Map::of)) - .build(); - CommandExecutionHelper.execute( - markExtensionAbsence(extName), Map.entry(ACTIVATE_APP, args) - ); + var args = new HashMap(); + args.put("bundleId", bundleId); + ofNullable(options).map(BaseOptions::build).ifPresent(opts -> args.put("options", opts)); + CommandExecutionHelper.execute(markExtensionAbsence(extName), Map.entry(ACTIVATE_APP, args)); } } @@ -274,22 +257,18 @@ default boolean terminateApp(String bundleId) { default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplicationOptions options) { final String extName = "mobile: terminateApp"; try { - Map args = ImmutableMap.builder() - .put("bundleId", bundleId) - .put("appId", bundleId) - .putAll(Optional.ofNullable(options).map(BaseOptions::build).orElseGet(Collections::emptyMap)) - .build(); + var args = new HashMap(); + args.put("bundleId", bundleId); + args.put("appId", bundleId); + ofNullable(options).map(BaseOptions::build).ifPresent(args::putAll); return requireNonNull( CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args) ); } catch (UnsupportedCommandException | InvalidArgumentException e) { // TODO: Remove the fallback - Map args = ImmutableMap.builder() - .put("bundleId", bundleId) - .putAll(Optional.ofNullable(options).map( - opts -> Map.of("options", opts.build()) - ).orElseGet(Map::of)) - .build(); + var args = new HashMap(); + args.put("bundleId", bundleId); + ofNullable(options).map(BaseOptions::build).ifPresent(opts -> args.put("options", opts)); //noinspection RedundantCast return requireNonNull( (Boolean) CommandExecutionHelper.execute( diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 6f7eafb34..029c1abb7 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -27,6 +27,7 @@ import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -610,12 +611,12 @@ public static ImmutableMap prepareArguments(String[] params, public static Map.Entry> compareImagesCommand(ComparisonMode mode, byte[] img1Data, byte[] img2Data, @Nullable BaseComparisonOptions options) { - ImmutableMap.Builder argsBuilder = ImmutableMap.builder() - .put("mode", mode.toString()) - .put("firstImage", new String(img1Data, StandardCharsets.UTF_8)) - .put("secondImage", new String(img2Data, StandardCharsets.UTF_8)); - Optional.ofNullable(options).ifPresent(opts -> argsBuilder.put("options", options.build())); - return Map.entry(COMPARE_IMAGES, argsBuilder.build()); + var args = new HashMap(); + args.put("mode", mode.toString()); + args.put("firstImage", new String(img1Data, StandardCharsets.UTF_8)); + args.put("secondImage", new String(img2Data, StandardCharsets.UTF_8)); + Optional.ofNullable(options).ifPresent(opts -> args.put("options", options.build())); + return Map.entry(COMPARE_IMAGES, Collections.unmodifiableMap(args)); } /** diff --git a/src/main/java/io/appium/java_client/MultiTouchAction.java b/src/main/java/io/appium/java_client/MultiTouchAction.java index 0a133756e..d82b47b1f 100644 --- a/src/main/java/io/appium/java_client/MultiTouchAction.java +++ b/src/main/java/io/appium/java_client/MultiTouchAction.java @@ -16,8 +16,7 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableList; - +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -53,12 +52,12 @@ @Deprecated public class MultiTouchAction implements PerformsActions { - private ImmutableList.Builder actions; + private List actions; private PerformsTouchActions performsTouchActions; public MultiTouchAction(PerformsTouchActions performsTouchActions) { this.performsTouchActions = performsTouchActions; - actions = ImmutableList.builder(); + actions = new ArrayList<>(); } /** @@ -76,21 +75,19 @@ public MultiTouchAction add(TouchAction action) { * Perform the multi-touch action on the mobile performsTouchActions. */ public MultiTouchAction perform() { - List touchActions = actions.build(); - checkArgument(touchActions.size() > 0, + checkArgument(!actions.isEmpty(), "MultiTouch action must have at least one TouchAction added before it can be performed"); - if (touchActions.size() > 1) { + if (actions.size() > 1) { performsTouchActions.performMultiTouchAction(this); return this; } //android doesn't like having multi-touch actions with only a single TouchAction... - performsTouchActions.performTouchAction(touchActions.get(0)); + performsTouchActions.performTouchAction(actions.get(0)); return this; } protected Map> getParameters() { return Map.of("actions", - actions.build().stream().map(touchAction -> - touchAction.getParameters().get("actions")).collect(toList()) + actions.stream().map(touchAction -> touchAction.getParameters().get("actions")).collect(toList()) ); } @@ -100,7 +97,7 @@ protected Map> getParameters() { * @return this MultiTouchAction, for possible segmented-touches. */ protected MultiTouchAction clearActions() { - actions = ImmutableList.builder(); + actions = new ArrayList<>(); return this; } } diff --git a/src/main/java/io/appium/java_client/TouchAction.java b/src/main/java/io/appium/java_client/TouchAction.java index be76d1610..6f6621f0b 100644 --- a/src/main/java/io/appium/java_client/TouchAction.java +++ b/src/main/java/io/appium/java_client/TouchAction.java @@ -16,8 +16,6 @@ package io.appium.java_client; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.touch.ActionOptions; import io.appium.java_client.touch.LongPressOptions; import io.appium.java_client.touch.TapOptions; @@ -25,10 +23,12 @@ import io.appium.java_client.touch.offset.ElementOption; import io.appium.java_client.touch.offset.PointOption; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; -import static com.google.common.collect.ImmutableList.builder; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; @@ -54,12 +54,12 @@ @Deprecated public class TouchAction> implements PerformsActions { - protected ImmutableList.Builder parameterBuilder; + protected List parameters; private PerformsTouchActions performsTouchActions; public TouchAction(PerformsTouchActions performsTouchActions) { this.performsTouchActions = requireNonNull(performsTouchActions); - parameterBuilder = builder(); + parameters = new ArrayList<>(); } /** @@ -69,7 +69,7 @@ public TouchAction(PerformsTouchActions performsTouchActions) { * @return this TouchAction, for chaining. */ public T press(PointOption pressOptions) { - parameterBuilder.add(new ActionParameter("press", pressOptions)); + parameters.add(new ActionParameter("press", pressOptions)); //noinspection unchecked return (T) this; } @@ -80,8 +80,7 @@ public T press(PointOption pressOptions) { * @return this TouchAction, for chaining. */ public T release() { - ActionParameter action = new ActionParameter("release"); - parameterBuilder.add(action); + parameters.add(new ActionParameter("release")); //noinspection unchecked return (T) this; } @@ -98,8 +97,7 @@ public T release() { * @return this TouchAction, for chaining. */ public T moveTo(PointOption moveToOptions) { - ActionParameter action = new ActionParameter("moveTo", moveToOptions); - parameterBuilder.add(action); + parameters.add(new ActionParameter("moveTo", moveToOptions)); return (T) this; } @@ -110,8 +108,7 @@ public T moveTo(PointOption moveToOptions) { * @return this TouchAction, for chaining. */ public T tap(TapOptions tapOptions) { - ActionParameter action = new ActionParameter("tap", tapOptions); - parameterBuilder.add(action); + parameters.add(new ActionParameter("tap", tapOptions)); return (T) this; } @@ -122,8 +119,7 @@ public T tap(TapOptions tapOptions) { * @return this TouchAction, for chaining. */ public T tap(PointOption tapOptions) { - ActionParameter action = new ActionParameter("tap", tapOptions); - parameterBuilder.add(action); + parameters.add(new ActionParameter("tap", tapOptions)); return (T) this; } @@ -133,8 +129,7 @@ public T tap(PointOption tapOptions) { * @return this TouchAction, for chaining. */ public T waitAction() { - ActionParameter action = new ActionParameter("wait"); - parameterBuilder.add(action); + parameters.add(new ActionParameter("wait")); //noinspection unchecked return (T) this; } @@ -146,8 +141,7 @@ public T waitAction() { * @return this TouchAction, for chaining. */ public T waitAction(WaitOptions waitOptions) { - ActionParameter action = new ActionParameter("wait", waitOptions); - parameterBuilder.add(action); + parameters.add(new ActionParameter("wait", waitOptions)); //noinspection unchecked return (T) this; } @@ -159,8 +153,7 @@ public T waitAction(WaitOptions waitOptions) { * @return this TouchAction, for chaining. */ public T longPress(LongPressOptions longPressOptions) { - ActionParameter action = new ActionParameter("longPress", longPressOptions); - parameterBuilder.add(action); + parameters.add(new ActionParameter("longPress", longPressOptions)); //noinspection unchecked return (T) this; } @@ -172,8 +165,7 @@ public T longPress(LongPressOptions longPressOptions) { * @return this TouchAction, for chaining. */ public T longPress(PointOption longPressOptions) { - ActionParameter action = new ActionParameter("longPress", longPressOptions); - parameterBuilder.add(action); + parameters.add(new ActionParameter("longPress", longPressOptions)); //noinspection unchecked return (T) this; } @@ -182,8 +174,7 @@ public T longPress(PointOption longPressOptions) { * Cancel this action, if it was partially completed by the performsTouchActions. */ public void cancel() { - ActionParameter action = new ActionParameter("cancel"); - parameterBuilder.add(action); + parameters.add(new ActionParameter("cancel")); this.perform(); } @@ -205,7 +196,7 @@ public T perform() { */ protected Map> getParameters() { return Map.of("actions", - parameterBuilder.build().stream().map(ActionParameter::getParameterMap).collect(toList()) + parameters.stream().map(ActionParameter::getParameterMap).collect(toList()) ); } @@ -215,7 +206,7 @@ protected Map> getParameters() { * @return this TouchAction, for possible segmented-touches. */ protected T clearParameters() { - parameterBuilder = builder(); + parameters = new ArrayList<>(); //noinspection unchecked return (T) this; } @@ -224,26 +215,25 @@ protected T clearParameters() { * Just holds values to eventually return the parameters required for the mjsonwp. */ protected class ActionParameter { - private String actionName; - private ImmutableMap.Builder optionsBuilder; + private final String actionName; + private final Map options; public ActionParameter(String actionName) { this.actionName = actionName; - optionsBuilder = ImmutableMap.builder(); + options = new HashMap<>(); } public ActionParameter(String actionName, ActionOptions opts) { + this(actionName); requireNonNull(opts); - this.actionName = actionName; - optionsBuilder = ImmutableMap.builder(); //noinspection unchecked - optionsBuilder.putAll(opts.build()); + options.putAll(opts.build()); } public Map getParameterMap() { return Map.of( "action", actionName, - "options", optionsBuilder.build() + "options", Collections.unmodifiableMap(options) ); } } diff --git a/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java index 14c575208..dd6ee2b2f 100644 --- a/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/android/AndroidStartScreenRecordingOptions.java @@ -16,11 +16,12 @@ package io.appium.java_client.android; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import io.appium.java_client.screenrecording.ScreenRecordingUploadOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -105,11 +106,10 @@ public AndroidStartScreenRecordingOptions withTimeLimit(Duration timeLimit) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(bitRate).ifPresent(x -> builder.put("bitRate", x)); - ofNullable(videoSize).ifPresent(x -> builder.put("videoSize", x)); - ofNullable(isBugReportEnabled).ifPresent(x -> builder.put("bugReport", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(bitRate).ifPresent(x -> map.put("bitRate", x)); + ofNullable(videoSize).ifPresent(x -> map.put("videoSize", x)); + ofNullable(isBugReportEnabled).ifPresent(x -> map.put("bugReport", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java index 27ce3e4a6..216641b84 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidInstallApplicationOptions.java @@ -16,10 +16,11 @@ package io.appium.java_client.android.appmanagement; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.BaseInstallApplicationOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; @@ -138,12 +139,12 @@ public AndroidInstallApplicationOptions withGrantPermissionsDisabled() { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(replace).ifPresent(x -> builder.put("replace", x)); - ofNullable(timeout).ifPresent(x -> builder.put("timeout", x.toMillis())); - ofNullable(allowTestPackages).ifPresent(x -> builder.put("allowTestPackages", x)); - ofNullable(useSdcard).ifPresent(x -> builder.put("useSdcard", x)); - ofNullable(grantPermissions).ifPresent(x -> builder.put("grantPermissions", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(replace).ifPresent(x -> map.put("replace", x)); + ofNullable(timeout).ifPresent(x -> map.put("timeout", x.toMillis())); + ofNullable(allowTestPackages).ifPresent(x -> map.put("allowTestPackages", x)); + ofNullable(useSdcard).ifPresent(x -> map.put("useSdcard", x)); + ofNullable(grantPermissions).ifPresent(x -> map.put("grantPermissions", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java index 9783d9fda..fe68a0073 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidRemoveApplicationOptions.java @@ -16,10 +16,11 @@ package io.appium.java_client.android.appmanagement; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; @@ -68,9 +69,9 @@ public AndroidRemoveApplicationOptions withKeepDataDisabled() { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(timeout).ifPresent(x -> builder.put("timeout", x.toMillis())); - ofNullable(keepData).ifPresent(x -> builder.put("keepData", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(timeout).ifPresent(x -> map.put("timeout", x.toMillis())); + ofNullable(keepData).ifPresent(x -> map.put("keepData", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java b/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java index c9a0a02d8..b683c5a8f 100644 --- a/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java +++ b/src/main/java/io/appium/java_client/android/appmanagement/AndroidTerminateApplicationOptions.java @@ -16,10 +16,11 @@ package io.appium.java_client.android.appmanagement; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; @@ -45,8 +46,8 @@ public AndroidTerminateApplicationOptions withTimeout(Duration timeout) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(timeout).ifPresent(x -> builder.put("timeout", x.toMillis())); - return builder.build(); + var map = new HashMap(); + ofNullable(timeout).ifPresent(x -> map.put("timeout", x.toMillis())); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java index 7cd53e698..f8e2d24c7 100644 --- a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java +++ b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java @@ -16,8 +16,8 @@ package io.appium.java_client.android.geolocation; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -110,16 +110,14 @@ public AndroidGeoLocation withSpeed(double speed) { * @return Parameters mapping */ public Map build() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(longitude).map(x -> builder.put("longitude", x)) - .orElseThrow(() -> new IllegalArgumentException( - "A valid 'longitude' must be provided")); - ofNullable(latitude).map(x -> builder.put("latitude", x)) - .orElseThrow(() -> new IllegalArgumentException( - "A valid 'latitude' must be provided")); - ofNullable(altitude).ifPresent(x -> builder.put("altitude", x)); - ofNullable(satellites).ifPresent(x -> builder.put("satellites", x)); - ofNullable(speed).ifPresent(x -> builder.put("speed", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(longitude).map(x -> map.put("longitude", x)).orElseThrow(() -> new IllegalArgumentException( + "A valid 'longitude' must be provided")); + ofNullable(latitude).map(x -> map.put("latitude", x)).orElseThrow(() -> new IllegalArgumentException( + "A valid 'latitude' must be provided")); + ofNullable(altitude).ifPresent(x -> map.put("altitude", x)); + ofNullable(satellites).ifPresent(x -> map.put("satellites", x)); + ofNullable(speed).ifPresent(x -> map.put("speed", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java b/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java index 8bf0a99e2..3d695e4c3 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java +++ b/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java @@ -16,8 +16,8 @@ package io.appium.java_client.android.nativekey; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -82,13 +82,12 @@ public KeyEvent withFlag(KeyEventFlag keyEventFlag) { * @throws IllegalStateException if key code is not set */ public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - final int keyCode = ofNullable(this.keyCode) - .orElseThrow(() -> new IllegalStateException("The key code must be set")); - builder.put("keycode", keyCode); - ofNullable(this.metaState).ifPresent(x -> builder.put("metastate", x)); - ofNullable(this.flags).ifPresent(x -> builder.put("flags", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(this.keyCode).map(x -> map.put("keycode", x)).orElseThrow(() -> new IllegalStateException( + "The key code must be set")); + ofNullable(this.metaState).ifPresent(x -> map.put("metastate", x)); + ofNullable(this.flags).ifPresent(x -> map.put("flags", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java index 641087050..af633a1d9 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java +++ b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java @@ -16,12 +16,12 @@ package io.appium.java_client.android.nativekey; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import org.openqa.selenium.UnsupportedCommandException; +import java.util.HashMap; import java.util.Map; import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE; @@ -55,10 +55,8 @@ default void pressKey(KeyEvent keyEvent) { default void longPressKey(KeyEvent keyEvent) { final String extName = "mobile: pressKey"; try { - Map args = ImmutableMap.builder() - .putAll(keyEvent.build()) - .put("isLongPress", true) - .build(); + var args = new HashMap<>(keyEvent.build()); + args.put("isLongPress", true); CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback diff --git a/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java b/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java index 11c4f650a..41b5cd78e 100644 --- a/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java +++ b/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java @@ -16,8 +16,8 @@ package io.appium.java_client.driverscripts; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Objects.requireNonNull; @@ -58,9 +58,9 @@ public ScriptOptions withTimeout(long timeoutMs) { * @return The map containing the provided options */ public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(scriptType).ifPresent(x -> builder.put("type", x.name().toLowerCase())); - ofNullable(timeoutMs).ifPresent(x -> builder.put("timeout", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(scriptType).ifPresent(x -> map.put("type", x.name().toLowerCase())); + ofNullable(timeoutMs).ifPresent(x -> map.put("timeout", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java b/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java index b91974009..bd20f884a 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/BaseComparisonOptions.java @@ -16,8 +16,8 @@ package io.appium.java_client.imagecomparison; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -45,8 +45,8 @@ public T withEnabledVisualization() { * @return comparison options mapping. */ public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(visualize).ifPresent(x -> builder.put("visualize", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(visualize).ifPresent(x -> map.put("visualize", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java index 42e4cd976..3fd56517c 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingOptions.java @@ -16,8 +16,8 @@ package io.appium.java_client.imagecomparison; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; @@ -68,11 +68,10 @@ public FeaturesMatchingOptions withGoodMatchesFactor(int factor) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(detectorName).ifPresent(x -> builder.put("detectorName", x)); - ofNullable(matchFunc).ifPresent(x -> builder.put("matchFunc", x)); - ofNullable(goodMatchesFactor).ifPresent(x -> builder.put("goodMatchesFactor", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(detectorName).ifPresent(x -> map.put("detectorName", x)); + ofNullable(matchFunc).ifPresent(x -> map.put("matchFunc", x)); + ofNullable(goodMatchesFactor).ifPresent(x -> map.put("goodMatchesFactor", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java index d75e1d7e1..314a237dc 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingOptions.java @@ -16,8 +16,8 @@ package io.appium.java_client.imagecomparison; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -66,11 +66,10 @@ public OccurrenceMatchingOptions withMatchNeighbourThreshold(int threshold) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(threshold).ifPresent(x -> builder.put("threshold", x)); - ofNullable(matchNeighbourThreshold).ifPresent(x -> builder.put("matchNeighbourThreshold", x)); - ofNullable(multiple).ifPresent(x -> builder.put("multiple", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(threshold).ifPresent(x -> map.put("threshold", x)); + ofNullable(matchNeighbourThreshold).ifPresent(x -> map.put("matchNeighbourThreshold", x)); + ofNullable(multiple).ifPresent(x -> map.put("multiple", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java index b0673a5e0..a608cae0f 100644 --- a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java @@ -16,11 +16,12 @@ package io.appium.java_client.ios; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import io.appium.java_client.screenrecording.ScreenRecordingUploadOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Objects.requireNonNull; @@ -133,13 +134,12 @@ public IOSStartScreenRecordingOptions withVideoFilters(String filters) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(videoType).map(x -> builder.put("videoType", x)); - ofNullable(videoQuality).map(x -> builder.put("videoQuality", x)); - ofNullable(videoScale).map(x -> builder.put("videoScale", x)); - ofNullable(videoFilters).map(x -> builder.put("videoFilters", x)); - ofNullable(fps).map(x -> builder.put("videoFps", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(videoType).map(x -> map.put("videoType", x)); + ofNullable(videoQuality).map(x -> map.put("videoQuality", x)); + ofNullable(videoScale).map(x -> map.put("videoScale", x)); + ofNullable(videoFilters).map(x -> map.put("videoFilters", x)); + ofNullable(fps).map(x -> map.put("videoFps", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/ios/IOSTouchAction.java b/src/main/java/io/appium/java_client/ios/IOSTouchAction.java index 01a98f9e5..aca87955d 100644 --- a/src/main/java/io/appium/java_client/ios/IOSTouchAction.java +++ b/src/main/java/io/appium/java_client/ios/IOSTouchAction.java @@ -48,9 +48,7 @@ public IOSTouchAction(PerformsTouchActions performsTouchActions) { * @return self-reference */ public IOSTouchAction doubleTap(PointOption doubleTapOption) { - ActionParameter action = new ActionParameter("doubleTap", - doubleTapOption); - parameterBuilder.add(action); + parameters.add(new ActionParameter("doubleTap", doubleTapOption)); return this; } @@ -61,7 +59,7 @@ public IOSTouchAction doubleTap(PointOption doubleTapOption) { * @return this TouchAction, for chaining. */ public IOSTouchAction press(IOSPressOptions pressOptions) { - parameterBuilder.add(new ActionParameter("press", pressOptions)); + parameters.add(new ActionParameter("press", pressOptions)); return this; } } diff --git a/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java index 45c573126..342598b62 100644 --- a/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/mac/Mac2StartScreenRecordingOptions.java @@ -16,10 +16,11 @@ package io.appium.java_client.mac; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -139,14 +140,13 @@ public Mac2StartScreenRecordingOptions withTimeLimit(Duration timeLimit) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(fps).map(x -> builder.put("fps", x)); - ofNullable(preset).map(x -> builder.put("preset", x)); - ofNullable(videoFilter).map(x -> builder.put("videoFilter", x)); - ofNullable(captureClicks).map(x -> builder.put("captureClicks", x)); - ofNullable(captureCursor).map(x -> builder.put("captureCursor", x)); - ofNullable(deviceId).map(x -> builder.put("deviceId", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(fps).map(x -> map.put("fps", x)); + ofNullable(preset).map(x -> map.put("preset", x)); + ofNullable(videoFilter).map(x -> map.put("videoFilter", x)); + ofNullable(captureClicks).map(x -> map.put("captureClicks", x)); + ofNullable(captureCursor).map(x -> map.put("captureCursor", x)); + ofNullable(deviceId).map(x -> map.put("deviceId", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java index 5f7655c2d..63fc663a5 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java +++ b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java @@ -16,7 +16,6 @@ package io.appium.java_client.remote; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.remote.options.BaseOptions; import org.openqa.selenium.Capabilities; import org.openqa.selenium.internal.Require; @@ -24,6 +23,7 @@ import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; @@ -37,7 +37,7 @@ public class AppiumNewSessionCommandPayload extends CommandPayload { private static Map makeW3CSafe(Capabilities possiblyInvalidCapabilities) { return Require.nonNull("Capabilities", possiblyInvalidCapabilities) .asMap().entrySet().stream() - .collect(ImmutableMap.toImmutableMap( + .collect(Collectors.toUnmodifiableMap( entry -> BaseOptions.toW3cName(entry.getKey()), Map.Entry::getValue )); diff --git a/src/main/java/io/appium/java_client/remote/SupportsLocation.java b/src/main/java/io/appium/java_client/remote/SupportsLocation.java index 45d81f36c..91e12f0fa 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsLocation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsLocation.java @@ -16,7 +16,6 @@ package io.appium.java_client.remote; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.MobileCommand; @@ -26,6 +25,7 @@ import org.openqa.selenium.html5.LocationContext; import org.openqa.selenium.remote.html5.RemoteLocationContext; +import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -86,10 +86,10 @@ default void setLocation(Location location) { * @param location A {@link Location} containing the new location information. */ default void setLocation(io.appium.java_client.Location location) { - ImmutableMap.Builder locationParameters = ImmutableMap.builder(); + var locationParameters = new HashMap(); locationParameters.put("latitude", location.getLatitude()); locationParameters.put("longitude", location.getLongitude()); Optional.ofNullable(location.getAltitude()).ifPresent(altitude -> locationParameters.put("altitude", altitude)); - execute(MobileCommand.SET_LOCATION, Map.of("location", locationParameters.build())); + execute(MobileCommand.SET_LOCATION, Map.of("location", locationParameters)); } } diff --git a/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java b/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java index e4e3797ad..fd75dc2d6 100644 --- a/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/BaseScreenRecordingOptions.java @@ -16,8 +16,6 @@ package io.appium.java_client.screenrecording; -import com.google.common.collect.ImmutableMap; - import java.util.Map; import static java.util.Objects.requireNonNull; @@ -46,9 +44,6 @@ protected T withUploadOptions(ScreenRecordingUploadOptions uploadOptions) { * @return arguments mapping. */ public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - //noinspection unchecked - ofNullable(uploadOptions).map(x -> builder.putAll(x.build())); - return builder.build(); + return ofNullable(uploadOptions).map(ScreenRecordingUploadOptions::build).orElseGet(Map::of); } } diff --git a/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java index 1ce5af766..55716b622 100644 --- a/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/BaseStartScreenRecordingOptions.java @@ -16,9 +16,9 @@ package io.appium.java_client.screenrecording; -import com.google.common.collect.ImmutableMap; - import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Objects.requireNonNull; @@ -66,10 +66,9 @@ public T disableForcedRestart() { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(timeLimit).map(x -> builder.put("timeLimit", x.getSeconds())); - ofNullable(forceRestart).map(x -> builder.put("forceRestart", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(timeLimit).map(x -> map.put("timeLimit", x.getSeconds())); + ofNullable(forceRestart).map(x -> map.put("forceRestart", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java b/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java index 97115a253..e018b47ea 100644 --- a/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java +++ b/src/main/java/io/appium/java_client/screenrecording/ScreenRecordingUploadOptions.java @@ -16,8 +16,8 @@ package io.appium.java_client.screenrecording; -import com.google.common.collect.ImmutableMap; - +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Objects.requireNonNull; @@ -123,14 +123,14 @@ public ScreenRecordingUploadOptions withHeaders(Map headers) { * @return arguments mapping. */ public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - ofNullable(remotePath).map(x -> builder.put("remotePath", x)); - ofNullable(user).map(x -> builder.put("user", x)); - ofNullable(pass).map(x -> builder.put("pass", x)); - ofNullable(method).map(x -> builder.put("method", x)); - ofNullable(fileFieldName).map(x -> builder.put("fileFieldName", x)); - ofNullable(formFields).map(x -> builder.put("formFields", x)); - ofNullable(headers).map(x -> builder.put("headers", x)); - return builder.build(); + var map = new HashMap(); + ofNullable(remotePath).map(x -> map.put("remotePath", x)); + ofNullable(user).map(x -> map.put("user", x)); + ofNullable(pass).map(x -> map.put("pass", x)); + ofNullable(method).map(x -> map.put("method", x)); + ofNullable(fileFieldName).map(x -> map.put("fileFieldName", x)); + ofNullable(formFields).map(x -> map.put("formFields", x)); + ofNullable(headers).map(x -> map.put("headers", x)); + return Collections.unmodifiableMap(map); } } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index a8690c78b..ad3729e77 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -16,7 +16,6 @@ package io.appium.java_client.service.local; -import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.appium.java_client.android.options.context.SupportsChromedriverExecutableOption; @@ -42,6 +41,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -395,7 +395,7 @@ protected List createArgs() { argList.add(capabilitiesToCmdlineArg()); } - return new ImmutableList.Builder().addAll(argList).build(); + return Collections.unmodifiableList(argList); } @Override diff --git a/src/main/java/io/appium/java_client/windows/WindowsStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/windows/WindowsStartScreenRecordingOptions.java index ff90a08f2..8f5d5bc72 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/windows/WindowsStartScreenRecordingOptions.java @@ -16,10 +16,11 @@ package io.appium.java_client.windows; -import com.google.common.collect.ImmutableMap; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static java.util.Optional.ofNullable; @@ -138,14 +139,13 @@ public WindowsStartScreenRecordingOptions withTimeLimit(Duration timeLimit) { @Override public Map build() { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.putAll(super.build()); - ofNullable(fps).map(x -> builder.put("fps", x)); - ofNullable(preset).map(x -> builder.put("preset", x)); - ofNullable(videoFilter).map(x -> builder.put("videoFilter", x)); - ofNullable(captureClicks).map(x -> builder.put("captureClicks", x)); - ofNullable(captureCursor).map(x -> builder.put("captureCursor", x)); - ofNullable(audioInput).map(x -> builder.put("audioInput", x)); - return builder.build(); + var map = new HashMap<>(super.build()); + ofNullable(fps).map(x -> map.put("fps", x)); + ofNullable(preset).map(x -> map.put("preset", x)); + ofNullable(videoFilter).map(x -> map.put("videoFilter", x)); + ofNullable(captureClicks).map(x -> map.put("captureClicks", x)); + ofNullable(captureCursor).map(x -> map.put("captureCursor", x)); + ofNullable(audioInput).map(x -> map.put("audioInput", x)); + return Collections.unmodifiableMap(map); } } From a60a7cc9b48f0f08e83c85a3b38dd7b4b1c374a3 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 27 Mar 2024 09:00:10 +0400 Subject: [PATCH 332/501] build: Restore execution of lost tests (#2139) --- build.gradle | 2 ++ src/test/java/io/appium/java_client/TestUtils.java | 7 ++++++- .../pagefactory_tests/DesktopBrowserCompatibilityTest.java | 3 ++- .../appium/java_client/pagefactory_tests/TimeoutTest.java | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1372dae1f..0b3860f17 100644 --- a/build.gradle +++ b/build.gradle @@ -207,6 +207,8 @@ test { includeTestsMatching 'io.appium.java_client.drivers.options.*' includeTestsMatching 'io.appium.java_client.events.*' includeTestsMatching 'io.appium.java_client.internal.*' + includeTestsMatching 'io.appium.java_client.pagefactory_tests.DesktopBrowserCompatibilityTest' + includeTestsMatching 'io.appium.java_client.pagefactory_tests.TimeoutTest' includeTestsMatching 'io.appium.java_client.proxy.*' includeTestsMatching 'io.appium.java_client.remote.*' includeTestsMatching 'io.appium.java_client.touch.*' diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index 6a968a4e1..aaf254f75 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -10,6 +10,7 @@ import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; +import java.net.URISyntaxException; import java.net.URL; import java.net.UnknownHostException; import java.nio.file.Files; @@ -35,7 +36,11 @@ public static Path resourcePathToLocalPath(String resourcePath) { if (url == null) { throw new IllegalArgumentException(String.format("Cannot find the '%s' resource", resourcePath)); } - return Paths.get(url.getPath()); + try { + return Paths.get(url.toURI()); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } } public static String resourceAsString(String resourcePath) { diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index aeefba86e..0a890dc67 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -26,6 +26,7 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBys; import org.openqa.selenium.support.PageFactory; @@ -58,7 +59,7 @@ public class DesktopBrowserCompatibilityTest { } @Test public void chromeTest() { - WebDriver driver = new ChromeDriver(); + WebDriver driver = new ChromeDriver(new ChromeOptions().addArguments("--headless=new")); try { PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(15)), this); driver.get(helloAppiumHtml().toUri().toString()); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java index a9d44562d..32d23c874 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java @@ -25,6 +25,7 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.support.FindAll; import org.openqa.selenium.support.FindBy; @@ -86,7 +87,7 @@ public static void beforeAll() { * The setting up. */ @BeforeEach public void setUp() { - driver = new ChromeDriver(); + driver = new ChromeDriver(new ChromeOptions().addArguments("--headless=new")); timeOutDuration = DEFAULT_WAITING_TIMEOUT; initElements(new AppiumFieldDecorator(driver, timeOutDuration), this); } From 60d5f24828baadd7c6edbf97652e2dccef08189c Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 27 Mar 2024 23:51:21 +0400 Subject: [PATCH 333/501] chore: Bump minimum Selenium version to `4.19.0` (#2142) --- README.md | 1 + gradle.properties | 2 +- .../remote/AppiumProtocolHandshake.java | 50 ++++++------------- 3 files changed, 18 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index a20c5218e..b0ee499da 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ---------------------------|----------------- + | `4.19.0` `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` N/A | `4.14.0` diff --git a/gradle.properties b/gradle.properties index fb33c2c1a..306b374dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.17.0 +selenium.version=4.19.0 # Please increment the value in a release appiumClient.version=9.2.0 diff --git a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java index 0f42b9a51..f92a3632d 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java +++ b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java @@ -16,8 +16,6 @@ package io.appium.java_client.remote; -import com.google.common.io.CountingOutputStream; -import com.google.common.io.FileBackedOutputStream; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.SessionNotCreatedException; @@ -28,21 +26,17 @@ import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.NewSessionPayload; import org.openqa.selenium.remote.ProtocolHandshake; +import org.openqa.selenium.remote.http.Contents; import org.openqa.selenium.remote.http.HttpHandler; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; +import java.io.StringWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; -import static java.nio.charset.StandardCharsets.UTF_8; - @SuppressWarnings("UnstableApiUsage") public class AppiumProtocolHandshake extends ProtocolHandshake { private static void writeJsonPayload(NewSessionPayload srcPayload, Appendable destination) { @@ -108,34 +102,22 @@ public Result createSession(HttpHandler client, Command command) throws IOExcept } @Override - public Either createSession( - HttpHandler client, NewSessionPayload payload) throws IOException { - int threshold = (int) Math.min(Runtime.getRuntime().freeMemory() / 10, Integer.MAX_VALUE); - FileBackedOutputStream os = new FileBackedOutputStream(threshold, true); + public Either createSession(HttpHandler client, NewSessionPayload payload) { - try (CountingOutputStream counter = new CountingOutputStream(os); - Writer writer = new OutputStreamWriter(counter, UTF_8)) { - writeJsonPayload(payload, writer); + StringWriter stringWriter = new StringWriter(); + writeJsonPayload(payload, stringWriter); - Supplier contentSupplier = () -> { - try { - return os.asByteSource().openBufferedStream(); - } catch (IOException e) { - throw new RuntimeException(e); - } - }; - try { - Method createSessionMethod = ProtocolHandshake.class.getDeclaredMethod( - "createSession", HttpHandler.class, Supplier.class, long.class - ); - createSessionMethod.setAccessible(true); - //noinspection unchecked - return (Either) createSessionMethod.invoke( - this, client, contentSupplier, counter.getCount() - ); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - throw new WebDriverException(e); - } + try { + Method createSessionMethod = ProtocolHandshake.class.getDeclaredMethod( + "createSession", HttpHandler.class, Contents.Supplier.class + ); + createSessionMethod.setAccessible(true); + //noinspection unchecked + return (Either) createSessionMethod.invoke( + this, client, Contents.utf8String(stringWriter.toString()) + ); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new WebDriverException(e); } } } From b510eaa3c283aec16d7b303c90aa2685dcfe401c Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 00:38:29 +0400 Subject: [PATCH 334/501] build: bump Gradle from `8.5` to `8.7` (#2140) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43453 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 20 ++++++++++---------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 0b3860f17..2956300e8 100644 --- a/build.gradle +++ b/build.gradle @@ -188,7 +188,7 @@ signing { } wrapper { - gradleVersion = '8.5' + gradleVersion = '8.7' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch delta 34118 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 delta 34176 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 SGW6ptSs!X7{rG*o_g?|vpSEZK diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e6aba2515..e7646dead 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..7101f8e46 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From 48f0d4febdfe7dcb52a5ccfd0906b0f095bd3f7d Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 01:44:23 +0400 Subject: [PATCH 335/501] build: Bump Checkstyle from `10.12.1` to `10.14.2` (#2132) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2956300e8..15768b583 100644 --- a/build.gradle +++ b/build.gradle @@ -99,7 +99,7 @@ jacocoTestReport.dependsOn test apply plugin: 'checkstyle' checkstyle { - toolVersion = '10.12.1' + toolVersion = '10.14.2' configFile = configDirectory.file('appium-style.xml').get().getAsFile() showViolations = true ignoreFailures = false From 5f9ba620b4d05ca002a30f97a5bf3e82ff62df13 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 01:44:57 +0400 Subject: [PATCH 336/501] refactor: Remove usages of Guava's `@VisibleForTesting` (#2138) --- .../filters/AppiumUserAgentFilter.java | 4 +-- .../local/AppiumDriverLocalService.java | 4 +-- .../internal/AppiumUserAgentFilterTest.java | 26 +++++++------------ 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java index 50e9449e0..7c68cfad1 100644 --- a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java @@ -16,7 +16,6 @@ package io.appium.java_client.internal.filters; -import com.google.common.annotations.VisibleForTesting; import com.google.common.net.HttpHeaders; import io.appium.java_client.internal.Config; import org.openqa.selenium.remote.http.AddSeleniumUserAgent; @@ -55,8 +54,7 @@ private static String buildUserAgentHeaderValue(@Nonnull String previousUA) { * @return whether the given User Agent includes Appium UA * like by this filter. */ - @VisibleForTesting - public static boolean containsAppiumName(@Nullable String userAgent) { + private static boolean containsAppiumName(@Nullable String userAgent) { return userAgent != null && userAgent.toLowerCase().contains(USER_AGENT_PREFIX.toLowerCase()); } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 666f2ba06..8026300ad 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -16,7 +16,6 @@ package io.appium.java_client.service.local; -import com.google.common.annotations.VisibleForTesting; import lombok.Getter; import lombok.SneakyThrows; import org.openqa.selenium.os.ExternalProcess; @@ -403,8 +402,7 @@ public void addSlf4jLogMessageConsumer(BiConsumer userAgentParams() { - return Stream.of( - Arguments.of("selenium/4.5.0 (java mac)", false), - Arguments.of("appium/8.2.0 (selenium/4.5.0 (java mac))", true), - Arguments.of("APPIUM/8.2.0 (selenium/4.5.0 (java mac))", true), - Arguments.of("something (Appium/8.2.0 (selenium/4.5.0 (java mac)))", true), - Arguments.of("something (appium/8.2.0 (selenium/4.5.0 (java mac)))", true) - ); - } - @ParameterizedTest - @MethodSource("userAgentParams") - void validUserAgentIfContainsAppiumName(String userAgent, boolean expected) { - assertEquals(AppiumUserAgentFilter.containsAppiumName(userAgent), expected); + @ValueSource(strings = { + "appium/8.2.0 (selenium/4.5.0 (java mac))", + "APPIUM/8.2.0 (selenium/4.5.0 (java mac))", + "something (Appium/8.2.0 (selenium/4.5.0 (java mac)))", + "something (appium/8.2.0 (selenium/4.5.0 (java mac)))" + }) + void validUserAgentIfContainsAppiumName(String userAgent) { + assertEquals(AppiumUserAgentFilter.buildUserAgent(userAgent), userAgent); } @Test From f0aad8a5dc6c088b5981577cda8e2dc40b525340 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 12:10:41 +0400 Subject: [PATCH 337/501] release: v9.2.1 (#2143) --- CHANGELOG.md | 9 +++++++++ README.md | 2 +- gradle.properties | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62b862e69..d1f7f1714 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.2.1_ +- **[REFACTOR]** + - Replace private usages of Guava Collections API with Java Collections API [#2136](https://github.com/appium/java-client/pull/2136) + - Remove usages of Guava's `@VisibleForTesting` annotation [#2138](https://github.com/appium/java-client/pull/2138). Previously opened internal API marked with `@VisibleForTesting` annotation is private now: + - `io.appium.java_client.internal.filters.AppiumUserAgentFilter#containsAppiumName` + - `io.appium.java_client.service.local.AppiumDriverLocalService#parseSlf4jContextFromLogMessage` +- **[DEPENDENCY CHANGE]** + - Bump minimum supported Selenium version from `4.17.0` to `4.19.0` [#2142](https://github.com/appium/java-client/pull/2142) + _9.2.0_ - **[ENHANCEMENTS]** - Incorporate poll delay mechanism into `AppiumFluentWait` [#2116](https://github.com/appium/java-client/pull/2116) (Closes [#2111](https://github.com/appium/java-client/pull/2111)) diff --git a/README.md b/README.md index b0ee499da..11084ab61 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ---------------------------|----------------- - | `4.19.0` + `9.2.1` | `4.19.0` `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` N/A | `4.14.0` diff --git a/gradle.properties b/gradle.properties index 306b374dd..2e3f2130e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.19.0 # Please increment the value in a release -appiumClient.version=9.2.0 +appiumClient.version=9.2.1 From bc39a230f216a594b6f1b0e428a47db5eb68e225 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 20:15:23 +0400 Subject: [PATCH 338/501] fix: Fix building of Android geo location parameters (#2146) --- build.gradle | 1 + .../geolocation/AndroidGeoLocation.java | 10 ++-- .../geolocation/AndroidGeoLocationTest.java | 59 +++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/test/java/io/appium/java_client/android/geolocation/AndroidGeoLocationTest.java diff --git a/build.gradle b/build.gradle index 15768b583..4197aa34a 100644 --- a/build.gradle +++ b/build.gradle @@ -204,6 +204,7 @@ test { testLogging.showStandardStreams = true testLogging.exceptionFormat = 'full' filter { + includeTestsMatching 'io.appium.java_client.android.geolocation.*' includeTestsMatching 'io.appium.java_client.drivers.options.*' includeTestsMatching 'io.appium.java_client.events.*' includeTestsMatching 'io.appium.java_client.internal.*' diff --git a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java index f8e2d24c7..37d878642 100644 --- a/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java +++ b/src/main/java/io/appium/java_client/android/geolocation/AndroidGeoLocation.java @@ -111,10 +111,12 @@ public AndroidGeoLocation withSpeed(double speed) { */ public Map build() { var map = new HashMap(); - ofNullable(longitude).map(x -> map.put("longitude", x)).orElseThrow(() -> new IllegalArgumentException( - "A valid 'longitude' must be provided")); - ofNullable(latitude).map(x -> map.put("latitude", x)).orElseThrow(() -> new IllegalArgumentException( - "A valid 'latitude' must be provided")); + ofNullable(longitude).ifPresentOrElse(x -> map.put("longitude", x), () -> { + throw new IllegalArgumentException("A valid 'longitude' must be provided"); + }); + ofNullable(latitude).ifPresentOrElse(x -> map.put("latitude", x), () -> { + throw new IllegalArgumentException("A valid 'latitude' must be provided"); + }); ofNullable(altitude).ifPresent(x -> map.put("altitude", x)); ofNullable(satellites).ifPresent(x -> map.put("satellites", x)); ofNullable(speed).ifPresent(x -> map.put("speed", x)); diff --git a/src/test/java/io/appium/java_client/android/geolocation/AndroidGeoLocationTest.java b/src/test/java/io/appium/java_client/android/geolocation/AndroidGeoLocationTest.java new file mode 100644 index 000000000..47746c42a --- /dev/null +++ b/src/test/java/io/appium/java_client/android/geolocation/AndroidGeoLocationTest.java @@ -0,0 +1,59 @@ +package io.appium.java_client.android.geolocation; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AndroidGeoLocationTest { + + @Test + void shouldThrowExceptionWhenLatitudeIsNotSet() { + var androidGeoLocation = new AndroidGeoLocation().withLongitude(24.105078); + + var exception = assertThrows(IllegalArgumentException.class, androidGeoLocation::build); + + assertEquals("A valid 'latitude' must be provided", exception.getMessage()); + } + + @Test + void shouldThrowExceptionWhenLongitudeIsNotSet() { + var androidGeoLocation = new AndroidGeoLocation().withLatitude(56.946285); + + var exception = assertThrows(IllegalArgumentException.class, androidGeoLocation::build); + + assertEquals("A valid 'longitude' must be provided", exception.getMessage()); + } + + @Test + void shodBuildMinimalParameters() { + var androidGeoLocation = new AndroidGeoLocation() + .withLongitude(24.105078) + .withLatitude(56.946285); + + assertParameters(androidGeoLocation.build(), 24.105078, 56.946285, null, null, null); + } + + @Test + void shodBuildFullParameters() { + var androidGeoLocation = new AndroidGeoLocation() + .withLongitude(24.105078) + .withLatitude(56.946285) + .withAltitude(7) + .withSpeed(1.5) + .withSatellites(12); + + assertParameters(androidGeoLocation.build(), 24.105078, 56.946285, 7.0, 1.5, 12); + } + + private static void assertParameters(Map actualParams, double longitude, double latitude, + Double altitude, Double speed, Integer satellites) { + assertEquals(longitude, actualParams.get("longitude")); + assertEquals(latitude, actualParams.get("latitude")); + assertEquals(altitude, actualParams.get("altitude")); + assertEquals(speed, actualParams.get("speed")); + assertEquals(satellites, actualParams.get("satellites")); + } +} From 3dfe243c7de29b13191594d472f9686289f496d1 Mon Sep 17 00:00:00 2001 From: Artur Lomako Date: Thu, 28 Mar 2024 18:03:22 +0100 Subject: [PATCH 339/501] fix: Fix building of Android key event parameters (#2145) Co-authored-by: Valery Yatsynovich --- .../io/appium/java_client/android/nativekey/KeyEvent.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java b/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java index 3d695e4c3..984c34cbf 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java +++ b/src/main/java/io/appium/java_client/android/nativekey/KeyEvent.java @@ -83,8 +83,9 @@ public KeyEvent withFlag(KeyEventFlag keyEventFlag) { */ public Map build() { var map = new HashMap(); - ofNullable(this.keyCode).map(x -> map.put("keycode", x)).orElseThrow(() -> new IllegalStateException( - "The key code must be set")); + ofNullable(this.keyCode).ifPresentOrElse(x -> map.put("keycode", x), () -> { + throw new IllegalStateException("The key code must be set"); + }); ofNullable(this.metaState).ifPresent(x -> map.put("metastate", x)); ofNullable(this.flags).ifPresent(x -> map.put("flags", x)); return Collections.unmodifiableMap(map); From 51170c10bc3e1dede1ac033b0f9bc3a3f3497598 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 22:31:41 +0400 Subject: [PATCH 340/501] test: Add unit tests for Android `KeyEvent` (#2147) --- .../android/nativekey/KeyEventTest.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/test/java/io/appium/java_client/android/nativekey/KeyEventTest.java diff --git a/src/test/java/io/appium/java_client/android/nativekey/KeyEventTest.java b/src/test/java/io/appium/java_client/android/nativekey/KeyEventTest.java new file mode 100644 index 000000000..707da9bfa --- /dev/null +++ b/src/test/java/io/appium/java_client/android/nativekey/KeyEventTest.java @@ -0,0 +1,48 @@ +package io.appium.java_client.android.nativekey; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class KeyEventTest { + + @Test + void shouldThrowExceptionWhenKeyCodeIsNotSet() { + var keyEvent = new KeyEvent(); + + var exception = assertThrows(IllegalStateException.class, keyEvent::build); + + assertEquals("The key code must be set", exception.getMessage()); + } + + @Test + void shouldBuildMinimalParameters() { + var keyEvent = new KeyEvent().withKey(AndroidKey.A); + + Map params = keyEvent.build(); + + assertParameters(params, AndroidKey.A, null, null); + } + + @Test + void shouldBuildFullParameters() { + var keyEvent = new KeyEvent() + .withKey(AndroidKey.A) + .withMetaModifier(KeyEventMetaModifier.CAP_LOCKED) + .withFlag(KeyEventFlag.KEEP_TOUCH_MODE); + + Map params = keyEvent.build(); + + assertParameters(params, AndroidKey.A, KeyEventMetaModifier.CAP_LOCKED.getValue(), + KeyEventFlag.KEEP_TOUCH_MODE.getValue()); + } + + private static void assertParameters(Map params, AndroidKey key, Integer metastate, Integer flags) { + assertEquals(key.getCode(), params.get("keycode")); + assertEquals(metastate, params.get("metastate")); + assertEquals(flags, params.get("flags")); + } +} From a5ed8d3d6d8daadecfeeccb36e8b6e137abfe5b4 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 28 Mar 2024 23:43:27 +0400 Subject: [PATCH 341/501] release: v9.2.2 (#2148) --- CHANGELOG.md | 5 +++++ README.md | 20 ++++++++++---------- gradle.properties | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1f7f1714..92823038c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.2.2_ +- **[BUG FIX]** + - fix: Fix building of Android key event parameters [#2145](https://github.com/appium/java-client/pull/2145) + - fix: Fix building of Android geo location parameters [#2146](https://github.com/appium/java-client/pull/2146) + _9.2.1_ - **[REFACTOR]** - Replace private usages of Guava Collections API with Java Collections API [#2136](https://github.com/appium/java-client/pull/2136) diff --git a/README.md b/README.md index 11084ab61..189592d79 100644 --- a/README.md +++ b/README.md @@ -93,16 +93,16 @@ dependencies { ``` ### Compatibility Matrix - Appium Java Client | Selenium client ----------------------------|----------------- - `9.2.1` | `4.19.0` - `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` - `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` - N/A | `4.14.0` - `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` - `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` - `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` - `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` + Appium Java Client | Selenium client +----------------------------------------------------------------------------------|----------------- + `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2` | `4.19.0` + `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` + `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` + N/A | `4.14.0` + `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` + `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` + `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` + `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` #### Why is it so complicated? diff --git a/gradle.properties b/gradle.properties index 2e3f2130e..b67a7114b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.19.0 # Please increment the value in a release -appiumClient.version=9.2.1 +appiumClient.version=9.2.2 From bcf39238cad72a24b55aaafaec6003e5cd11910e Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 29 Mar 2024 19:44:34 +0400 Subject: [PATCH 342/501] refactor: Replace Guava `HttpHeaders` with Selenium `HttpHeader` (#2151) --- .../java_client/internal/filters/AppiumUserAgentFilter.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java index 7c68cfad1..d4f1842ce 100644 --- a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java @@ -16,11 +16,11 @@ package io.appium.java_client.internal.filters; -import com.google.common.net.HttpHeaders; import io.appium.java_client.internal.Config; import org.openqa.selenium.remote.http.AddSeleniumUserAgent; import org.openqa.selenium.remote.http.Filter; import org.openqa.selenium.remote.http.HttpHandler; +import org.openqa.selenium.remote.http.HttpHeader; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -81,7 +81,9 @@ public static String buildUserAgent(@Nullable String userAgent) { @Override public HttpHandler apply(HttpHandler next) { return req -> { - req.setHeader(HttpHeaders.USER_AGENT, buildUserAgent(req.getHeader(HttpHeaders.USER_AGENT))); + var originalUserAgentHeader = req.getHeader(HttpHeader.UserAgent.getName()); + var newUserAgentHeader = buildUserAgent(originalUserAgentHeader); + req.setHeader(HttpHeader.UserAgent.getName(), newUserAgentHeader); return next.execute(req); }; } From 1330a6bf485ec0f436f8add1c703c8bfdce513b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 22:51:40 +0300 Subject: [PATCH 343/501] build(deps): Bump org.owasp.dependencycheck from 9.0.10 to 9.1.0 (#2152) Bumps org.owasp.dependencycheck from 9.0.10 to 9.1.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4197aa34a..e3c633ce6 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.0.10' + id 'org.owasp.dependencycheck' version '9.1.0' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 284918d6fe18ddf13c48e5a833a702dc0dbb9576 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 4 Apr 2024 18:08:45 +0400 Subject: [PATCH 344/501] test: Re-group tests into Gradle suites (#2150) --- .github/workflows/gradle.yml | 4 +- build.gradle | 150 +++++++++++------- .../AndroidAbilityToUseSupplierTest.java | 0 .../android/AndroidAppStringsTest.java | 0 .../android/AndroidConnectionTest.java | 0 .../android/AndroidContextTest.java | 0 .../android/AndroidDataMatcherTest.java | 0 .../android/AndroidDriverTest.java | 0 .../android/AndroidElementTest.java | 0 .../android/AndroidFunctionTest.java | 0 .../android/AndroidLogcatListenerTest.java | 0 .../android/AndroidScreenRecordTest.java | 0 .../android/AndroidSearchingTest.java | 0 .../java_client/android/AndroidTouchTest.java | 0 .../android/AndroidViewMatcherTest.java | 0 .../java_client/android/BaseAndroidTest.java | 4 +- .../java_client/android/BaseEspressoTest.java | 4 +- .../java_client/android/BatteryTest.java | 0 .../java_client/android/ClipboardTest.java | 0 .../android/ExecuteCDPCommandTest.java | 0 .../android/ExecuteDriverScriptTest.java | 0 .../java_client/android/FingerPrintTest.java | 0 .../android/ImagesComparisonTest.java | 0 .../java_client/android/KeyCodeTest.java | 0 .../java_client/android/LogEventTest.java | 0 .../android/OpenNotificationsTest.java | 0 .../java_client/android/SettingTest.java | 0 .../java_client/android/TestResources.java | 12 ++ .../java_client/android/UIAutomator2Test.java | 0 .../AndroidPageObjectTest.java | 0 .../MobileBrowserCompatibilityTest.java | 0 .../service/local/ServerBuilderTest.java | 27 ++-- .../local/StartingAppLocallyAndroidTest.java | 10 +- .../service/local/ThreadSafetyTest.java | 0 .../resources}/ApiDemos-debug.apk | Bin .../resources}/main.js | 0 .../io/appium/java_client/ios/AppIOSTest.java | 10 +- .../appium/java_client/ios/BaseIOSTest.java | 0 .../java_client/ios/BaseIOSWebViewTest.java | 10 +- .../java_client/ios/BaseSafariTest.java | 0 .../appium/java_client/ios/ClipboardTest.java | 0 .../appium/java_client/ios/IOSAlertTest.java | 0 .../java_client/ios/IOSAppStringsTest.java | 0 .../java_client/ios/IOSContextTest.java | 0 .../appium/java_client/ios/IOSDriverTest.java | 0 .../java_client/ios/IOSElementTest.java | 0 .../ios/IOSNativeWebTapSettingTest.java | 0 .../java_client/ios/IOSScreenRecordTest.java | 0 .../java_client/ios/IOSSearchingTest.java | 0 .../ios/IOSSyslogListenerTest.java | 0 .../java_client/ios/IOSWebViewTest.java | 0 .../java_client/ios/ImagesComparisonTest.java | 0 .../appium/java_client/ios/RotationTest.java | 0 .../appium/java_client/ios/SettingTest.java | 0 .../pagefactory_tests/XCUITModeTest.java | 0 .../local/StartingAppLocallyIosTest.java | 12 +- .../resources}/TestApp.app.zip | Bin .../resources}/UICatalog.app.zip | Bin .../apps => e2eIosTest/resources}/vodqa.zip | Bin .../io/appium/java_client/TestResources.java | 34 ---- .../java/io/appium/java_client/TestUtils.java | 14 +- .../DesktopBrowserCompatibilityTest.java | 6 +- src/test/resources/apps/IntentExample.apk | Bin 50008 -> 0 bytes 63 files changed, 150 insertions(+), 147 deletions(-) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidAppStringsTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidConnectionTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidContextTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidDataMatcherTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidDriverTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidElementTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidFunctionTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidLogcatListenerTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidScreenRecordTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidSearchingTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidTouchTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/AndroidViewMatcherTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/BaseAndroidTest.java (94%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/BaseEspressoTest.java (93%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/BatteryTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/ClipboardTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/ExecuteCDPCommandTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/ExecuteDriverScriptTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/FingerPrintTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/ImagesComparisonTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/KeyCodeTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/LogEventTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/OpenNotificationsTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/SettingTest.java (100%) create mode 100644 src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java rename src/{test => e2eAndroidTest}/java/io/appium/java_client/android/UIAutomator2Test.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java (100%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/service/local/ServerBuilderTest.java (92%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java (92%) rename src/{test => e2eAndroidTest}/java/io/appium/java_client/service/local/ThreadSafetyTest.java (100%) rename src/{test/resources/apps => e2eAndroidTest/resources}/ApiDemos-debug.apk (100%) rename src/{test/java/io/appium/java_client/service/local => e2eAndroidTest/resources}/main.js (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/AppIOSTest.java (73%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/BaseIOSTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/BaseIOSWebViewTest.java (92%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/BaseSafariTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/ClipboardTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSAlertTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSAppStringsTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSContextTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSDriverTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSElementTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSScreenRecordTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSSearchingTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSSyslogListenerTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/IOSWebViewTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/ImagesComparisonTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/RotationTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/ios/SettingTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java (100%) rename src/{test => e2eIosTest}/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java (92%) rename src/{test/resources/apps => e2eIosTest/resources}/TestApp.app.zip (100%) rename src/{test/resources/apps => e2eIosTest/resources}/UICatalog.app.zip (100%) rename src/{test/resources/apps => e2eIosTest/resources}/vodqa.zip (100%) delete mode 100644 src/test/java/io/appium/java_client/TestResources.java delete mode 100644 src/test/resources/apps/IntentExample.apk diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c293b7b40..9a5972673 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -81,7 +81,7 @@ jobs: if: matrix.e2e-tests == 'android' uses: reactivecircus/android-emulator-runner@v2 with: - script: ./gradlew uiAutomationTest -PisCI -Pselenium.version=$latest_snapshot + script: ./gradlew e2eAndroidTest -PisCI -Pselenium.version=$latest_snapshot api-level: ${{ env.ANDROID_SDK_VERSION }} avd-name: ${{ env.ANDROID_EMU_NAME }} sdcard-path-or-size: 1500M @@ -108,4 +108,4 @@ jobs: xcrun simctl bootstatus $target_sim_id -b - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' - run: ./gradlew xcuiTest -PisCI -Pselenium.version=$latest_snapshot + run: ./gradlew e2eIosTest -PisCI -Pselenium.version=$latest_snapshot diff --git a/build.gradle b/build.gradle index e3c633ce6..da8dd2da3 100644 --- a/build.gradle +++ b/build.gradle @@ -67,15 +67,6 @@ dependencies { } implementation 'com.google.code.gson:gson:2.10.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" - - testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - testImplementation 'org.hamcrest:hamcrest:2.2' - testImplementation (group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '5.7.0') { - exclude group: 'org.seleniumhq.selenium' - } - testImplementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - testRuntimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" } dependencyCheck { @@ -199,51 +190,104 @@ processResources { ] } -test { - useJUnitPlatform() - testLogging.showStandardStreams = true - testLogging.exceptionFormat = 'full' - filter { - includeTestsMatching 'io.appium.java_client.android.geolocation.*' - includeTestsMatching 'io.appium.java_client.drivers.options.*' - includeTestsMatching 'io.appium.java_client.events.*' - includeTestsMatching 'io.appium.java_client.internal.*' - includeTestsMatching 'io.appium.java_client.pagefactory_tests.DesktopBrowserCompatibilityTest' - includeTestsMatching 'io.appium.java_client.pagefactory_tests.TimeoutTest' - includeTestsMatching 'io.appium.java_client.proxy.*' - includeTestsMatching 'io.appium.java_client.remote.*' - includeTestsMatching 'io.appium.java_client.touch.*' - } - finalizedBy jacocoTestReport -} +testing { + suites { + configureEach { + useJUnitJupiter() + dependencies { + implementation 'org.junit.jupiter:junit-jupiter:5.10.2' + runtimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.hamcrest:hamcrest:2.2' + runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" + } + targets.configureEach { + testTask.configure { + testLogging { + showStandardStreams = true + exceptionFormat = 'full' + } + } + } + } -tasks.register('xcuiTest', Test) { - useJUnitPlatform() - testLogging.showStandardStreams = true - testLogging.exceptionFormat = 'full' - filter { - includeTestsMatching 'io.appium.java_client.ios.*' - includeTestsMatching '*.pagefactory_tests.XCUITModeTest' - includeTestsMatching '*.pagefactory_tests.widget.tests.combined.*' - includeTestsMatching '*.pagefactory_tests.widget.tests.ios.*' - includeTestsMatching 'io.appium.java_client.service.local.StartingAppLocallyIosTest' - exclude '**/IOSScreenRecordTest.class' - exclude '**/ImagesComparisonTest.class' - } -} + test { + dependencies { + implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" + implementation('io.github.bonigarcia:webdrivermanager:5.7.0') { + exclude group: 'org.seleniumhq.selenium' + } + } + targets.configureEach { + testTask.configure { + finalizedBy jacocoTestReport + } + } + } + + e2eIosTest(JvmTestSuite) { + sources { + java { + srcDirs = ['src/e2eIosTest/java'] + } + } + dependencies { + implementation project() + implementation(sourceSets.test.output) + implementation('org.apache.commons:commons-lang3:3.14.0') + } -tasks.register('uiAutomationTest', Test) { - useJUnitPlatform() - testLogging.showStandardStreams = true - testLogging.exceptionFormat = 'full' - filter { - includeTestsMatching 'io.appium.java_client.android.SettingTest' - includeTestsMatching 'io.appium.java_client.android.ClipboardTest' - includeTestsMatching 'io.appium.java_client.android.OpenNotificationsTest' - includeTestsMatching '*.AndroidAppStringsTest' - includeTestsMatching '*.pagefactory_tests.widget.tests.android.*' - includeTestsMatching 'io.appium.java_client.service.local.StartingAppLocallyAndroidTest' - includeTestsMatching 'io.appium.java_client.service.local.ServerBuilderTest' - includeTestsMatching 'io.appium.java_client.service.local.ThreadSafetyTest' + targets.configureEach { + testTask.configure { + shouldRunAfter(test) + filter { + exclude '**/IOSScreenRecordTest.class' + exclude '**/ImagesComparisonTest.class' + } + } + } + } + + e2eAndroidTest(JvmTestSuite) { + sources { + java { + srcDirs = ['src/e2eAndroidTest/java'] + } + } + dependencies { + implementation project() + implementation(sourceSets.test.output) + implementation('io.github.bonigarcia:webdrivermanager:5.7.0') { + exclude group: 'org.seleniumhq.selenium' + } + } + + targets.configureEach { + testTask.configure { + shouldRunAfter(test) + filter { + // The following tests fail and should be reviewed/fixed + exclude '**/AndroidAbilityToUseSupplierTest.class' + exclude '**/AndroidConnectionTest.class' + exclude '**/AndroidContextTest.class' + exclude '**/AndroidDataMatcherTest.class' + exclude '**/AndroidDriverTest.class' + exclude '**/AndroidElementTest.class' + exclude '**/AndroidFunctionTest.class' + exclude '**/AndroidSearchingTest.class' + exclude '**/AndroidTouchTest.class' + exclude '**/AndroidViewMatcherTest.class' + exclude '**/ExecuteCDPCommandTest.class' + exclude '**/ExecuteDriverScriptTest.class' + exclude '**/FingerPrintTest.class' + exclude '**/ImagesComparisonTest.class' + exclude '**/KeyCodeTest.class' + exclude '**/LogEventTest.class' + exclude '**/UIAutomator2Test.class' + exclude '**/AndroidPageObjectTest.class' + exclude '**/MobileBrowserCompatibilityTest.class' + } + } + } + } } } diff --git a/src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAppStringsTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidAppStringsTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAppStringsTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidConnectionTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidConnectionTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidConnectionTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidConnectionTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidContextTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidContextTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidContextTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidContextTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidDataMatcherTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidDataMatcherTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidDataMatcherTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidDriverTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidDriverTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidDriverTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidDriverTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidElementTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidElementTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidElementTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidElementTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidFunctionTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidFunctionTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidFunctionTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidLogcatListenerTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidLogcatListenerTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidLogcatListenerTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidScreenRecordTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidScreenRecordTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidScreenRecordTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidSearchingTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidSearchingTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidSearchingTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidSearchingTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidTouchTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidTouchTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidTouchTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidTouchTest.java diff --git a/src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidViewMatcherTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/AndroidViewMatcherTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/AndroidViewMatcherTest.java diff --git a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java similarity index 94% rename from src/test/java/io/appium/java_client/android/BaseAndroidTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java index e14343d75..347304cf5 100644 --- a/src/test/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java @@ -24,8 +24,6 @@ import java.util.Map; -import static io.appium.java_client.TestResources.apiDemosApk; - @SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class BaseAndroidTest { public static final String APP_ID = "io.appium.android.apis"; @@ -46,7 +44,7 @@ public class BaseAndroidTest { UiAutomator2Options options = new UiAutomator2Options() .setDeviceName("Android Emulator") - .setApp(apiDemosApk().toAbsolutePath().toString()) + .setApp(TestResources.API_DEMOS_APK.toString()) .eventTimings(); driver = new AndroidDriver(service.getUrl(), options); } diff --git a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/BaseEspressoTest.java similarity index 93% rename from src/test/java/io/appium/java_client/android/BaseEspressoTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/BaseEspressoTest.java index d312587bd..f26469cb8 100644 --- a/src/test/java/io/appium/java_client/android/BaseEspressoTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/BaseEspressoTest.java @@ -22,8 +22,6 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import static io.appium.java_client.TestResources.apiDemosApk; - @SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class BaseEspressoTest { @@ -44,7 +42,7 @@ public class BaseEspressoTest { EspressoOptions options = new EspressoOptions() .setDeviceName("Android Emulator") - .setApp(apiDemosApk().toAbsolutePath().toString()) + .setApp(TestResources.API_DEMOS_APK.toString()) .eventTimings(); driver = new AndroidDriver(service.getUrl(), options); } diff --git a/src/test/java/io/appium/java_client/android/BatteryTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/BatteryTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/BatteryTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/BatteryTest.java diff --git a/src/test/java/io/appium/java_client/android/ClipboardTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/ClipboardTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/ClipboardTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/ClipboardTest.java diff --git a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/ExecuteCDPCommandTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/ExecuteCDPCommandTest.java diff --git a/src/test/java/io/appium/java_client/android/ExecuteDriverScriptTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/ExecuteDriverScriptTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/ExecuteDriverScriptTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/ExecuteDriverScriptTest.java diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/FingerPrintTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/FingerPrintTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/FingerPrintTest.java diff --git a/src/test/java/io/appium/java_client/android/ImagesComparisonTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/ImagesComparisonTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/ImagesComparisonTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/ImagesComparisonTest.java diff --git a/src/test/java/io/appium/java_client/android/KeyCodeTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/KeyCodeTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/KeyCodeTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/KeyCodeTest.java diff --git a/src/test/java/io/appium/java_client/android/LogEventTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/LogEventTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/LogEventTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/LogEventTest.java diff --git a/src/test/java/io/appium/java_client/android/OpenNotificationsTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/OpenNotificationsTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/OpenNotificationsTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/OpenNotificationsTest.java diff --git a/src/test/java/io/appium/java_client/android/SettingTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/SettingTest.java similarity index 100% rename from src/test/java/io/appium/java_client/android/SettingTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/SettingTest.java diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java b/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java new file mode 100644 index 000000000..149a72a4a --- /dev/null +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java @@ -0,0 +1,12 @@ +package io.appium.java_client.android; + +import io.appium.java_client.TestUtils; + +import java.nio.file.Path; + +public class TestResources { + public static final Path API_DEMOS_APK = TestUtils.resourcePathToAbsolutePath("ApiDemos-debug.apk"); + + private TestResources() { + } +} diff --git a/src/test/java/io/appium/java_client/android/UIAutomator2Test.java b/src/e2eAndroidTest/java/io/appium/java_client/android/UIAutomator2Test.java similarity index 100% rename from src/test/java/io/appium/java_client/android/UIAutomator2Test.java rename to src/e2eAndroidTest/java/io/appium/java_client/android/UIAutomator2Test.java diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/e2eAndroidTest/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java similarity index 100% rename from src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/e2eAndroidTest/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java similarity index 100% rename from src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java diff --git a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java similarity index 92% rename from src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java index 9822e9417..d482284b2 100644 --- a/src/test/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -1,5 +1,7 @@ package io.appium.java_client.service.local; +import io.appium.java_client.TestUtils; +import io.appium.java_client.android.TestResources; import io.appium.java_client.android.options.UiAutomator2Options; import io.github.bonigarcia.wdm.WebDriverManager; import org.junit.jupiter.api.AfterEach; @@ -15,7 +17,6 @@ import java.util.List; import java.util.Map; -import static io.appium.java_client.TestResources.apiDemosApk; import static io.appium.java_client.TestUtils.getLocalIp4Address; import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; import static io.appium.java_client.service.local.AppiumServiceBuilder.APPIUM_PATH; @@ -27,7 +28,6 @@ import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static java.lang.System.getProperty; import static java.lang.System.setProperty; -import static java.nio.file.FileSystems.getDefault; import static java.util.Arrays.asList; import static java.util.Optional.ofNullable; import static java.util.concurrent.TimeUnit.SECONDS; @@ -49,14 +49,10 @@ class ServerBuilderTest { */ private static final String PATH_TO_APPIUM_NODE_IN_PROPERTIES = getProperty(APPIUM_PATH); - private static final Path ROOT_TEST_PATH = getDefault().getPath("src") - .resolve("test").resolve("java").resolve("io").resolve("appium").resolve("java_client"); - /** * This is the path to the stub main.js file */ - private static final Path PATH_T0_TEST_MAIN_JS = ROOT_TEST_PATH - .resolve("service").resolve("local").resolve("main.js"); + private static final Path PATH_T0_TEST_MAIN_JS = TestUtils.resourcePathToAbsolutePath("main.js"); private static String testIP; private AppiumDriverLocalService service; @@ -111,18 +107,14 @@ void checkAbilityToStartDefaultService() { @Test void checkAbilityToFindNodeDefinedInProperties() { - File definedNode = PATH_T0_TEST_MAIN_JS.toFile(); - setProperty(APPIUM_PATH, definedNode.getAbsolutePath()); - assertThat(new AppiumServiceBuilder().createArgs().get(0), is(definedNode.getAbsolutePath())); + setProperty(APPIUM_PATH, PATH_T0_TEST_MAIN_JS.toString()); + assertThat(new AppiumServiceBuilder().createArgs().get(0), is(PATH_T0_TEST_MAIN_JS.toString())); } @Test void checkAbilityToUseNodeDefinedExplicitly() { - File mainJS = PATH_T0_TEST_MAIN_JS.toFile(); - AppiumServiceBuilder builder = new AppiumServiceBuilder() - .withAppiumJS(mainJS); - assertThat(builder.createArgs().get(0), - is(mainJS.getAbsolutePath())); + AppiumServiceBuilder builder = new AppiumServiceBuilder().withAppiumJS(PATH_T0_TEST_MAIN_JS.toFile()); + assertThat(builder.createArgs().get(0), is(PATH_T0_TEST_MAIN_JS.toString())); } @Test @@ -156,7 +148,7 @@ void checkAbilityToStartServiceUsingCapabilities() { .setNewCommandTimeout(Duration.ofSeconds(60)) .setAppPackage("io.appium.android.apis") .setAppActivity(".view.WebView1") - .setApp(apiDemosApk().toAbsolutePath().toString()) + .setApp(TestResources.API_DEMOS_APK.toString()) .setChromedriverExecutable(chromeManager.getDownloadedDriverPath()); service = new AppiumServiceBuilder().withCapabilities(options).build(); @@ -166,14 +158,13 @@ void checkAbilityToStartServiceUsingCapabilities() { @Test void checkAbilityToStartServiceUsingCapabilitiesAndFlags() { - File app = ROOT_TEST_PATH.resolve("ApiDemos-debug.apk").toFile(); UiAutomator2Options options = new UiAutomator2Options() .fullReset() .setNewCommandTimeout(Duration.ofSeconds(60)) .setAppPackage("io.appium.android.apis") .setAppActivity(".view.WebView1") - .setApp(app.getAbsolutePath()) + .setApp(TestResources.API_DEMOS_APK.toString()) .setChromedriverExecutable(chromeManager.getDownloadedDriverPath()) .amend("winPath", "C:\\selenium\\app.apk") .amend("unixPath", "/selenium/app.apk") diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java b/src/e2eAndroidTest/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java similarity index 92% rename from src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java index 157077f88..77a7cc585 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/service/local/StartingAppLocallyAndroidTest.java @@ -17,6 +17,7 @@ package io.appium.java_client.service.local; import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.TestResources; import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; @@ -27,7 +28,6 @@ import java.time.Duration; -import static io.appium.java_client.TestResources.apiDemosApk; import static io.appium.java_client.remote.options.SupportsAppOption.APP_OPTION; import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; import static io.appium.java_client.remote.options.SupportsDeviceNameOption.DEVICE_NAME_OPTION; @@ -44,7 +44,7 @@ void startingAndroidAppWithCapabilitiesOnlyTest() { AndroidDriver driver = new AndroidDriver(new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() - .setApp(apiDemosApk().toAbsolutePath().toString())); + .setApp(TestResources.API_DEMOS_APK.toString())); try { Capabilities caps = driver.getCapabilities(); @@ -53,7 +53,7 @@ void startingAndroidAppWithCapabilitiesOnlyTest() { ); assertEquals(AutomationName.ANDROID_UIAUTOMATOR2, caps.getCapability(AUTOMATION_NAME_OPTION)); assertNotNull(caps.getCapability(DEVICE_NAME_OPTION)); - assertEquals(apiDemosApk().toAbsolutePath().toString(), caps.getCapability(APP_OPTION)); + assertEquals(TestResources.API_DEMOS_APK.toString(), caps.getCapability(APP_OPTION)); } finally { driver.quit(); } @@ -68,7 +68,7 @@ void startingAndroidAppWithCapabilitiesAndServiceTest() { AndroidDriver driver = new AndroidDriver(builder, new UiAutomator2Options() .setDeviceName("Android Emulator") .autoGrantPermissions() - .setApp(apiDemosApk().toAbsolutePath().toString())); + .setApp(TestResources.API_DEMOS_APK.toString())); try { Capabilities caps = driver.getCapabilities(); @@ -88,7 +88,7 @@ void startingAndroidAppWithCapabilitiesAndFlagsOnServerSideTest() { .fullReset() .autoGrantPermissions() .setNewCommandTimeout(Duration.ofSeconds(60)) - .setApp(apiDemosApk().toAbsolutePath().toString()); + .setApp(TestResources.API_DEMOS_APK.toString()); WebDriverManager chromeManager = chromedriver(); chromeManager.setup(); diff --git a/src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ThreadSafetyTest.java similarity index 100% rename from src/test/java/io/appium/java_client/service/local/ThreadSafetyTest.java rename to src/e2eAndroidTest/java/io/appium/java_client/service/local/ThreadSafetyTest.java diff --git a/src/test/resources/apps/ApiDemos-debug.apk b/src/e2eAndroidTest/resources/ApiDemos-debug.apk similarity index 100% rename from src/test/resources/apps/ApiDemos-debug.apk rename to src/e2eAndroidTest/resources/ApiDemos-debug.apk diff --git a/src/test/java/io/appium/java_client/service/local/main.js b/src/e2eAndroidTest/resources/main.js similarity index 100% rename from src/test/java/io/appium/java_client/service/local/main.js rename to src/e2eAndroidTest/resources/main.js diff --git a/src/test/java/io/appium/java_client/ios/AppIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java similarity index 73% rename from src/test/java/io/appium/java_client/ios/AppIOSTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java index b049a15bb..25574d727 100644 --- a/src/test/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java @@ -1,26 +1,26 @@ package io.appium.java_client.ios; +import io.appium.java_client.TestUtils; import io.appium.java_client.ios.options.XCUITestOptions; import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.SessionNotCreatedException; import java.time.Duration; -import static io.appium.java_client.TestResources.testAppZip; - public class AppIOSTest extends BaseIOSTest { + protected static final String BUNDLE_ID = "io.appium.TestApp"; - public static final String BUNDLE_ID = "io.appium.TestApp"; + private static final String TEST_APP_ZIP = TestUtils.resourcePathToAbsolutePath("TestApp.app.zip").toString(); @BeforeAll - public static void beforeClass() throws Exception { + public static void beforeClass() { startAppiumServer(); XCUITestOptions options = new XCUITestOptions() .setPlatformVersion(PLATFORM_VERSION) .setDeviceName(DEVICE_NAME) .setCommandTimeouts(Duration.ofSeconds(240)) - .setApp(testAppZip().toAbsolutePath().toString()) + .setApp(TEST_APP_ZIP) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); try { driver = new IOSDriver(service.getUrl(), options); diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/BaseIOSTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java diff --git a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java similarity index 92% rename from src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index c461ded8a..f975d3c5b 100644 --- a/src/test/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -16,29 +16,29 @@ package io.appium.java_client.ios; +import io.appium.java_client.TestUtils; import io.appium.java_client.ios.options.XCUITestOptions; import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.SessionNotCreatedException; -import java.io.IOException; import java.time.Duration; import java.util.function.Supplier; -import static io.appium.java_client.TestResources.vodQaAppZip; - public class BaseIOSWebViewTest extends BaseIOSTest { + private static final String VODQA_ZIP = TestUtils.resourcePathToAbsolutePath("vodqa.zip").toString(); + private static final Duration WEB_VIEW_DETECT_INTERVAL = Duration.ofSeconds(1); private static final Duration WEB_VIEW_DETECT_DURATION = Duration.ofSeconds(15); @BeforeAll - public static void beforeClass() throws IOException { + public static void beforeClass() { startAppiumServer(); XCUITestOptions options = new XCUITestOptions() .setDeviceName(DEVICE_NAME) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) .setCommandTimeouts(Duration.ofSeconds(240)) - .setApp(vodQaAppZip().toAbsolutePath().toString()); + .setApp(VODQA_ZIP); Supplier createDriver = () -> new IOSDriver(service.getUrl(), options); try { driver = createDriver.get(); diff --git a/src/test/java/io/appium/java_client/ios/BaseSafariTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/BaseSafariTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java diff --git a/src/test/java/io/appium/java_client/ios/ClipboardTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/ClipboardTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/ClipboardTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/ClipboardTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSAlertTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSAlertTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSAlertTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSAlertTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSAppStringsTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSAppStringsTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSAppStringsTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSContextTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSContextTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSDriverTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSDriverTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSElementTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSElementTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSElementTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSElementTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSScreenRecordTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSScreenRecordTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSScreenRecordTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSSearchingTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSSearchingTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSSearchingTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSSearchingTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSSyslogListenerTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSSyslogListenerTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSSyslogListenerTest.java diff --git a/src/test/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/IOSWebViewTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java diff --git a/src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/ImagesComparisonTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/ImagesComparisonTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/ImagesComparisonTest.java diff --git a/src/test/java/io/appium/java_client/ios/RotationTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/RotationTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/RotationTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/RotationTest.java diff --git a/src/test/java/io/appium/java_client/ios/SettingTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/SettingTest.java similarity index 100% rename from src/test/java/io/appium/java_client/ios/SettingTest.java rename to src/e2eIosTest/java/io/appium/java_client/ios/SettingTest.java diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java b/src/e2eIosTest/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java similarity index 100% rename from src/test/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java rename to src/e2eIosTest/java/io/appium/java_client/pagefactory_tests/XCUITModeTest.java diff --git a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java similarity index 92% rename from src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java rename to src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index 5041231ec..b262e93af 100644 --- a/src/test/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.service.local; +import io.appium.java_client.TestUtils; import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.options.XCUITestOptions; @@ -26,7 +27,6 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; -import static io.appium.java_client.TestResources.uiCatalogAppZip; import static io.appium.java_client.remote.options.SupportsDeviceNameOption.DEVICE_NAME_OPTION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -35,12 +35,14 @@ import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; class StartingAppLocallyIosTest { + private static final String UI_CATALOG_ZIP = TestUtils.resourcePathToAbsolutePath("UICatalog.app.zip").toString(); + @Test void startingIOSAppWithCapabilitiesOnlyTest() { XCUITestOptions options = new XCUITestOptions() .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) .setDeviceName(BaseIOSTest.DEVICE_NAME) - .setApp(uiCatalogAppZip().toAbsolutePath().toString()) + .setApp(UI_CATALOG_ZIP) .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); IOSDriver driver = new IOSDriver(options); try { @@ -50,7 +52,7 @@ void startingIOSAppWithCapabilitiesOnlyTest() { assertEquals(Platform.IOS, caps.getPlatformName()); assertNotNull(caps.getDeviceName().orElse(null)); assertEquals(BaseIOSTest.PLATFORM_VERSION, caps.getPlatformVersion().orElse(null)); - assertEquals(uiCatalogAppZip().toAbsolutePath().toString(), caps.getApp().orElse(null)); + assertEquals(UI_CATALOG_ZIP, caps.getApp().orElse(null)); } finally { driver.quit(); } @@ -62,7 +64,7 @@ void startingIOSAppWithCapabilitiesAndServiceTest() { XCUITestOptions options = new XCUITestOptions() .setPlatformVersion(BaseIOSTest.PLATFORM_VERSION) .setDeviceName(BaseIOSTest.DEVICE_NAME) - .setApp(uiCatalogAppZip().toAbsolutePath().toString()) + .setApp(UI_CATALOG_ZIP) .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); AppiumServiceBuilder builder = new AppiumServiceBuilder() @@ -89,7 +91,7 @@ void startingIOSAppWithCapabilitiesAndFlagsOnServerSideTest() { .setWdaLaunchTimeout(BaseIOSTest.WDA_LAUNCH_TIMEOUT); XCUITestOptions clientOptions = new XCUITestOptions() - .setApp(uiCatalogAppZip().toAbsolutePath().toString()); + .setApp(UI_CATALOG_ZIP); AppiumServiceBuilder builder = new AppiumServiceBuilder() .withArgument(GeneralServerFlag.SESSION_OVERRIDE) diff --git a/src/test/resources/apps/TestApp.app.zip b/src/e2eIosTest/resources/TestApp.app.zip similarity index 100% rename from src/test/resources/apps/TestApp.app.zip rename to src/e2eIosTest/resources/TestApp.app.zip diff --git a/src/test/resources/apps/UICatalog.app.zip b/src/e2eIosTest/resources/UICatalog.app.zip similarity index 100% rename from src/test/resources/apps/UICatalog.app.zip rename to src/e2eIosTest/resources/UICatalog.app.zip diff --git a/src/test/resources/apps/vodqa.zip b/src/e2eIosTest/resources/vodqa.zip similarity index 100% rename from src/test/resources/apps/vodqa.zip rename to src/e2eIosTest/resources/vodqa.zip diff --git a/src/test/java/io/appium/java_client/TestResources.java b/src/test/java/io/appium/java_client/TestResources.java deleted file mode 100644 index 6928cdcaf..000000000 --- a/src/test/java/io/appium/java_client/TestResources.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.appium.java_client; - -import java.nio.file.Path; - -import static io.appium.java_client.TestUtils.resourcePathToLocalPath; - -public class TestResources { - private TestResources() { - } - - public static Path apiDemosApk() { - return resourcePathToLocalPath("apps/ApiDemos-debug.apk"); - } - - public static Path testAppZip() { - return resourcePathToLocalPath("apps/TestApp.app.zip"); - } - - public static Path uiCatalogAppZip() { - return resourcePathToLocalPath("apps/UICatalog.app.zip"); - } - - public static Path vodQaAppZip() { - return resourcePathToLocalPath("apps/vodqa.zip"); - } - - public static Path intentExampleApk() { - return resourcePathToLocalPath("apps/IntentExample.apk"); - } - - public static Path helloAppiumHtml() { - return resourcePathToLocalPath("html/hello appium - saved page.htm"); - } -} diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index aaf254f75..1d650777c 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -6,14 +6,12 @@ import org.openqa.selenium.WebElement; import javax.annotation.Nullable; -import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.URISyntaxException; import java.net.URL; import java.net.UnknownHostException; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; @@ -31,26 +29,18 @@ public static String getLocalIp4Address() throws SocketException, UnknownHostExc } } - public static Path resourcePathToLocalPath(String resourcePath) { + public static Path resourcePathToAbsolutePath(String resourcePath) { URL url = ClassLoader.getSystemResource(resourcePath); if (url == null) { throw new IllegalArgumentException(String.format("Cannot find the '%s' resource", resourcePath)); } try { - return Paths.get(url.toURI()); + return Paths.get(url.toURI()).toAbsolutePath(); } catch (URISyntaxException e) { throw new IllegalArgumentException(e); } } - public static String resourceAsString(String resourcePath) { - try { - return new String(Files.readAllBytes(resourcePathToLocalPath(resourcePath))); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - public static void waitUntilTrue(Supplier func, Duration timeout, Duration interval) { long started = System.currentTimeMillis(); RuntimeException lastError = null; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index 0a890dc67..40c672ae7 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.pagefactory_tests; +import io.appium.java_client.TestUtils; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; @@ -33,7 +34,6 @@ import java.util.List; -import static io.appium.java_client.TestResources.helloAppiumHtml; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static java.time.Duration.ofSeconds; @@ -41,6 +41,8 @@ import static org.junit.jupiter.api.Assertions.assertNull; public class DesktopBrowserCompatibilityTest { + private static final String HELLO_APPIUM_HTML = + TestUtils.resourcePathToAbsolutePath("html/hello appium - saved page.htm").toUri().toString(); @HowToUseLocators(iOSXCUITAutomation = ALL_POSSIBLE) @AndroidFindBy(className = "someClass") @@ -62,7 +64,7 @@ public class DesktopBrowserCompatibilityTest { WebDriver driver = new ChromeDriver(new ChromeOptions().addArguments("--headless=new")); try { PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(15)), this); - driver.get(helloAppiumHtml().toUri().toString()); + driver.get(HELLO_APPIUM_HTML); assertNotEquals(0, foundLinks.size()); assertNotEquals(0, main.size()); assertNull(trap1); diff --git a/src/test/resources/apps/IntentExample.apk b/src/test/resources/apps/IntentExample.apk deleted file mode 100644 index 196ea90940af607535d0cf5c57e0c22c1d3e4af2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50008 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Ž)U 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 C0*Da+ From cfb815694fefc2d5d3a3fbfcae2de16402dd7ad6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:50:16 +0300 Subject: [PATCH 345/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2155) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.7.0 to 5.8.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.7.0...webdrivermanager-5.8.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index da8dd2da3..9a981364b 100644 --- a/build.gradle +++ b/build.gradle @@ -213,7 +213,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:5.7.0') { + implementation('io.github.bonigarcia:webdrivermanager:5.8.0') { exclude group: 'org.seleniumhq.selenium' } } @@ -256,7 +256,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:5.7.0') { + implementation('io.github.bonigarcia:webdrivermanager:5.8.0') { exclude group: 'org.seleniumhq.selenium' } } From 989153fd4a985b5472174376a8911a57fa2df184 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:26:31 +0300 Subject: [PATCH 346/501] build(deps): Bump gradle/wrapper-validation-action from 2 to 3 (#2159) Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 2 to 3. - [Release notes](https://github.com/gradle/wrapper-validation-action/releases) - [Commits](https://github.com/gradle/wrapper-validation-action/compare/v2...v3) --- updated-dependencies: - dependency-name: gradle/wrapper-validation-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 531000b79..e3df8193e 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -24,4 +24,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v2 + - uses: gradle/wrapper-validation-action@v3 From fc03b6cb9e3e79dc0e0bf41fc6e271080586b436 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:51:12 +0300 Subject: [PATCH 347/501] build(deps): Bump slf4jVersion from 2.0.12 to 2.0.13 (#2158) Bumps `slf4jVersion` from 2.0.12 to 2.0.13. Updates `org.slf4j:slf4j-api` from 2.0.12 to 2.0.13 Updates `org.slf4j:slf4j-simple` from 2.0.12 to 2.0.13 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9a981364b..719b1921e 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.12' + slf4jVersion = '2.0.13' } dependencies { From 57e431c3c1fc3f77f41e6973be02eac833f30404 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 16 Apr 2024 08:17:48 +0300 Subject: [PATCH 348/501] ci: Use non-deprecated GH action for Gradle wrapper validation (#2160) https://github.com/gradle/wrapper-validation-action/releases/tag/v3.3.0: As of v3 this action has been deprecated by gradle/actions/wrapper-validation. Any workflow that uses gradle/wrapper-validation-action@v3 will transparently delegate to gradle/actions/wrapper-validation@v3. --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index e3df8193e..72a15d717 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -24,4 +24,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v3 + - uses: gradle/actions/wrapper-validation@v3 From 496417f296df2176132cd6a5c6178ba278249b10 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 5 May 2024 07:28:21 +0200 Subject: [PATCH 349/501] ci: Update the flow for Android e2e tests (#2166) --- .github/workflows/gradle.yml | 11 +++++++++-- .../io/appium/java_client/ios/BaseSafariTest.java | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9a5972673..c83581927 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -37,7 +37,7 @@ jobs: platform: macos-12 e2e-tests: ios - java: 17 - platform: macos-latest + platform: ubuntu-latest e2e-tests: android - java: 21 platform: ubuntu-latest @@ -49,6 +49,13 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Enable KVM group perms + if: matrix.e2e-tests == 'android' + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v4 with: @@ -84,8 +91,8 @@ jobs: script: ./gradlew e2eAndroidTest -PisCI -Pselenium.version=$latest_snapshot api-level: ${{ env.ANDROID_SDK_VERSION }} avd-name: ${{ env.ANDROID_EMU_NAME }} - sdcard-path-or-size: 1500M disable-spellchecker: true + disable-animations: true target: ${{ env.ANDROID_EMU_TARGET }} - name: Select Xcode diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java index 654c4e58b..d35c76357 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java @@ -21,8 +21,10 @@ import org.junit.jupiter.api.BeforeAll; import java.io.IOException; +import java.time.Duration; public class BaseSafariTest extends BaseIOSTest { + private static final Duration WEBVIEW_CONNECT_TIMEOUT = Duration.ofSeconds(30); @BeforeAll public static void beforeClass() throws IOException { startAppiumServer(); @@ -31,6 +33,7 @@ public class BaseSafariTest extends BaseIOSTest { .withBrowserName(MobileBrowserType.SAFARI) .setDeviceName(DEVICE_NAME) .setPlatformVersion(PLATFORM_VERSION) + .setWebviewConnectTimeout(WEBVIEW_CONNECT_TIMEOUT) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); driver = new IOSDriver(service.getUrl(), options); } From 6f83f1d223f306c6bd6b14b2ac20a286e446ac00 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 9 May 2024 09:35:30 +0200 Subject: [PATCH 350/501] ci: Bump conventional-pr-action to v3 --- .github/workflows/pr-title.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index f3387333b..393ca3bd6 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -8,8 +8,8 @@ jobs: name: https://www.conventionalcommits.org runs-on: ubuntu-latest steps: - - uses: beemojs/conventional-pr-action@v2 + - uses: beemojs/conventional-pr-action@v3 with: - config-preset: angular + config-preset: angular env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 3efeaebc8964423a8a1619305f343d2ec7128149 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 15 May 2024 07:26:22 +0200 Subject: [PATCH 351/501] fix: Properly represent FeaturesMatchingResult model if `multiple` option is enabled (#2170) --- .../io/appium/java_client/ComparesImages.java | 3 +- .../imagecomparison/ComparisonResult.java | 17 +- .../FeaturesMatchingResult.java | 12 +- .../OccurrenceMatchingResult.java | 150 ++++++++++++++++-- .../SimilarityMatchingResult.java | 7 +- 5 files changed, 153 insertions(+), 36 deletions(-) diff --git a/src/main/java/io/appium/java_client/ComparesImages.java b/src/main/java/io/appium/java_client/ComparesImages.java index 1b29c35cf..5a9a58b1c 100644 --- a/src/main/java/io/appium/java_client/ComparesImages.java +++ b/src/main/java/io/appium/java_client/ComparesImages.java @@ -126,8 +126,7 @@ default OccurrenceMatchingResult findImageOccurrence(byte[] fullImage, byte[] pa @Nullable OccurrenceMatchingOptions options) { Object response = CommandExecutionHelper.execute(this, compareImagesCommand(ComparisonMode.MATCH_TEMPLATE, fullImage, partialImage, options)); - //noinspection unchecked - return new OccurrenceMatchingResult((Map) response); + return new OccurrenceMatchingResult(response); } /** diff --git a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java index 49e487b59..0fba408d4 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java @@ -16,8 +16,6 @@ package io.appium.java_client.imagecomparison; -import lombok.AccessLevel; -import lombok.Getter; import org.openqa.selenium.Point; import org.openqa.selenium.Rectangle; @@ -32,12 +30,17 @@ public abstract class ComparisonResult { private static final String VISUALIZATION = "visualization"; - @Getter(AccessLevel.PROTECTED) private final Map commandResult; + protected final Object commandResult; - public ComparisonResult(Map commandResult) { + public ComparisonResult(Object commandResult) { this.commandResult = commandResult; } + protected Map getResultAsMap() { + //noinspection unchecked + return (Map) commandResult; + } + /** * Verifies if the corresponding property is present in the commend result * and throws an exception if not. @@ -45,7 +48,7 @@ public ComparisonResult(Map commandResult) { * @param propertyName the actual property name to be verified for presence */ protected void verifyPropertyPresence(String propertyName) { - if (!commandResult.containsKey(propertyName)) { + if (!getResultAsMap().containsKey(propertyName)) { throw new IllegalStateException( String.format("There is no '%s' attribute in the resulting command output %s. " + "Did you set the options properly?", propertyName, commandResult)); @@ -59,13 +62,13 @@ protected void verifyPropertyPresence(String propertyName) { */ public byte[] getVisualization() { verifyPropertyPresence(VISUALIZATION); - return ((String) getCommandResult().get(VISUALIZATION)).getBytes(StandardCharsets.UTF_8); + return ((String) getResultAsMap().get(VISUALIZATION)).getBytes(StandardCharsets.UTF_8); } /** * Stores visualization image into the given file. * - * @param destination file to save image. + * @param destination File path to save the image to. * @throws IOException On file system I/O error. */ public void storeVisualization(File destination) throws IOException { diff --git a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingResult.java b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingResult.java index 2ba90c7dd..0a983e50a 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/FeaturesMatchingResult.java @@ -43,7 +43,7 @@ public FeaturesMatchingResult(Map input) { */ public int getCount() { verifyPropertyPresence(COUNT); - return ((Long) getCommandResult().get(COUNT)).intValue(); + return ((Long) getResultAsMap().get(COUNT)).intValue(); } /** @@ -56,7 +56,7 @@ public int getCount() { */ public int getTotalCount() { verifyPropertyPresence(TOTAL_COUNT); - return ((Long) getCommandResult().get(TOTAL_COUNT)).intValue(); + return ((Long) getResultAsMap().get(TOTAL_COUNT)).intValue(); } /** @@ -67,7 +67,7 @@ public int getTotalCount() { public List getPoints1() { verifyPropertyPresence(POINTS1); //noinspection unchecked - return ((List>) getCommandResult().get(POINTS1)).stream() + return ((List>) getResultAsMap().get(POINTS1)).stream() .map(ComparisonResult::mapToPoint) .collect(Collectors.toList()); } @@ -80,7 +80,7 @@ public List getPoints1() { public Rectangle getRect1() { verifyPropertyPresence(RECT1); //noinspection unchecked - return mapToRect((Map) getCommandResult().get(RECT1)); + return mapToRect((Map) getResultAsMap().get(RECT1)); } /** @@ -91,7 +91,7 @@ public Rectangle getRect1() { public List getPoints2() { verifyPropertyPresence(POINTS2); //noinspection unchecked - return ((List>) getCommandResult().get(POINTS2)).stream() + return ((List>) getResultAsMap().get(POINTS2)).stream() .map(ComparisonResult::mapToPoint) .collect(Collectors.toList()); } @@ -104,6 +104,6 @@ public List getPoints2() { public Rectangle getRect2() { verifyPropertyPresence(RECT2); //noinspection unchecked - return mapToRect((Map) getCommandResult().get(RECT2)); + return mapToRect((Map) getResultAsMap().get(RECT2)); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java index 510f64b8e..7b0266f23 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/OccurrenceMatchingResult.java @@ -18,34 +18,131 @@ import org.openqa.selenium.Rectangle; +import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class OccurrenceMatchingResult extends ComparisonResult { private static final String RECT = "rect"; - private static final String MULTIPLE = "multiple"; + private static final String SCORE = "score"; - private final boolean isAtRoot; + private final boolean hasMultiple; - public OccurrenceMatchingResult(Map input) { - this(input, true); + public OccurrenceMatchingResult(Object input) { + super(input); + hasMultiple = input instanceof List; } - private OccurrenceMatchingResult(Map input, boolean isAtRoot) { - super(input); - this.isAtRoot = isAtRoot; + /** + * Check whether the current instance contains multiple matches. + * + * @return True or false. + */ + public boolean hasMultiple() { + return hasMultiple; } /** - * Returns rectangle of partial image occurrence. + * Returns rectangle of the partial image occurrence. * * @return The region of the partial image occurrence on the full image. */ public Rectangle getRect() { + if (hasMultiple) { + return getRect(0); + } verifyPropertyPresence(RECT); //noinspection unchecked - return mapToRect((Map) getCommandResult().get(RECT)); + return mapToRect((Map) getResultAsMap().get(RECT)); + } + + /** + * Returns rectangle of the partial image occurrence for the given match index. + * + * @param matchIndex Match index. + * @return Matching rectangle. + * @throws IllegalStateException If the current instance does not represent multiple matches. + */ + public Rectangle getRect(int matchIndex) { + return getMatch(matchIndex).getRect(); + } + + /** + * Returns the score of the partial image occurrence. + * + * @return Matching score in range 0..1. + */ + public double getScore() { + if (hasMultiple) { + return getScore(0); + } + verifyPropertyPresence(SCORE); + var value = getResultAsMap().get(SCORE); + if (value instanceof Long) { + return ((Long) value).doubleValue(); + } + return (Double) value; + } + + /** + * Returns the score of the partial image occurrence for the given match index. + * + * @param matchIndex Match index. + * @return Matching score in range 0..1. + * @throws IllegalStateException If the current instance does not represent multiple matches. + */ + public double getScore(int matchIndex) { + return getMatch(matchIndex).getScore(); + } + + /** + * Returns the visualization of the matching result. + * + * @return The visualization of the matching result represented as base64-encoded PNG image. + */ + @Override + public byte[] getVisualization() { + return hasMultiple ? getVisualization(0) : super.getVisualization(); + } + + /** + * Returns the visualization of the partial image occurrence for the given match index. + * + * @param matchIndex Match index. + * @return The visualization of the matching result represented as base64-encoded PNG image. + * @throws IllegalStateException If the current instance does not represent multiple matches. + */ + public byte[] getVisualization(int matchIndex) { + return getMatch(matchIndex).getVisualization(); + } + + /** + * Stores visualization image into the given file. + * + * @param destination File path to save the image to. + * @throws IOException On file system I/O error. + */ + @Override + public void storeVisualization(File destination) throws IOException { + if (hasMultiple) { + getMatch(0).storeVisualization(destination); + } else { + super.storeVisualization(destination); + } + } + + /** + * Stores visualization image into the given file. + * + * @param matchIndex Match index. + * @param destination File path to save the image to. + * @throws IOException On file system I/O error. + * @throws IllegalStateException If the current instance does not represent multiple matches. + */ + public void storeVisualization(int matchIndex, File destination) throws IOException { + getMatch(matchIndex).storeVisualization(destination); } /** @@ -54,18 +151,37 @@ public Rectangle getRect() { * * @since Appium 1.21.0 * @return The list containing properties of each single match or an empty list. - * @throws IllegalStateException If the accessor is called on a non-root match instance. + * @throws IllegalStateException If the current instance does not represent multiple matches. */ public List getMultiple() { - if (!isAtRoot) { - throw new IllegalStateException("Only the root match could contain multiple submatches"); - } - verifyPropertyPresence(MULTIPLE); + return getMultipleMatches(false); + } + private List getMultipleMatches(boolean throwIfEmpty) { + if (!hasMultiple) { + throw new IllegalStateException(String.format( + "This %s does not represent multiple matches. Did you set options properly?", + getClass().getSimpleName() + )); + } //noinspection unchecked - List> multiple = (List>) getCommandResult().get(MULTIPLE); - return multiple.stream() - .map(m -> new OccurrenceMatchingResult(m, false)) + var matches = ((List>) commandResult).stream() + .map(OccurrenceMatchingResult::new) .collect(Collectors.toList()); + if (matches.isEmpty() && throwIfEmpty) { + throw new IllegalStateException("Zero matches have been found. Try the lookup with different options."); + } + return matches; + } + + private OccurrenceMatchingResult getMatch(int index) { + var matches = getMultipleMatches(true); + if (index < 0 || index >= matches.size()) { + throw new IndexOutOfBoundsException(String.format( + "The match #%s does not exist. The total number of found matches is %s", + index, matches.size() + )); + } + return matches.get(index); } } diff --git a/src/main/java/io/appium/java_client/imagecomparison/SimilarityMatchingResult.java b/src/main/java/io/appium/java_client/imagecomparison/SimilarityMatchingResult.java index 50c388ead..0806e7b53 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/SimilarityMatchingResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/SimilarityMatchingResult.java @@ -33,10 +33,9 @@ public SimilarityMatchingResult(Map input) { */ public double getScore() { verifyPropertyPresence(SCORE); - //noinspection unchecked - if (getCommandResult().get(SCORE) instanceof Long) { - return ((Long) getCommandResult().get(SCORE)).doubleValue(); + if (getResultAsMap().get(SCORE) instanceof Long) { + return ((Long) getResultAsMap().get(SCORE)).doubleValue(); } - return (double) getCommandResult().get(SCORE); + return (double) getResultAsMap().get(SCORE); } } From 73a438752de816d90826501142809c8c807aa614 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 15 May 2024 09:07:20 +0200 Subject: [PATCH 352/501] fix: Use current class loader for the ByteBuddy wrapper (#2172) --- src/main/java/io/appium/java_client/proxy/Helpers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index af724ae43..d162c3ed5 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -136,7 +136,7 @@ public static T createProxy( .defineField("methodCallListeners", MethodCallListener[].class, Visibility.PRIVATE) .implement(HasMethodCallListeners.class).intercept(FieldAccessor.ofBeanProperty()) .make() - .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.WRAPPER) + .load(Helpers.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) .getLoaded() .asSubclass(cls); }); From 56dc41186d466c80d2e038c9b56fac98144bcdb7 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 15 May 2024 09:07:33 +0200 Subject: [PATCH 353/501] fix: Correct extension name for `mobile: replaceElementValue` (#2171) --- .../io/appium/java_client/android/CanReplaceElementValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java index 447377633..3c42f5c35 100644 --- a/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java +++ b/src/main/java/io/appium/java_client/android/CanReplaceElementValue.java @@ -21,7 +21,7 @@ public interface CanReplaceElementValue extends ExecutesMethod, CanRememberExten * off from the typed text). */ default void replaceElementValue(RemoteWebElement element, String value) { - final String extName = "mobile: replaceValue"; + final String extName = "mobile: replaceElementValue"; try { CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "elementId", element.getId(), From b1f8bc9e529906bea353e7bb3bd2c9eabc767e45 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 16 May 2024 09:45:39 +0200 Subject: [PATCH 354/501] fix: Deprecate AppiumProtocolHandshake class (#2173) --- .../io/appium/java_client/AppiumDriver.java | 41 +++---- .../remote/AppiumCommandExecutor.java | 2 +- .../AppiumNewSessionCommandPayload.java | 6 + .../remote/AppiumProtocolHandshake.java | 107 +----------------- 4 files changed, 35 insertions(+), 121 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 6d66639c9..c8d660e9f 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -20,7 +20,6 @@ import io.appium.java_client.internal.ReflectionHelpers; import io.appium.java_client.internal.SessionHelpers; import io.appium.java_client.remote.AppiumCommandExecutor; -import io.appium.java_client.remote.AppiumNewSessionCommandPayload; import io.appium.java_client.remote.AppiumW3CHttpCommandCodec; import io.appium.java_client.remote.options.BaseOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -50,11 +49,13 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.Set; import static com.google.common.base.Strings.isNullOrEmpty; import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX; import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION; +import static java.util.Collections.singleton; import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; /** @@ -265,25 +266,27 @@ public void addCommand(HttpMethod httpMethod, String url, String methodName) { @Override protected void startSession(Capabilities capabilities) { - Response response = execute(new AppiumNewSessionCommandPayload(capabilities)); - if (response == null) { - throw new SessionNotCreatedException( - "The underlying command executor returned a null response."); - } - - Object responseValue = response.getValue(); - if (responseValue == null) { - throw new SessionNotCreatedException( - "The underlying command executor returned a response without payload: " - + response); - } - if (!(responseValue instanceof Map)) { - throw new SessionNotCreatedException( - "The underlying command executor returned a response with a non well formed payload: " - + response); - } + var response = Optional.ofNullable( + execute(DriverCommand.NEW_SESSION(singleton(capabilities))) + ).orElseThrow(() -> new SessionNotCreatedException( + "The underlying command executor returned a null response." + )); + + var rawCapabilities = Optional.ofNullable(response.getValue()) + .map(value -> { + if (!(value instanceof Map)) { + throw new SessionNotCreatedException(String.format( + "The underlying command executor returned a response " + + "with a non well formed payload: %s", response) + ); + } + //noinspection unchecked + return (Map) value; + }) + .orElseThrow(() -> new SessionNotCreatedException( + "The underlying command executor returned a response without payload: " + response) + ); - @SuppressWarnings("unchecked") Map rawCapabilities = (Map) responseValue; // TODO: remove this workaround for Selenium API enforcing some legacy capability values in major version rawCapabilities.remove("platform"); if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME) diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index d3310f478..118f0ff81 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -173,7 +173,7 @@ private Response createSession(Command command) throws IOException { throw new SessionNotCreatedException("Session already exists"); } - ProtocolHandshake.Result result = new AppiumProtocolHandshake().createSession(getClient(), command); + var result = new ProtocolHandshake().createSession(getClient(), command); Dialect dialect = result.getDialect(); if (!(dialect.getCommandCodec() instanceof W3CHttpCommandCodec)) { throw new SessionNotCreatedException("Only W3C sessions are supported. " diff --git a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java index 63fc663a5..31635dabb 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java +++ b/src/main/java/io/appium/java_client/remote/AppiumNewSessionCommandPayload.java @@ -27,6 +27,12 @@ import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; +/** + * This class is deprecated and will be removed. + * + * @deprecated Use CommandPayload instead. + */ +@Deprecated public class AppiumNewSessionCommandPayload extends CommandPayload { /** * Appends "appium:" prefix to all non-prefixed non-standard capabilities. diff --git a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java index f92a3632d..ef2f659da 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java +++ b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandshake.java @@ -16,108 +16,13 @@ package io.appium.java_client.remote; -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.ImmutableCapabilities; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.internal.Either; -import org.openqa.selenium.json.Json; -import org.openqa.selenium.json.JsonOutput; -import org.openqa.selenium.remote.Command; -import org.openqa.selenium.remote.NewSessionPayload; import org.openqa.selenium.remote.ProtocolHandshake; -import org.openqa.selenium.remote.http.Contents; -import org.openqa.selenium.remote.http.HttpHandler; -import java.io.IOException; -import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Set; -import java.util.stream.Stream; - -@SuppressWarnings("UnstableApiUsage") +/** + * This class is deprecated and should be removed. + * + * @deprecated Use ProtocolHandshake instead. + */ +@Deprecated public class AppiumProtocolHandshake extends ProtocolHandshake { - private static void writeJsonPayload(NewSessionPayload srcPayload, Appendable destination) { - try (JsonOutput json = new Json().newOutput(destination)) { - json.beginObject(); - - json.name("capabilities"); - json.beginObject(); - - json.name("firstMatch"); - json.beginArray(); - json.beginObject(); - json.endObject(); - json.endArray(); - - json.name("alwaysMatch"); - try { - Method getW3CMethod = NewSessionPayload.class.getDeclaredMethod("getW3C"); - getW3CMethod.setAccessible(true); - //noinspection unchecked,resource - ((Stream>) getW3CMethod.invoke(srcPayload)) - .findFirst() - .map(json::write) - .orElseGet(() -> { - json.beginObject(); - json.endObject(); - return null; - }); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - throw new WebDriverException(e); - } - - json.endObject(); // Close "capabilities" object - - try { - Method writeMetaDataMethod = NewSessionPayload.class.getDeclaredMethod( - "writeMetaData", JsonOutput.class); - writeMetaDataMethod.setAccessible(true); - writeMetaDataMethod.invoke(srcPayload, json); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - throw new WebDriverException(e); - } - - json.endObject(); - } - } - - @Override - public Result createSession(HttpHandler client, Command command) throws IOException { - //noinspection unchecked - Capabilities desired = ((Set>) command.getParameters().get("capabilities")) - .stream() - .findAny() - .map(ImmutableCapabilities::new) - .orElseGet(ImmutableCapabilities::new); - try (NewSessionPayload payload = NewSessionPayload.create(desired)) { - Either result = createSession(client, payload); - if (result.isRight()) { - return result.right(); - } - throw result.left(); - } - } - - @Override - public Either createSession(HttpHandler client, NewSessionPayload payload) { - - StringWriter stringWriter = new StringWriter(); - writeJsonPayload(payload, stringWriter); - - try { - Method createSessionMethod = ProtocolHandshake.class.getDeclaredMethod( - "createSession", HttpHandler.class, Contents.Supplier.class - ); - createSessionMethod.setAccessible(true); - //noinspection unchecked - return (Either) createSessionMethod.invoke( - this, client, Contents.utf8String(stringWriter.toString()) - ); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - throw new WebDriverException(e); - } - } } From 6b8e28d96973f73dc770662f7c3fbc0a586bef45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 14:39:35 +0300 Subject: [PATCH 355/501] build(deps): Bump com.google.code.gson:gson from 2.10.1 to 2.11.0 (#2175) Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.10.1 to 2.11.0. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.10.1...gson-parent-2.11.0) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 719b1921e..30e5abd59 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ dependencies { } } } - implementation 'com.google.code.gson:gson:2.10.1' + implementation 'com.google.code.gson:gson:2.11.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" } From a67dd969a6252806a14d9adaf09d78f2147fba8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 14:43:20 +0300 Subject: [PATCH 356/501] build(deps): Bump org.owasp.dependencycheck from 9.1.0 to 9.2.0 (#2176) Bumps org.owasp.dependencycheck from 9.1.0 to 9.2.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 30e5abd59..54057da0c 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.1.0' + id 'org.owasp.dependencycheck' version '9.2.0' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 127a70f3449e7a8e174a65812d1fedb639056731 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 28 May 2024 19:57:56 +0300 Subject: [PATCH 357/501] release: v9.2.3 (#2177) --- CHANGELOG.md | 15 +++++++++++++++ README.md | 20 ++++++++++---------- gradle.properties | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92823038c..44838a04f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.2.3_ +- **[BUG FIX]** + - Properly represent `FeaturesMatchingResult` model if `multiple` option is enabled [#2170](https://github.com/appium/java-client/pull/2170) + - Use current class loader for the ByteBuddy wrapper [#2172](https://github.com/appium/java-client/pull/2172) \ + This fixes errors like `NoClassDefFoundError: org/openqa/selenium/remote/RemoteWebElement`, `NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners` when `PageFactory` is used. + - Correct extension name for `mobile: replaceElementValue` [#2171](https://github.com/appium/java-client/pull/2171) +- **[DEPRECATION]** + - Deprecate `AppiumProtocolHandshake` class [#2173](https://github.com/appium/java-client/pull/2173) \ + The original `ProtocolHandshake` class only supports W3C protocol now. There is no need to hack it anymore. +- **[REFACTOR]** + - Replace Guava `HttpHeaders` with Selenium `HttpHeader` [#2151](https://github.com/appium/java-client/pull/2151) +- **[DEPENDENCY CHANGE]** + - Bump SLF4J from `2.0.12` to `2.0.13` [#2158](https://github.com/appium/java-client/pull/2158) + - Bump Gson from `2.10.1` to `2.11.0` [#2175](https://github.com/appium/java-client/pull/2175) + _9.2.2_ - **[BUG FIX]** - fix: Fix building of Android key event parameters [#2145](https://github.com/appium/java-client/pull/2145) diff --git a/README.md b/README.md index 189592d79..6b7f4988e 100644 --- a/README.md +++ b/README.md @@ -93,16 +93,16 @@ dependencies { ``` ### Compatibility Matrix - Appium Java Client | Selenium client -----------------------------------------------------------------------------------|----------------- - `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2` | `4.19.0` - `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` - `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` - N/A | `4.14.0` - `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` - `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` - `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` - `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` + Appium Java Client | Selenium client +-------------------------------------------------------------------------------------------|----------------- + `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0` + `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` + `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` + N/A | `4.14.0` + `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` + `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` + `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` + `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` #### Why is it so complicated? diff --git a/gradle.properties b/gradle.properties index b67a7114b..44154a53b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.19.0 # Please increment the value in a release -appiumClient.version=9.2.2 +appiumClient.version=9.2.3 From e62b3951cb48bea076d104a3a3d0b6588e618587 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 28 May 2024 19:03:42 +0200 Subject: [PATCH 358/501] ci: Bump iOS version (#2167) --- .github/workflows/gradle.yml | 22 +++++++++---------- build.gradle | 1 + .../java_client/ios/BaseIOSWebViewTest.java | 6 +++-- .../java_client/ios/BaseSafariTest.java | 3 +-- .../ios/IOSNativeWebTapSettingTest.java | 2 -- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c83581927..e8006e8df 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -22,9 +22,10 @@ env: ANDROID_SDK_VERSION: "28" ANDROID_EMU_NAME: test ANDROID_EMU_TARGET: default - XCODE_VERSION: "14.2" - IOS_DEVICE_NAME: iPhone 12 - IOS_PLATFORM_VERSION: "16.2" + # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md + XCODE_VERSION: "15.4" + IOS_DEVICE_NAME: iPhone 15 + IOS_PLATFORM_VERSION: "17.5" jobs: build: @@ -34,7 +35,7 @@ jobs: include: - java: 11 # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available - platform: macos-12 + platform: macos-14 e2e-tests: ios - java: 17 platform: ubuntu-latest @@ -100,19 +101,18 @@ jobs: uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: "${{ env.XCODE_VERSION }}" + - name: Prepare iOS simulator + if: matrix.e2e-tests == 'ios' + uses: futureware-tech/simulator-action@v3 + with: + model: "${{ env.IOS_DEVICE_NAME }}" + os_version: "${{ env.IOS_PLATFORM_VERSION }}" - name: Install XCUITest driver if: matrix.e2e-tests == 'ios' run: appium driver install xcuitest - name: Prebuild XCUITest driver if: matrix.e2e-tests == 'ios' run: appium driver run xcuitest build-wda - - name: Prepare iOS simulator - if: matrix.e2e-tests == 'ios' - run: | - xcrun simctl list - target_sim_id=$(xcrun simctl list devices available | grep "$IOS_DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) - open -Fn "/Applications/Xcode_$XCODE_VERSION.app/Contents/Developer/Applications/Simulator.app" - xcrun simctl bootstatus $target_sim_id -b - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' run: ./gradlew e2eIosTest -PisCI -Pselenium.version=$latest_snapshot diff --git a/build.gradle b/build.gradle index 54057da0c..b4f39d1fa 100644 --- a/build.gradle +++ b/build.gradle @@ -242,6 +242,7 @@ testing { filter { exclude '**/IOSScreenRecordTest.class' exclude '**/ImagesComparisonTest.class' + exclude '**/IOSNativeWebTapSettingTest.class' } } } diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index f975d3c5b..752a0c539 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -27,17 +27,19 @@ public class BaseIOSWebViewTest extends BaseIOSTest { private static final String VODQA_ZIP = TestUtils.resourcePathToAbsolutePath("vodqa.zip").toString(); - private static final Duration WEB_VIEW_DETECT_INTERVAL = Duration.ofSeconds(1); - private static final Duration WEB_VIEW_DETECT_DURATION = Duration.ofSeconds(15); + private static final Duration WEB_VIEW_DETECT_INTERVAL = Duration.ofSeconds(2); + private static final Duration WEB_VIEW_DETECT_DURATION = Duration.ofSeconds(30); @BeforeAll public static void beforeClass() { startAppiumServer(); XCUITestOptions options = new XCUITestOptions() + .setPlatformVersion(PLATFORM_VERSION) .setDeviceName(DEVICE_NAME) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) .setCommandTimeouts(Duration.ofSeconds(240)) + .setShowIosLog(true) .setApp(VODQA_ZIP); Supplier createDriver = () -> new IOSDriver(service.getUrl(), options); try { diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java index d35c76357..710f5dbf1 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java @@ -20,13 +20,12 @@ import io.appium.java_client.remote.MobileBrowserType; import org.junit.jupiter.api.BeforeAll; -import java.io.IOException; import java.time.Duration; public class BaseSafariTest extends BaseIOSTest { private static final Duration WEBVIEW_CONNECT_TIMEOUT = Duration.ofSeconds(30); - @BeforeAll public static void beforeClass() throws IOException { + @BeforeAll public static void beforeClass() { startAppiumServer(); XCUITestOptions options = new XCUITestOptions() diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java index 922dbb7cd..8c1bc3fee 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSNativeWebTapSettingTest.java @@ -1,6 +1,5 @@ package io.appium.java_client.ios; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; @@ -14,7 +13,6 @@ public class IOSNativeWebTapSettingTest extends BaseSafariTest { @Test - @Disabled("https://github.com/appium/appium/issues/17014") public void nativeWebTapSettingTest() { assertTrue(driver.isBrowser()); driver.get("https://saucelabs.com/test/guinea-pig"); From c8e13e19746abd8a3d0ee71eed299a442e65c57c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:14:13 +0300 Subject: [PATCH 359/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2187) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.8.0 to 5.9.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.8.0...webdrivermanager-5.9.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b4f39d1fa..c1fdd6d81 100644 --- a/build.gradle +++ b/build.gradle @@ -213,7 +213,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:5.8.0') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.0') { exclude group: 'org.seleniumhq.selenium' } } @@ -257,7 +257,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:5.8.0') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.0') { exclude group: 'org.seleniumhq.selenium' } } From 409d167d6e923b058b79f8e127e665aa882b8536 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 28 Jun 2024 08:08:03 +0200 Subject: [PATCH 360/501] chore: Add mobile: replacements to clipboards API wrappers (#2188) --- .../java_client/CommandExecutionHelper.java | 2 +- .../java_client/clipboard/HasClipboard.java | 33 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 7cb011677..e64470b38 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -62,7 +62,7 @@ public static T executeScript(ExecutesMethod executesMethod, String scriptNa */ @Nullable public static T executeScript( - ExecutesMethod executesMethod, String scriptName, @Nullable Map args + ExecutesMethod executesMethod, String scriptName, @Nullable Map args ) { return execute(executesMethod, Map.entry(EXECUTE_SCRIPT, Map.of( "script", scriptName, diff --git a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java index a6ae3327c..24384da13 100644 --- a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java +++ b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java @@ -16,8 +16,10 @@ package io.appium.java_client.clipboard; +import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.UnsupportedCommandException; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -27,20 +29,25 @@ import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; import static java.util.Objects.requireNonNull; -public interface HasClipboard extends ExecutesMethod { +public interface HasClipboard extends ExecutesMethod, CanRememberExtensionPresence { /** * Set the content of device's clipboard. * - * @param contentType one of supported content types. + * @param contentType one of supported content types. * @param base64Content base64-encoded content to be set. */ default void setClipboard(ClipboardContentType contentType, byte[] base64Content) { - CommandExecutionHelper.execute(this, Map.entry(SET_CLIPBOARD, - Map.of( - "content", new String(requireNonNull(base64Content), StandardCharsets.UTF_8), - "contentType", contentType.name().toLowerCase() - ) - )); + final String extName = "mobile: setClipboard"; + var args = Map.of( + "content", new String(requireNonNull(base64Content), StandardCharsets.UTF_8), + "contentType", contentType.name().toLowerCase() + ); + try { + CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + CommandExecutionHelper.execute(this, Map.entry(SET_CLIPBOARD, args)); + } } /** @@ -50,8 +57,14 @@ default void setClipboard(ClipboardContentType contentType, byte[] base64Content * @return the actual content of the clipboard as base64-encoded string or an empty string if the clipboard is empty */ default String getClipboard(ClipboardContentType contentType) { - return CommandExecutionHelper.execute(this, Map.entry(GET_CLIPBOARD, - Map.of("contentType", contentType.name().toLowerCase()))); + final String extName = "mobile: getClipboard"; + var args = Map.of("contentType", contentType.name().toLowerCase()); + try { + return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); + } catch (UnsupportedCommandException e) { + // TODO: Remove the fallback + return CommandExecutionHelper.execute(this, Map.entry(GET_CLIPBOARD, args)); + } } /** From 9333f955ce9208e7daf79c12be7e7b9a662027bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 19:24:07 +0300 Subject: [PATCH 361/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2189) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.9.0 to 5.9.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.9.0...webdrivermanager-5.9.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c1fdd6d81..955239afd 100644 --- a/build.gradle +++ b/build.gradle @@ -213,7 +213,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:5.9.0') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.1') { exclude group: 'org.seleniumhq.selenium' } } @@ -257,7 +257,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:5.9.0') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.1') { exclude group: 'org.seleniumhq.selenium' } } From d8a31a48e119254a601e8820e7964836db53bef9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 19:24:31 +0300 Subject: [PATCH 362/501] build(deps): Bump org.projectlombok:lombok from 1.18.32 to 1.18.34 (#2191) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.32 to 1.18.34. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.32...v1.18.34) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 955239afd..f98ed2764 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.32' - annotationProcessor 'org.projectlombok:lombok:1.18.32' + compileOnly 'org.projectlombok:lombok:1.18.34' + annotationProcessor 'org.projectlombok:lombok:1.18.34' if (project.hasProperty("isCI")) { api "org.seleniumhq.selenium:selenium-api:${seleniumVersion}" From 969248542bf32c35273ce7cb425e3f5ae108fe05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:40:42 +0300 Subject: [PATCH 363/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.10.2 to 5.10.3 (#2190) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.2 to 5.10.3. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.2...r5.10.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f98ed2764..7afb2ddcf 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.10.2' + implementation 'org.junit.jupiter:junit-jupiter:5.10.3' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:2.2' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From f821c1982aecdbe3e11a22300d405242ea9934cc Mon Sep 17 00:00:00 2001 From: Saikat <41847480+sailfishdev@users.noreply.github.com> Date: Mon, 8 Jul 2024 02:48:38 +0530 Subject: [PATCH 364/501] docs: Update README.md (#2193) --- README.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6b7f4988e..edbb5cc83 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,13 @@ This is the Java language bindings for writing Appium Tests that conform to [Web ## v8 to v9 Migration Since v9 the client only supports Java 11 and above. -Follow the [v8 to v9 Migration Guide](./docs/v8-to-v9-migration-guide.md) in order to streamline the migration process. +Follow the [v8 to v9 Migration Guide](./docs/v8-to-v9-migration-guide.md) to streamline the migration process. ## v7 to v8 Migration Since version 8 Appium Java Client had several major changes, which might require to update your client code. Make sure to follow the [v7 to v8 Migration Guide](./docs/v7-to-v8-migration-guide.md) -in order to streamline the migration process. +to streamline the migration process. ## Add Appium java client to your test framework @@ -46,7 +46,7 @@ dependencies { ### Beta/Snapshots -Java client project is available to use even before it is officially published to maven central. Refer [jitpack.io](https://jitpack.io/#appium/java-client) +Java client project is available to use even before it is officially published to Maven Central. Refer [jitpack.io](https://jitpack.io/#appium/java-client) #### Maven @@ -73,7 +73,7 @@ Add the dependency: #### Gradle -Add the JitPack repository to your build file. Add it in your root build.gradle at the end of repositories: +Add the JitPack repository to your build file. Add it to your root build.gradle at the end of repositories: ```groovy allprojects { @@ -107,11 +107,11 @@ dependencies { #### Why is it so complicated? Selenium client does not follow [Semantic Versioning](https://semver.org/), so breaking changes might be introduced -even in patches, which requires Appium team to update Java client in response. +even in patches, which requires the Appium team to update the Java client in response. #### How to pin Selenium dependencies? -Appium Java Client declares Selenium dependencies using open version range which is handled in differently by different +Appium Java Client declares Selenium dependencies using an open version range which is handled differently by different build tools. Sometimes users may want to pin used Selenium dependencies for [various reasons](https://github.com/appium/java-client/issues/1823). Follow the [Transitive Dependencies Management article](docs/transitive-dependencies-management.md) for more information about establishing a fixed Selenium version for your Java test framework. @@ -130,10 +130,10 @@ Appium java client has dedicated classes to support the following Appium drivers To automate other platforms that are not listed above you could use [AppiumDriver](src/main/java/io/appium/java_client/AppiumDriver.java) or its custom derivatives. -Appium java client is built on top of Selenium and implements same interfaces that the foundation +Appium java client is built on top of Selenium and implements the same interfaces that the foundation [RemoteWebDriver](https://github.com/SeleniumHQ/selenium/blob/trunk/java/src/org/openqa/selenium/remote/RemoteWebDriver.java) -does. However, Selenium lib is mostly focused on web browsers automation while -Appium is universal and covers wide range of possible platforms, e.g. mobile and desktop +does. However, Selenium lib is mostly focused on web browser automation while +Appium is universal and covers a wide range of possible platforms, e.g. mobile and desktop operating systems, IOT devices, etc. Thus, the foundation `AppiumDriver` class in this package extends `RemoteWebDriver` with additional features, and makes it more flexible, so it is not so strictly focused on web-browser related operations. @@ -161,7 +161,7 @@ using [AppiumServiceBuilder](src/main/java/io/appium/java_client/service/local/A **Note** -> AppiumDriverLocalService does not support the server management on non-local hosts +> AppiumDriverLocalService does not support server management on non-local hosts ## Usage Examples @@ -169,14 +169,14 @@ using [AppiumServiceBuilder](src/main/java/io/appium/java_client/service/local/A ```java UiAutomator2Options options = new UiAutomator2Options() - .setUdid('123456') + .setUdid("123456") .setApp("/home/myapp.apk"); AndroidDriver driver = new AndroidDriver( // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub new URL("http://127.0.0.1:4723"), options ); try { - WebElement el = driver.findElement(AppiumBy.xpath, "//Button"); + WebElement el = driver.findElement(AppiumBy.xpath("//Button")); el.click(); driver.getPageSource(); } finally { @@ -188,14 +188,14 @@ try { ```java XCUITestOptions options = new XCUITestOptions() - .setUdid('123456') + .setUdid("123456") .setApp("/home/myapp.ipa"); IOSDriver driver = new IOSDriver( // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub new URL("http://127.0.0.1:4723"), options ); try { - WebElement el = driver.findElement(AppiumBy.accessibilityId, "myId"); + WebElement el = driver.findElement(AppiumBy.accessibilityId("myId")); el.click(); driver.getPageSource(); } finally { @@ -216,7 +216,7 @@ AppiumDriver driver = new AppiumDriver( new URL("http://127.0.0.1:4723"), options ); try { - WebElement el = driver.findElement(AppiumBy.className, "myClass"); + WebElement el = driver.findElement(AppiumBy.className("myClass")); el.click(); driver.getPageSource(); } finally { @@ -226,7 +226,7 @@ try { Check the corresponding driver's READMEs to know the list of capabilities and features it supports. -You could find much more code examples by checking client's +You can find many more code examples by checking client's [unit and integration tests](src/test/java/io/appium/java_client). ## Troubleshooting @@ -234,24 +234,24 @@ You could find much more code examples by checking client's ### InaccessibleObjectException is thrown in runtime if Java 16+ is used Appium Java client uses reflective access to private members of other modules -to ensure proper functionality of several features, like Page Object model. +to ensure proper functionality of several features, like the Page Object model. If you get a runtime exception and `InaccessibleObjectException` is present in -the stacktrace, and your Java runtime is at version 16 or higher, then consider following +the stack trace and your Java runtime is at version 16 or higher, then consider the following [Oracle's tutorial](https://docs.oracle.com/en/java/javase/16/migrate/migrating-jdk-8-later-jdk-releases.html#GUID-7BB28E4D-99B3-4078-BDC4-FC24180CE82B) and/or checking [existing issues](https://github.com/appium/java-client/search?q=InaccessibleObjectException&type=issues) -for possible solutions. Basically, the idea there would be to explicitly allow +for possible solutions. The idea there would be to explicitly allow access for particular modules using `--add-exports/--add-opens` command line arguments. Another possible, but weakly advised solution, would be to downgrade Java to version 15 or lower. -### Issues related to environment variables presence or to their values +### Issues related to environment variables' presence or to their values -Such issues are usually the case when Appium server is started directly from your +Such issues are usually the case when the Appium server is started directly from your framework code rather than run separately by a script or manually. Depending on the way the server process is started it may or may not inherit the currently -active shell environment. That is why you may still receive errors about variables -presence even though these variables ar actually defined for your command line interpreter. +active shell environment. That is why you may still receive errors about the variables' +presence even though these variables are defined for your command line interpreter. Again, there is no universal solution to that, as there are many ways to spin up a new server process. Consider checking the [Appium Environment Troubleshooting](docs/environment.md) document for more information on how to debug and fix process environment issues. From b2c7d872544a3bbca174c25fdddd8774cefdf04d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:39:18 +0300 Subject: [PATCH 365/501] build(deps): Bump org.owasp.dependencycheck from 9.2.0 to 10.0.2 (#2195) Bumps org.owasp.dependencycheck from 9.2.0 to 10.0.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7afb2ddcf..8de5f95be 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '9.2.0' + id 'org.owasp.dependencycheck' version '10.0.2' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 8a637591fb3747eda528b9edf8509499fd22d27b Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 10 Jul 2024 07:51:21 +0300 Subject: [PATCH 366/501] feat: Add ability to use secure WebSocket to listen Logcat messages (#2182) --- .../android/ListensToLogcatMessages.java | 20 +++++++++---------- .../ios/ListensToSyslogMessages.java | 20 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java index 8d16bf7de..d5051da0e 100644 --- a/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java +++ b/src/main/java/io/appium/java_client/android/ListensToLogcatMessages.java @@ -19,10 +19,12 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.ws.StringWebSocketClient; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.SessionId; import java.net.URI; -import java.net.URISyntaxException; +import java.net.URL; import java.util.function.Consumer; import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; @@ -36,7 +38,7 @@ public interface ListensToLogcatMessages extends ExecutesMethod { * is assigned to the default port (4723). */ default void startLogcatBroadcast() { - startLogcatBroadcast("127.0.0.1", DEFAULT_APPIUM_PORT); + startLogcatBroadcast("127.0.0.1"); } /** @@ -56,15 +58,13 @@ default void startLogcatBroadcast(String host) { * @param port the port of the host where Appium server is running */ default void startLogcatBroadcast(String host, int port) { + var remoteWebDriver = (RemoteWebDriver) this; + URL serverUrl = ((HttpCommandExecutor) remoteWebDriver.getCommandExecutor()).getAddressOfRemoteServer(); + var scheme = "https".equals(serverUrl.getProtocol()) ? "wss" : "ws"; CommandExecutionHelper.executeScript(this, "mobile: startLogsBroadcast"); - final URI endpointUri; - try { - endpointUri = new URI(String.format("ws://%s:%s/ws/session/%s/appium/device/logcat", - host, port, ((RemoteWebDriver) this).getSessionId())); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - getLogcatClient().connect(endpointUri); + SessionId sessionId = remoteWebDriver.getSessionId(); + var endpoint = String.format("%s://%s:%s/ws/session/%s/appium/device/logcat", scheme, host, port, sessionId); + getLogcatClient().connect(URI.create(endpoint)); } /** diff --git a/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java b/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java index ef0bd3f9d..98a75158a 100644 --- a/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java +++ b/src/main/java/io/appium/java_client/ios/ListensToSyslogMessages.java @@ -19,10 +19,12 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; import io.appium.java_client.ws.StringWebSocketClient; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.SessionId; import java.net.URI; -import java.net.URISyntaxException; +import java.net.URL; import java.util.function.Consumer; import static io.appium.java_client.service.local.AppiumServiceBuilder.DEFAULT_APPIUM_PORT; @@ -37,7 +39,7 @@ public interface ListensToSyslogMessages extends ExecutesMethod { * is assigned to the default port (4723). */ default void startSyslogBroadcast() { - startSyslogBroadcast("localhost", DEFAULT_APPIUM_PORT); + startSyslogBroadcast("localhost"); } /** @@ -57,15 +59,13 @@ default void startSyslogBroadcast(String host) { * @param port the port of the host where Appium server is running */ default void startSyslogBroadcast(String host, int port) { + var remoteWebDriver = (RemoteWebDriver) this; + URL serverUrl = ((HttpCommandExecutor) remoteWebDriver.getCommandExecutor()).getAddressOfRemoteServer(); + var scheme = "https".equals(serverUrl.getProtocol()) ? "wss" : "ws"; CommandExecutionHelper.executeScript(this, "mobile: startLogsBroadcast"); - final URI endpointUri; - try { - endpointUri = new URI(String.format("ws://%s:%s/ws/session/%s/appium/device/syslog", - host, port, ((RemoteWebDriver) this).getSessionId())); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - getSyslogClient().connect(endpointUri); + SessionId sessionId = remoteWebDriver.getSessionId(); + var endpoint = String.format("%s://%s:%s/ws/session/%s/appium/device/syslog", scheme, host, port, sessionId); + getSyslogClient().connect(URI.create(endpoint)); } /** From 0e24ef1d3e55a6ac8960db70e10d1633e8d33ca8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 13 Jul 2024 09:16:33 +0200 Subject: [PATCH 367/501] chore: Deprecate obsolete TouchAction helpers (#2199) --- .../AndroidAbilityToUseSupplierTest.java | 71 ------- .../java_client/android/AndroidTouchTest.java | 193 ------------------ .../java/io/appium/java_client/AppiumBy.java | 26 +-- .../pagefactory/bys/ContentMappedBy.java | 23 +-- .../java_client/touch/ActionOptions.java | 1 + .../java_client/touch/LongPressOptions.java | 1 + .../appium/java_client/touch/TapOptions.java | 1 + .../appium/java_client/touch/WaitOptions.java | 1 + .../AbstractOptionCombinedWithPosition.java | 1 + .../touch/offset/ElementOption.java | 1 + .../java_client/touch/offset/PointOption.java | 1 + .../java_client/touch/DummyElement.java | 103 ---------- .../java_client/touch/FailsWithMatcher.java | 43 ---- .../java_client/touch/TouchOptionsTests.java | 96 --------- 14 files changed, 11 insertions(+), 551 deletions(-) delete mode 100644 src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java delete mode 100644 src/e2eAndroidTest/java/io/appium/java_client/android/AndroidTouchTest.java delete mode 100644 src/test/java/io/appium/java_client/touch/DummyElement.java delete mode 100644 src/test/java/io/appium/java_client/touch/FailsWithMatcher.java delete mode 100644 src/test/java/io/appium/java_client/touch/TouchOptionsTests.java diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java deleted file mode 100644 index 5db7921a7..000000000 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidAbilityToUseSupplierTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.appium.java_client.android; - -import io.appium.java_client.AppiumBy; -import io.appium.java_client.functions.ActionSupplier; -import io.appium.java_client.touch.offset.ElementOption; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebElement; - -import java.util.List; -import java.util.Map; - -import static io.appium.java_client.TestUtils.getCenter; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -public class AndroidAbilityToUseSupplierTest extends BaseAndroidTest { - - private final ActionSupplier horizontalSwipe = () -> { - driver.findElement(By.id("io.appium.android.apis:id/gallery")); - - WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); - Point location = gallery.getLocation(); - Point center = getCenter(gallery, location); - - ElementOption pressOption = element(images.get(2),-10,center.y - location.y); - ElementOption moveOption = element(gallery, 10,center.y - location.y); - - return new AndroidTouchAction(driver) - .press(pressOption) - .waitAction(waitOptions(ofSeconds(2))) - .moveTo(moveOption) - .release(); - }; - - private final ActionSupplier verticalSwiping = () -> - new AndroidTouchAction(driver) - .press(element(driver.findElement(AppiumBy.accessibilityId("Gallery")))) - - .waitAction(waitOptions(ofSeconds(2))) - - .moveTo(element(driver.findElement(AppiumBy.accessibilityId("Auto Complete")))) - .release(); - - @Test public void horizontalSwipingWithSupplier() { - startActivity(".view.Gallery1"); - WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); - int originalImageCount = images.size(); - - horizontalSwipe.get().perform(); - - assertNotEquals(originalImageCount, - gallery.findElements(AppiumBy.className("android.widget.ImageView")).size()); - } - - @Test public void verticalSwipingWithSupplier() throws Exception { - driver.executeScript("mobile: terminateApp", Map.of("appId", APP_ID)); - driver.executeScript("mobile: activateApp", Map.of("appId", APP_ID)); - driver.findElement(AppiumBy.accessibilityId("Views")).click(); - - Point originalLocation = driver.findElement(AppiumBy.accessibilityId("Gallery")).getLocation(); - verticalSwiping.get().perform(); - Thread.sleep(5000); - assertNotEquals(originalLocation, driver.findElement(AppiumBy.accessibilityId("Gallery")).getLocation()); - } -} diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidTouchTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidTouchTest.java deleted file mode 100644 index c24ed20fa..000000000 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidTouchTest.java +++ /dev/null @@ -1,193 +0,0 @@ -package io.appium.java_client.android; - -import io.appium.java_client.AppiumBy; -import io.appium.java_client.MultiTouchAction; -import io.appium.java_client.TouchAction; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebElement; - -import java.util.List; -import java.util.Map; - -import static io.appium.java_client.TestUtils.getCenter; -import static io.appium.java_client.touch.LongPressOptions.longPressOptions; -import static io.appium.java_client.touch.TapOptions.tapOptions; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static io.appium.java_client.touch.offset.PointOption.point; -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -public class AndroidTouchTest extends BaseAndroidTest { - - @BeforeEach - public void setUp() { - driver.executeScript("mobile: terminateApp", Map.of("appId", APP_ID)); - driver.executeScript("mobile: activateApp", Map.of("appId", APP_ID)); - } - - @Test public void dragNDropByElementTest() { - startActivity(".view.DragAndDropDemo"); - WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); - - WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); - assertEquals("Drag text not empty", "", dragText.getText()); - - TouchAction dragNDrop = new TouchAction(driver) - .longPress(element(dragDot1)) - .moveTo(element(dragDot3)) - .release(); - dragNDrop.perform(); - assertNotEquals("Drag text empty", "", dragText.getText()); - } - - @Test public void dragNDropByElementAndDurationTest() { - startActivity(".view.DragAndDropDemo"); - WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); - - WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); - assertEquals("Drag text not empty", "", dragText.getText()); - - TouchAction dragNDrop = new TouchAction(driver) - .longPress(longPressOptions() - .withElement(element(dragDot1)) - .withDuration(ofSeconds(2))) - .moveTo(element(dragDot3)) - .release(); - dragNDrop.perform(); - assertNotEquals("Drag text empty", "", dragText.getText()); - } - - @Test public void dragNDropByCoordinatesTest() { - startActivity(".view.DragAndDropDemo"); - WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); - - WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); - assertEquals("Drag text not empty", "", dragText.getText()); - - Point center1 = getCenter(dragDot1); - Point center2 = getCenter(dragDot3); - - TouchAction dragNDrop = new TouchAction(driver) - .longPress(point(center1.x, center1.y)) - .moveTo(point(center2.x, center2.y)) - .release(); - dragNDrop.perform(); - assertNotEquals("Drag text empty", "", dragText.getText()); - } - - @Test public void dragNDropByCoordinatesAndDurationTest() { - startActivity(".view.DragAndDropDemo"); - WebElement dragDot1 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_1")); - WebElement dragDot3 = driver.findElement(By.id("io.appium.android.apis:id/drag_dot_3")); - - WebElement dragText = driver.findElement(By.id("io.appium.android.apis:id/drag_text")); - assertEquals("Drag text not empty", "", dragText.getText()); - - Point center1 = getCenter(dragDot1); - Point center2 = getCenter(dragDot3); - - TouchAction dragNDrop = new TouchAction(driver) - .longPress(longPressOptions() - .withPosition(point(center1.x, center1.y)) - .withDuration(ofSeconds(2))) - .moveTo(point(center2.x, center2.y)) - .release(); - dragNDrop.perform(); - assertNotEquals("Drag text empty", "", dragText.getText()); - } - - @Test public void pressByCoordinatesTest() { - startActivity(".view.Buttons1"); - Point point = driver.findElement(By.id("io.appium.android.apis:id/button_toggle")).getLocation(); - new TouchAction(driver) - .press(point(point.x + 20, point.y + 30)) - .waitAction(waitOptions(ofSeconds(1))) - .release() - .perform(); - assertEquals("ON", driver.findElement(By.id("io.appium.android.apis:id/button_toggle")).getText()); - } - - @Test public void pressByElementTest() { - startActivity(".view.Buttons1"); - new TouchAction(driver) - .press(element(driver.findElement(By.id("io.appium.android.apis:id/button_toggle")))) - .waitAction(waitOptions(ofSeconds(1))) - .release() - .perform(); - assertEquals("ON", driver.findElement(By.id("io.appium.android.apis:id/button_toggle")).getText()); - } - - @Test public void tapActionTestByElement() throws Exception { - startActivity(".view.ChronometerDemo"); - WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); - - TouchAction startStop = new TouchAction(driver) - .tap(tapOptions().withElement(element(driver.findElement(By.id("io.appium.android.apis:id/start"))))) - .waitAction(waitOptions(ofSeconds(2))) - .tap(tapOptions().withElement(element(driver.findElement(By.id("io.appium.android.apis:id/stop"))))); - - startStop.perform(); - - String time = chronometer.getText(); - assertNotEquals(time, "Initial format: 00:00"); - Thread.sleep(2500); - assertEquals(time, chronometer.getText()); - } - - @Test public void tapActionTestByCoordinates() throws Exception { - startActivity(".view.ChronometerDemo"); - WebElement chronometer = driver.findElement(By.id("io.appium.android.apis:id/chronometer")); - - Point center1 = getCenter(driver.findElement(By.id("io.appium.android.apis:id/start"))); - - TouchAction startStop = new TouchAction(driver) - .tap(point(center1.x, center1.y)) - .tap(element(driver.findElement(By.id("io.appium.android.apis:id/stop")), 5, 5)); - startStop.perform(); - - String time = chronometer.getText(); - assertNotEquals(time, "Initial format: 00:00"); - Thread.sleep(2500); - assertEquals(time, chronometer.getText()); - } - - @Test public void horizontalSwipingTest() { - startActivity(".view.Gallery1"); - - WebElement gallery = driver.findElement(By.id("io.appium.android.apis:id/gallery")); - List images = gallery.findElements(AppiumBy.className("android.widget.ImageView")); - int originalImageCount = images.size(); - Point location = gallery.getLocation(); - Point center = getCenter(gallery); - - TouchAction swipe = new TouchAction(driver) - .press(element(images.get(2),-10, center.y - location.y)) - .waitAction(waitOptions(ofSeconds(2))) - .moveTo(element(gallery,10,center.y - location.y)) - .release(); - swipe.perform(); - assertNotEquals(originalImageCount, - gallery.findElements(AppiumBy.className("android.widget.ImageView")).size()); - } - - @Test public void multiTouchTest() { - startActivity(".view.Buttons1"); - TouchAction press = new TouchAction(driver) - .press(element(driver.findElement(By.id("io.appium.android.apis:id/button_toggle")))) - .waitAction(waitOptions(ofSeconds(1))) - .release(); - new MultiTouchAction(driver) - .add(press) - .perform(); - assertEquals("ON", driver.findElement(By.id("io.appium.android.apis:id/button_toggle")).getText()); - } - -} diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 21e11d08e..cb374831e 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -17,6 +17,7 @@ package io.appium.java_client; import com.google.common.base.Preconditions; +import lombok.EqualsAndHashCode; import lombok.Getter; import org.openqa.selenium.By; import org.openqa.selenium.By.Remotable; @@ -25,10 +26,10 @@ import java.io.Serializable; import java.util.List; -import java.util.Objects; import static com.google.common.base.Strings.isNullOrEmpty; +@EqualsAndHashCode(callSuper = true) public abstract class AppiumBy extends By implements Remotable { @Getter private final Parameters remoteParameters; @@ -256,27 +257,4 @@ protected ByIosNsPredicate(String locatorString) { super("-ios predicate string", locatorString, "iOSNsPredicate"); } } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - AppiumBy appiumBy = (AppiumBy) o; - return Objects.equals(remoteParameters, appiumBy.remoteParameters) - && Objects.equals(locatorName, appiumBy.locatorName); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), remoteParameters, locatorName); - } } - - diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java index 4bb1b1f4d..6c0c0f99f 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java @@ -16,6 +16,7 @@ package io.appium.java_client.pagefactory.bys; +import lombok.EqualsAndHashCode; import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; @@ -23,11 +24,11 @@ import javax.annotation.Nonnull; import java.util.List; import java.util.Map; -import java.util.Objects; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; import static java.util.Objects.requireNonNull; +@EqualsAndHashCode(callSuper = true) public class ContentMappedBy extends By { private final Map map; private ContentType currentContent = NATIVE_MOBILE_SPECIFIC; @@ -62,24 +63,4 @@ public List findElements(SearchContext context) { public String toString() { return map.get(currentContent).toString(); } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - ContentMappedBy that = (ContentMappedBy) o; - return Objects.equals(map, that.map) && currentContent == that.currentContent; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), map, currentContent); - } } diff --git a/src/main/java/io/appium/java_client/touch/ActionOptions.java b/src/main/java/io/appium/java_client/touch/ActionOptions.java index 2673142e4..2514a92a5 100644 --- a/src/main/java/io/appium/java_client/touch/ActionOptions.java +++ b/src/main/java/io/appium/java_client/touch/ActionOptions.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Map; +@Deprecated public abstract class ActionOptions> { /** * This method is automatically called before building diff --git a/src/main/java/io/appium/java_client/touch/LongPressOptions.java b/src/main/java/io/appium/java_client/touch/LongPressOptions.java index 9f9104b71..56d2334fb 100644 --- a/src/main/java/io/appium/java_client/touch/LongPressOptions.java +++ b/src/main/java/io/appium/java_client/touch/LongPressOptions.java @@ -25,6 +25,7 @@ import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; +@Deprecated public class LongPressOptions extends AbstractOptionCombinedWithPosition { protected Duration duration = null; diff --git a/src/main/java/io/appium/java_client/touch/TapOptions.java b/src/main/java/io/appium/java_client/touch/TapOptions.java index 620df8286..7dee99fae 100644 --- a/src/main/java/io/appium/java_client/touch/TapOptions.java +++ b/src/main/java/io/appium/java_client/touch/TapOptions.java @@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static java.util.Optional.ofNullable; +@Deprecated public class TapOptions extends AbstractOptionCombinedWithPosition { private Integer tapsCount = null; diff --git a/src/main/java/io/appium/java_client/touch/WaitOptions.java b/src/main/java/io/appium/java_client/touch/WaitOptions.java index 29d869b07..11eb0ccdc 100644 --- a/src/main/java/io/appium/java_client/touch/WaitOptions.java +++ b/src/main/java/io/appium/java_client/touch/WaitOptions.java @@ -23,6 +23,7 @@ import static java.time.Duration.ofMillis; import static java.util.Objects.requireNonNull; +@Deprecated public class WaitOptions extends ActionOptions { protected Duration duration = ofMillis(0); diff --git a/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java b/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java index d10a05682..194228eea 100644 --- a/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java +++ b/src/main/java/io/appium/java_client/touch/offset/AbstractOptionCombinedWithPosition.java @@ -6,6 +6,7 @@ import static java.util.Optional.ofNullable; +@Deprecated public abstract class AbstractOptionCombinedWithPosition> extends ActionOptions> { private ActionOptions positionOption; diff --git a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java index 16cf65f70..ac5d577a7 100644 --- a/src/main/java/io/appium/java_client/touch/offset/ElementOption.java +++ b/src/main/java/io/appium/java_client/touch/offset/ElementOption.java @@ -11,6 +11,7 @@ import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; +@Deprecated public class ElementOption extends PointOption { private String elementId; diff --git a/src/main/java/io/appium/java_client/touch/offset/PointOption.java b/src/main/java/io/appium/java_client/touch/offset/PointOption.java index 9bad51609..a45d59f9c 100644 --- a/src/main/java/io/appium/java_client/touch/offset/PointOption.java +++ b/src/main/java/io/appium/java_client/touch/offset/PointOption.java @@ -7,6 +7,7 @@ import static java.util.Optional.ofNullable; +@Deprecated public class PointOption> extends ActionOptions { protected Point coordinates; diff --git a/src/test/java/io/appium/java_client/touch/DummyElement.java b/src/test/java/io/appium/java_client/touch/DummyElement.java deleted file mode 100644 index 62e1fbb12..000000000 --- a/src/test/java/io/appium/java_client/touch/DummyElement.java +++ /dev/null @@ -1,103 +0,0 @@ -package io.appium.java_client.touch; - -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.OutputType; -import org.openqa.selenium.Point; -import org.openqa.selenium.Rectangle; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebElement; - -import java.util.List; - -public class DummyElement extends RemoteWebElement { - @Override - public void click() { - // dummy - } - - @Override - public void submit() { - // dummy - } - - @Override - public void sendKeys(CharSequence... charSequences) { - // dummy - } - - @Override - public void clear() { - // dummy - } - - @Override - public String getTagName() { - return ""; - } - - @Override - public String getAttribute(String s) { - return ""; - } - - @Override - public boolean isSelected() { - return false; - } - - @Override - public boolean isEnabled() { - return false; - } - - @Override - public String getText() { - return ""; - } - - @Override - public List findElements(By by) { - return null; - } - - @Override - public WebElement findElement(By by) { - return null; - } - - @Override - public boolean isDisplayed() { - return false; - } - - @Override - public Point getLocation() { - return null; - } - - @Override - public Dimension getSize() { - return null; - } - - @Override - public Rectangle getRect() { - return null; - } - - @Override - public String getCssValue(String s) { - return ""; - } - - @Override - public X getScreenshotAs(OutputType outputType) { - return null; - } - - @Override - public String getId() { - return "123"; - } -} diff --git a/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java b/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java deleted file mode 100644 index 2d79fcfec..000000000 --- a/src/test/java/io/appium/java_client/touch/FailsWithMatcher.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.appium.java_client.touch; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -import static org.hamcrest.core.AllOf.allOf; -import static org.hamcrest.core.IsInstanceOf.instanceOf; - -public final class FailsWithMatcher extends TypeSafeMatcher { - - private final Matcher matcher; - - private FailsWithMatcher(final Matcher matcher) { - this.matcher = matcher; - } - - public static Matcher failsWith( - final Class throwableType) { - return new FailsWithMatcher<>(instanceOf(throwableType)); - } - - public static Matcher failsWith( - final Class throwableType, final Matcher throwableMatcher) { - return new FailsWithMatcher(allOf(instanceOf(throwableType), throwableMatcher)); - } - - @Override - protected boolean matchesSafely(final Runnable runnable) { - try { - runnable.run(); - return false; - } catch (final Throwable ex) { - return matcher.matches(ex); - } - } - - @Override - public void describeTo(final Description description) { - description.appendText("fails with ").appendDescriptionOf(matcher); - } - -} diff --git a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java b/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java deleted file mode 100644 index a68bc3fa6..000000000 --- a/src/test/java/io/appium/java_client/touch/TouchOptionsTests.java +++ /dev/null @@ -1,96 +0,0 @@ -package io.appium.java_client.touch; - -import io.appium.java_client.touch.offset.ElementOption; -import io.appium.java_client.touch.offset.PointOption; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.Point; -import org.openqa.selenium.remote.RemoteWebElement; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static io.appium.java_client.touch.FailsWithMatcher.failsWith; -import static io.appium.java_client.touch.LongPressOptions.longPressOptions; -import static io.appium.java_client.touch.TapOptions.tapOptions; -import static io.appium.java_client.touch.WaitOptions.waitOptions; -import static io.appium.java_client.touch.offset.ElementOption.element; -import static io.appium.java_client.touch.offset.PointOption.point; -import static java.time.Duration.ofMillis; -import static java.time.Duration.ofSeconds; -import static org.hamcrest.CoreMatchers.everyItem; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.in; -import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class TouchOptionsTests { - private static final RemoteWebElement DUMMY_ELEMENT = new DummyElement(); - - @Test - public void invalidEmptyPointOptionsShouldFailOnBuild() { - assertThrows(IllegalArgumentException.class, - () -> new PointOption<>().build()); - } - - @Test - public void invalidEmptyElementOptionsShouldFailOnBuild() { - assertThrows(IllegalArgumentException.class, - () -> new ElementOption().build()); - } - - @Test - public void invalidOptionsArgumentsShouldFailOnAltering() { - final List invalidOptions = new ArrayList<>(); - invalidOptions.add(() -> waitOptions(ofMillis(-1))); - invalidOptions.add(() -> new ElementOption().withCoordinates(new Point(0, 0)).withElement(null)); - invalidOptions.add(() -> new WaitOptions().withDuration(null)); - invalidOptions.add(() -> tapOptions().withTapsCount(-1)); - invalidOptions.add(() -> longPressOptions().withDuration(null)); - invalidOptions.add(() -> longPressOptions().withDuration(ofMillis(-1))); - for (Runnable item : invalidOptions) { - assertThat(item, failsWith(RuntimeException.class)); - } - } - - @Test - public void longPressOptionsShouldBuildProperly() { - final Map actualOpts = longPressOptions() - .withElement(element(DUMMY_ELEMENT).withCoordinates(0, 0)) - .withDuration(ofMillis(1)) - .build(); - final Map expectedOpts = new HashMap<>(); - expectedOpts.put("element", DUMMY_ELEMENT.getId()); - expectedOpts.put("x", 0); - expectedOpts.put("y", 0); - expectedOpts.put("duration", 1L); - assertThat(actualOpts.entrySet(), everyItem(is(in(expectedOpts.entrySet())))); - assertThat(expectedOpts.entrySet(), everyItem(is(in(actualOpts.entrySet())))); - } - - @Test - public void tapOptionsShouldBuildProperly() { - final Map actualOpts = tapOptions() - .withPosition(point(new Point(0, 0))) - .withTapsCount(2) - .build(); - final Map expectedOpts = new HashMap<>(); - expectedOpts.put("x", 0); - expectedOpts.put("y", 0); - expectedOpts.put("count", 2); - assertThat(actualOpts.entrySet(), everyItem(is(in(expectedOpts.entrySet())))); - assertThat(expectedOpts.entrySet(), everyItem(is(in(actualOpts.entrySet())))); - } - - @Test - public void waitOptionsShouldBuildProperly() { - final Map actualOpts = new WaitOptions() - .withDuration(ofSeconds(1)) - .build(); - final Map expectedOpts = new HashMap<>(); - expectedOpts.put("ms", 1000L); - assertThat(actualOpts.entrySet(), everyItem(is(in(expectedOpts.entrySet())))); - assertThat(expectedOpts.entrySet(), everyItem(is(in(actualOpts.entrySet())))); - } -} From bb4ee2d15316b09ad3e88401482b651e58d6e7fd Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Sun, 21 Jul 2024 02:30:10 +0530 Subject: [PATCH 368/501] feat: Add locator types supported by flutter integration driver (#2201) --- .../java/io/appium/java_client/AppiumBy.java | 125 ++++++++++++++++-- 1 file changed, 113 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index cb374831e..164c7d3e7 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -32,7 +32,8 @@ @EqualsAndHashCode(callSuper = true) public abstract class AppiumBy extends By implements Remotable { - @Getter private final Parameters remoteParameters; + @Getter + private final Parameters remoteParameters; private final String locatorName; protected AppiumBy(String selector, String locatorString, String locatorName) { @@ -41,15 +42,18 @@ protected AppiumBy(String selector, String locatorString, String locatorName) { this.locatorName = locatorName; } - @Override public List findElements(SearchContext context) { + @Override + public List findElements(SearchContext context) { return context.findElements(this); } - @Override public WebElement findElement(SearchContext context) { + @Override + public WebElement findElement(SearchContext context) { return context.findElement(this); } - @Override public String toString() { + @Override + public String toString() { return String.format("%s.%s: %s", AppiumBy.class.getSimpleName(), locatorName, remoteParameters.value()); } @@ -59,6 +63,7 @@ protected AppiumBy(String selector, String locatorString, String locatorName) { * About iOS accessibility * https://developer.apple.com/library/ios/documentation/UIKit/Reference/ * UIAccessibilityIdentification_Protocol/index.html + * * @param accessibilityId id is a convenient UI automation accessibility Id. * @return an instance of {@link AppiumBy.ByAndroidUIAutomator} */ @@ -68,9 +73,10 @@ public static By accessibilityId(final String accessibilityId) { /** * This locator strategy is only available in Espresso Driver mode. + * * @param dataMatcherString is a valid json string detailing hamcrest matcher for Espresso onData(). - * See - * the documentation for more details + * See + * the documentation for more details * @return an instance of {@link AppiumBy.ByAndroidDataMatcher} */ public static By androidDataMatcher(final String dataMatcherString) { @@ -79,6 +85,7 @@ public static By androidDataMatcher(final String dataMatcherString) { /** * Refer to https://developer.android.com/training/testing/ui-automator + * * @param uiautomatorText is Android UIAutomator string * @return an instance of {@link AppiumBy.ByAndroidUIAutomator} */ @@ -88,9 +95,10 @@ public static By androidUIAutomator(final String uiautomatorText) { /** * This locator strategy is only available in Espresso Driver mode. + * * @param viewMatcherString is a valid json string detailing hamcrest matcher for Espresso onView(). - * See - * the documentation for more details + * See + * the documentation for more details * @return an instance of {@link AppiumBy.ByAndroidViewMatcher} */ public static By androidViewMatcher(final String viewMatcherString) { @@ -99,9 +107,10 @@ public static By androidViewMatcher(final String viewMatcherString) { /** * This locator strategy is available in Espresso Driver mode. - * @since Appium 1.8.2 beta + * * @param tag is a view tag string * @return an instance of {@link ByAndroidViewTag} + * @since Appium 1.8.2 beta */ public static By androidViewTag(final String tag) { return new ByAndroidViewTag(tag); @@ -110,6 +119,7 @@ public static By androidViewTag(final String tag) { /** * For IOS it is the full name of the XCUI element and begins with XCUIElementType. * For Android it is the full name of the UIAutomator2 class (e.g.: android.widget.TextView) + * * @param selector the class name of the element * @return an instance of {@link ByClassName} */ @@ -120,6 +130,7 @@ public static By className(final String selector) { /** * For IOS the element name. * For Android it is the resource identifier. + * * @param selector element id * @return an instance of {@link ById} */ @@ -130,6 +141,7 @@ public static By id(final String selector) { /** * For IOS the element name. * For Android it is the resource identifier. + * * @param selector element id * @return an instance of {@link ByName} */ @@ -153,14 +165,14 @@ public static By custom(final String selector) { * This locator strategy is available only if OpenCV libraries and * Node.js bindings are installed on the server machine. * + * @param b64Template base64-encoded template image string. Supported image formats are the same + * as for OpenCV library. + * @return an instance of {@link ByImage} * @see * The documentation on Image Comparison Features * @see * The settings available for lookup fine-tuning * @since Appium 1.8.2 - * @param b64Template base64-encoded template image string. Supported image formats are the same - * as for OpenCV library. - * @return an instance of {@link ByImage} */ public static By image(final String b64Template) { return new ByImage(b64Template); @@ -168,6 +180,7 @@ public static By image(final String b64Template) { /** * This locator strategy is available in XCUITest Driver mode. + * * @param iOSClassChainString is a valid class chain locator string. * See * the documentation for more details @@ -179,6 +192,7 @@ public static By iOSClassChain(final String iOSClassChainString) { /** * This locator strategy is available in XCUITest Driver mode. + * * @param iOSNsPredicateString is an iOS NsPredicate String * @return an instance of {@link AppiumBy.ByIosNsPredicate} */ @@ -186,6 +200,56 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) { return new ByIosNsPredicate(iOSNsPredicateString); } + /** + * This locator strategy is available in FlutterIntegration Driver mode. + * + * @param selector is the value defined to the key attribute of the flutter element + * @return an instance of {@link AppiumBy.ByFlutterKey} + */ + public static By flutterKey(final String selector) { + return new ByFlutterKey(selector); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode. + * + * @param selector is the Type of widget mounted in the app tree + * @return an instance of {@link AppiumBy.ByFlutterType} + */ + public static By flutterType(final String selector) { + return new ByFlutterType(selector); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode. + * + * @param selector is the text that is present on the widget + * @return an instance of {@link AppiumBy.ByFlutterText} + */ + public static By flutterText(final String selector) { + return new ByFlutterText(selector); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode. + * + * @param selector is the text that is partially present on the widget + * @return an instance of {@link AppiumBy.ByFlutterTextContaining} + */ + public static By flutterTextContaining(final String selector) { + return new ByFlutterTextContaining(selector); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode. + * + * @param semanticsLabel represents the value assigned to the label attribute of semantics element + * @return an instance of {@link AppiumBy.ByFlutterSemanticsLabel} + */ + public static By flutterSemanticsLabel(final String semanticsLabel) { + return new ByFlutterSemanticsLabel(semanticsLabel); + } + public static class ByAccessibilityId extends AppiumBy implements Serializable { public ByAccessibilityId(String accessibilityId) { super("accessibility id", accessibilityId, "accessibilityId"); @@ -257,4 +321,41 @@ protected ByIosNsPredicate(String locatorString) { super("-ios predicate string", locatorString, "iOSNsPredicate"); } } + + public abstract static class FlutterBy extends AppiumBy { + protected FlutterBy(String selector, String locatorString, String locatorName) { + super(selector, locatorString, locatorName); + } + } + + public static class ByFlutterType extends FlutterBy implements Serializable { + protected ByFlutterType(String locatorString) { + super("-flutter type", locatorString, "flutterType"); + } + } + + public static class ByFlutterKey extends FlutterBy implements Serializable { + protected ByFlutterKey(String locatorString) { + super("-flutter key", locatorString, "flutterKey"); + } + } + + public static class ByFlutterSemanticsLabel extends FlutterBy implements Serializable { + protected ByFlutterSemanticsLabel(String locatorString) { + super("-flutter semantics label", locatorString, "flutterSemanticsLabel"); + } + } + + public static class ByFlutterText extends FlutterBy implements Serializable { + protected ByFlutterText(String locatorString) { + super("-flutter text", locatorString, "flutterText"); + } + } + + public static class ByFlutterTextContaining extends FlutterBy implements Serializable { + protected ByFlutterTextContaining(String locatorString) { + super("-flutter text containing", locatorString, "flutterTextContaining"); + } + } + } From 7f28bfbcf051ec0b3d53533280b1236ca2a2838f Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Tue, 23 Jul 2024 06:20:12 +0530 Subject: [PATCH 369/501] feat: add support for FlutterAndroidDriver (#2203) --- .github/workflows/gradle.yml | 48 +++++++--- build.gradle | 23 ++++- .../java_client/android/BaseFlutterTest.java | 82 +++++++++++++++++ .../java_client/android/CommandTest.java | 62 +++++++++++++ .../java_client/android/FinderTests.java | 54 ++++++++++++ .../java/io/appium/java_client/AppiumBy.java | 10 +-- .../flutter/CanExecuteFlutterScripts.java | 20 +++++ .../SupportsScrollingOfFlutterElements.java | 17 ++++ .../SupportsWaitingForFlutterElements.java | 25 ++++++ .../flutter/android/FlutterAndroidDriver.java | 72 +++++++++++++++ .../commands/FlutterCommandParameter.java | 25 ++++++ .../flutter/commands/ScrollParameter.java | 87 +++++++++++++++++++ .../flutter/commands/WaitParameter.java | 38 ++++++++ .../java_client/remote/AutomationName.java | 2 + 14 files changed, 544 insertions(+), 21 deletions(-) create mode 100644 src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java create mode 100644 src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java create mode 100644 src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java create mode 100644 src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java create mode 100644 src/main/java/io/appium/java_client/flutter/SupportsScrollingOfFlutterElements.java create mode 100644 src/main/java/io/appium/java_client/flutter/SupportsWaitingForFlutterElements.java create mode 100644 src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java create mode 100644 src/main/java/io/appium/java_client/flutter/commands/FlutterCommandParameter.java create mode 100644 src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java create mode 100644 src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e8006e8df..8cdab0ef7 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -26,6 +26,7 @@ env: XCODE_VERSION: "15.4" IOS_DEVICE_NAME: iPhone 15 IOS_PLATFORM_VERSION: "17.5" + FLUTTER_ANDROID_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/app-debug.apk" jobs: build: @@ -33,25 +34,28 @@ jobs: strategy: matrix: include: - - java: 11 - # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available - platform: macos-14 - e2e-tests: ios - - java: 17 - platform: ubuntu-latest - e2e-tests: android - - java: 21 - platform: ubuntu-latest + - java: 11 + # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available + platform: macos-14 + e2e-tests: ios + - java: 17 + platform: ubuntu-latest + e2e-tests: android + - java: 17 + platform: ubuntu-latest + e2e-tests: flutter-android + - java: 21 + platform: ubuntu-latest fail-fast: false runs-on: ${{ matrix.platform }} - name: JDK ${{ matrix.java }} - ${{ matrix.platform }} + name: JDK ${{ matrix.java }} - ${{ matrix.platform }} ${{ matrix.e2e-tests }} steps: - uses: actions/checkout@v4 - name: Enable KVM group perms - if: matrix.e2e-tests == 'android' + if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'flutter-android' run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules sudo udevadm control --reload-rules @@ -73,18 +77,23 @@ jobs: ./gradlew clean build -PisCI -Pselenium.version=$latest_snapshot - name: Install Node.js - if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' + if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-android' uses: actions/setup-node@v4 with: node-version: 'lts/*' - name: Install Appium - if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' + if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-android' run: npm install --location=global appium - name: Install UIA2 driver - if: matrix.e2e-tests == 'android' + if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'flutter-android' run: appium driver install uiautomator2 + + - name: Install Flutter Integration driver + if: matrix.e2e-tests == 'flutter-android' + run: appium driver install appium-flutter-integration-driver --source npm + - name: Run Android E2E tests if: matrix.e2e-tests == 'android' uses: reactivecircus/android-emulator-runner@v2 @@ -96,6 +105,17 @@ jobs: disable-animations: true target: ${{ env.ANDROID_EMU_TARGET }} + - name: Run Flutter Android E2E tests + if: matrix.e2e-tests == 'flutter-android' + uses: reactivecircus/android-emulator-runner@v2 + with: + script: ./gradlew e2eFlutterTest -Pplatform="android" -Pselenium.version=$latest_snapshot -PisCI -PflutterApp=${{ env.FLUTTER_ANDROID_APP }} + api-level: ${{ env.ANDROID_SDK_VERSION }} + avd-name: ${{ env.ANDROID_EMU_NAME }} + disable-spellchecker: true + disable-animations: true + target: ${{ env.ANDROID_EMU_TARGET }} + - name: Select Xcode if: matrix.e2e-tests == 'ios' uses: maxim-lobanov/setup-xcode@v1 diff --git a/build.gradle b/build.gradle index 8de5f95be..3488703d7 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ dependencies { } dependencyCheck { - failBuildOnCVSS=22 + failBuildOnCVSS = 22 } jacoco { @@ -185,7 +185,7 @@ wrapper { processResources { filter ReplaceTokens, tokens: [ - 'selenium.version': seleniumVersion, + 'selenium.version' : seleniumVersion, 'appiumClient.version': appiumClientVersion ] } @@ -290,5 +290,24 @@ testing { } } } + + e2eFlutterTest(JvmTestSuite) { + sources { + java { + srcDirs = ['src/e2eFlutterTest/java'] + } + } + dependencies { + implementation project() + implementation(sourceSets.test.output) + } + + targets.configureEach { + testTask.configure { + shouldRunAfter(test) + systemProperties project.properties.subMap(["platform", "flutterApp"]) + } + } + } } } diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java new file mode 100644 index 000000000..e18112d4a --- /dev/null +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java @@ -0,0 +1,82 @@ +package io.appium.java_client.android; + +import io.appium.java_client.AppiumBy; +import io.appium.java_client.android.options.UiAutomator2Options; +import io.appium.java_client.flutter.android.FlutterAndroidDriver; +import io.appium.java_client.flutter.commands.ScrollParameter; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.openqa.selenium.By; +import org.openqa.selenium.InvalidArgumentException; +import org.openqa.selenium.WebElement; + +import java.net.MalformedURLException; +import java.util.Optional; + +class BaseFlutterTest { + + private static final boolean IS_ANDROID = Optional + .ofNullable(System.getProperty("platform")) + .orElse("android") + .equalsIgnoreCase("android"); + private static final String APP_ID = IS_ANDROID + ? "com.example.appium_testing_app" : "com.example.appiumTestingApp"; + protected static final int PORT = 4723; + + private static AppiumDriverLocalService service; + protected static FlutterAndroidDriver driver; + protected static final By LOGIN_BUTTON = AppiumBy.flutterText("Login"); + + /** + * initialization. + */ + @BeforeAll + public static void beforeClass() { + service = new AppiumServiceBuilder() + .withIPAddress("127.0.0.1") + .usingPort(PORT) + .build(); + service.start(); + } + + @BeforeEach + public void startSession() throws MalformedURLException { + if (IS_ANDROID) { + // TODO: update it with FlutterDriverOptions once implemented + UiAutomator2Options options = new UiAutomator2Options() + .setAutomationName(AutomationName.FLUTTER_INTEGRATION) + .setApp(System.getProperty("flutterApp")) + .eventTimings(); + driver = new FlutterAndroidDriver(service.getUrl(), options); + } else { + throw new InvalidArgumentException( + "Currently flutter driver implementation only supports android platform"); + } + } + + @AfterEach + public void stopSession() { + if (driver != null) { + driver.quit(); + } + } + + @AfterAll + public static void afterClass() { + if (service.isRunning()) { + service.stop(); + } + } + + public void openScreen(String screenTitle) { + ScrollParameter scrollOptions = new ScrollParameter( + AppiumBy.flutterText(screenTitle), ScrollParameter.ScrollDirection.DOWN); + WebElement element = driver.scrollTillVisible(scrollOptions); + element.click(); + } +} diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java new file mode 100644 index 000000000..80f32002d --- /dev/null +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java @@ -0,0 +1,62 @@ +package io.appium.java_client.android; + +import io.appium.java_client.AppiumBy; +import io.appium.java_client.flutter.commands.ScrollParameter; +import io.appium.java_client.flutter.commands.WaitParameter; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.WebElement; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CommandTest extends BaseFlutterTest { + + private static final AppiumBy.FlutterBy MESSAGE_FIELD = AppiumBy.flutterKey("message_field"); + private static final AppiumBy.FlutterBy TOGGLE_BUTTON = AppiumBy.flutterKey("toggle_button"); + + @Test + public void testWaitCommand() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Lazy Loading"); + + WebElement messageField = driver.findElement(MESSAGE_FIELD); + WebElement toggleButton = driver.findElement(TOGGLE_BUTTON); + + assertEquals(messageField.getText(), "Hello world"); + toggleButton.click(); + assertEquals(messageField.getText(), "Hello world"); + + WaitParameter waitParameter = new WaitParameter().setLocator(MESSAGE_FIELD); + + driver.waitForInVisible(waitParameter); + assertEquals(0, driver.findElements(MESSAGE_FIELD).size()); + toggleButton.click(); + driver.waitForVisible(waitParameter); + assertEquals(1, driver.findElements(MESSAGE_FIELD).size()); + assertEquals(messageField.getText(), "Hello world"); + } + + @Test + public void testScrollTillVisibleCommand() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Vertical Swiping"); + + WebElement firstElement = driver.scrollTillVisible(new ScrollParameter(AppiumBy.flutterText("Java"))); + assertTrue(Boolean.parseBoolean(firstElement.getAttribute("displayed"))); + + WebElement lastElement = driver.scrollTillVisible(new ScrollParameter(AppiumBy.flutterText("Protractor"))); + assertTrue(Boolean.parseBoolean(lastElement.getAttribute("displayed"))); + assertFalse(Boolean.parseBoolean(firstElement.getAttribute("displayed"))); + + firstElement = driver.scrollTillVisible( + new ScrollParameter(AppiumBy.flutterText("Java"), + ScrollParameter.ScrollDirection.UP) + ); + assertTrue(Boolean.parseBoolean(firstElement.getAttribute("displayed"))); + assertFalse(Boolean.parseBoolean(lastElement.getAttribute("displayed"))); + } + +} diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java b/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java new file mode 100644 index 000000000..dc2361869 --- /dev/null +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java @@ -0,0 +1,54 @@ +package io.appium.java_client.android; + +import io.appium.java_client.AppiumBy; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.WebElement; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + +class FinderTests extends BaseFlutterTest { + + @Test + public void testFlutterByKey() { + WebElement userNameField = driver.findElement(AppiumBy.flutterKey("username_text_field")); + assertEquals("admin", userNameField.getText()); + userNameField.clear(); + driver.findElement(AppiumBy.flutterKey("username_text_field")).sendKeys("admin123"); + assertEquals("admin123", userNameField.getText()); + } + + @Test + public void testFlutterByType() { + WebElement loginButton = driver.findElement(AppiumBy.flutterType("ElevatedButton")); + assertEquals(loginButton.findElement(AppiumBy.flutterType("Text")).getText(), "Login"); + } + + @Test + public void testFlutterText() { + WebElement loginButton = driver.findElement(AppiumBy.flutterText("Login")); + assertEquals(loginButton.getText(), "Login"); + loginButton.click(); + + assertEquals(1, driver.findElements(AppiumBy.flutterText("Slider")).size()); + } + + @Test + public void testFlutterTextContaining() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + assertEquals(driver.findElement(AppiumBy.flutterTextContaining("Vertical")).getText(), + "Vertical Swiping"); + } + + @Test + public void testFlutterSemanticsLabel() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Lazy Loading"); + + WebElement messageField = driver.findElement(AppiumBy.flutterSemanticsLabel("message_field")); + assertEquals(messageField.getText(), + "Hello world"); + } +} diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 164c7d3e7..aca01fea7 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -206,7 +206,7 @@ public static By iOSNsPredicateString(final String iOSNsPredicateString) { * @param selector is the value defined to the key attribute of the flutter element * @return an instance of {@link AppiumBy.ByFlutterKey} */ - public static By flutterKey(final String selector) { + public static FlutterBy flutterKey(final String selector) { return new ByFlutterKey(selector); } @@ -216,7 +216,7 @@ public static By flutterKey(final String selector) { * @param selector is the Type of widget mounted in the app tree * @return an instance of {@link AppiumBy.ByFlutterType} */ - public static By flutterType(final String selector) { + public static FlutterBy flutterType(final String selector) { return new ByFlutterType(selector); } @@ -226,7 +226,7 @@ public static By flutterType(final String selector) { * @param selector is the text that is present on the widget * @return an instance of {@link AppiumBy.ByFlutterText} */ - public static By flutterText(final String selector) { + public static FlutterBy flutterText(final String selector) { return new ByFlutterText(selector); } @@ -236,7 +236,7 @@ public static By flutterText(final String selector) { * @param selector is the text that is partially present on the widget * @return an instance of {@link AppiumBy.ByFlutterTextContaining} */ - public static By flutterTextContaining(final String selector) { + public static FlutterBy flutterTextContaining(final String selector) { return new ByFlutterTextContaining(selector); } @@ -246,7 +246,7 @@ public static By flutterTextContaining(final String selector) { * @param semanticsLabel represents the value assigned to the label attribute of semantics element * @return an instance of {@link AppiumBy.ByFlutterSemanticsLabel} */ - public static By flutterSemanticsLabel(final String semanticsLabel) { + public static FlutterBy flutterSemanticsLabel(final String semanticsLabel) { return new ByFlutterSemanticsLabel(semanticsLabel); } diff --git a/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java b/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java new file mode 100644 index 000000000..f8eaf3af4 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java @@ -0,0 +1,20 @@ +package io.appium.java_client.flutter; + +import io.appium.java_client.flutter.commands.FlutterCommandParameter; +import org.openqa.selenium.JavascriptExecutor; + +public interface CanExecuteFlutterScripts extends JavascriptExecutor { + + /** + * Executes a Flutter-specific script using JavascriptExecutor. + * + * @param scriptName The name of the Flutter script to execute. + * @param parameter The parameters for the Flutter command. + * @return The result of executing the script. + */ + default Object executeFlutterCommand(String scriptName, FlutterCommandParameter parameter) { + String commandName = String.format("flutter: %s", scriptName); + return executeScript(commandName, parameter.toJson()); + } + +} diff --git a/src/main/java/io/appium/java_client/flutter/SupportsScrollingOfFlutterElements.java b/src/main/java/io/appium/java_client/flutter/SupportsScrollingOfFlutterElements.java new file mode 100644 index 000000000..25a734cf7 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/SupportsScrollingOfFlutterElements.java @@ -0,0 +1,17 @@ +package io.appium.java_client.flutter; + +import io.appium.java_client.flutter.commands.ScrollParameter; +import org.openqa.selenium.WebElement; + +public interface SupportsScrollingOfFlutterElements extends CanExecuteFlutterScripts { + + /** + * Scrolls to make an element visible on the screen. + * + * @param parameter The parameters for scrolling, specifying element details. + * @return The WebElement that was scrolled to. + */ + default WebElement scrollTillVisible(ScrollParameter parameter) { + return (WebElement) executeFlutterCommand("scrollTillVisible", parameter); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/SupportsWaitingForFlutterElements.java b/src/main/java/io/appium/java_client/flutter/SupportsWaitingForFlutterElements.java new file mode 100644 index 000000000..521f75cc8 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/SupportsWaitingForFlutterElements.java @@ -0,0 +1,25 @@ +package io.appium.java_client.flutter; + +import io.appium.java_client.flutter.commands.WaitParameter; + +public interface SupportsWaitingForFlutterElements extends CanExecuteFlutterScripts { + + /** + * Waits for an element to become visible on the screen. + * + * @param parameter The parameters for waiting, specifying timeout and element details. + */ + default void waitForVisible(WaitParameter parameter) { + executeFlutterCommand("waitForVisible", parameter); + } + + /** + * Waits for an element to become absent on the screen. + * + * @param parameter The parameters for waiting, specifying timeout and element details. + */ + default void waitForInVisible(WaitParameter parameter) { + executeFlutterCommand("waitForAbsent", parameter); + } + +} diff --git a/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java b/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java new file mode 100644 index 000000000..f7be154ff --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java @@ -0,0 +1,72 @@ +package io.appium.java_client.flutter.android; + +import io.appium.java_client.AppiumClientConfig; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.flutter.SupportsScrollingOfFlutterElements; +import io.appium.java_client.flutter.SupportsWaitingForFlutterElements; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.HttpClient; + +import java.net.URL; + +/** + * Custom AndroidDriver implementation with additional Flutter-specific capabilities. + */ +public class FlutterAndroidDriver extends AndroidDriver implements + SupportsWaitingForFlutterElements, + SupportsScrollingOfFlutterElements { + + public FlutterAndroidDriver(HttpCommandExecutor executor, Capabilities capabilities) { + super(executor, capabilities); + } + + public FlutterAndroidDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, capabilities); + } + + public FlutterAndroidDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, capabilities); + } + + public FlutterAndroidDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, capabilities); + } + + public FlutterAndroidDriver( + AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(service, httpClientFactory, capabilities); + } + + public FlutterAndroidDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, capabilities); + } + + public FlutterAndroidDriver( + AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(builder, httpClientFactory, capabilities); + } + + public FlutterAndroidDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, capabilities); + } + + public FlutterAndroidDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, capabilities); + } + + public FlutterAndroidDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, capabilities); + } + + public FlutterAndroidDriver(Capabilities capabilities) { + super(capabilities); + } + + public FlutterAndroidDriver(URL remoteSessionAddress, String automationName) { + super(remoteSessionAddress, automationName); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/commands/FlutterCommandParameter.java b/src/main/java/io/appium/java_client/flutter/commands/FlutterCommandParameter.java new file mode 100644 index 000000000..ddd2d74f6 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/commands/FlutterCommandParameter.java @@ -0,0 +1,25 @@ +package io.appium.java_client.flutter.commands; + +import io.appium.java_client.AppiumBy; +import org.openqa.selenium.By; + +import java.util.Map; + +public abstract class FlutterCommandParameter { + + /** + * Parses an Appium Flutter locator into a Map representation suitable for Flutter Integration Driver. + * + * @param by The FlutterBy instance representing the locator to parse. + * @return A Map containing the parsed locator information with keys using and value. + */ + protected static Map parseFlutterLocator(AppiumBy.FlutterBy by) { + By.Remotable.Parameters parameters = by.getRemoteParameters(); + return Map.of( + "using", parameters.using(), + "value", parameters.value() + ); + } + + public abstract Map toJson(); +} diff --git a/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java b/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java new file mode 100644 index 000000000..695cb060d --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java @@ -0,0 +1,87 @@ +package io.appium.java_client.flutter.commands; + +import com.google.common.base.Preconditions; +import io.appium.java_client.AppiumBy; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.openqa.selenium.WebElement; + +import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Accessors(chain = true) +@Getter +@Setter +public class ScrollParameter extends FlutterCommandParameter { + private AppiumBy.FlutterBy scrollTo; + private WebElement scrollView; + private ScrollDirection scrollDirection; + private Integer delta; + private Integer maxScrolls; + private Integer settleBetweenScrollsTimeout; + private Duration dragDuration; + + private ScrollParameter() { + } + + /** + * Constructs a new ScrollOptions object with the given parameters. + * + * @param scrollTo the locator used for scrolling to a specific element + */ + public ScrollParameter(AppiumBy.FlutterBy scrollTo) { + this(scrollTo, ScrollDirection.DOWN); + } + + /** + * Constructs a new ScrollOptions object with the given parameters. + * + * @param scrollTo the locator used for scrolling to a specific element + * @param scrollDirection the direction in which to scroll (e.g., ScrollDirection.DOWN) + * @throws IllegalArgumentException if scrollTo is null + */ + public ScrollParameter(AppiumBy.FlutterBy scrollTo, ScrollDirection scrollDirection) { + Preconditions.checkArgument(scrollTo != null, "Must supply a valid locator for scrollTo"); + this.scrollTo = scrollTo; + this.scrollDirection = scrollDirection; + } + + @Override + public Map toJson() { + Map params = new HashMap<>(); + + params.put("finder", parseFlutterLocator(scrollTo)); + Optional.ofNullable(scrollView) + .ifPresent(scrollView -> params.put("scrollView", scrollView)); + Optional.ofNullable(delta) + .ifPresent(delta -> params.put("delta", delta)); + Optional.ofNullable(maxScrolls) + .ifPresent(maxScrolls -> params.put("delta", maxScrolls)); + Optional.ofNullable(settleBetweenScrollsTimeout) + .ifPresent(timeout -> params.put("delta", settleBetweenScrollsTimeout)); + Optional.ofNullable(scrollDirection) + .ifPresent(direction -> params.put("scrollDirection", direction.getDirection())); + Optional.ofNullable(dragDuration) + .ifPresent(direction -> params.put("dragDuration", dragDuration.getSeconds())); + + return Collections.unmodifiableMap(params); + } + + @Getter + public static enum ScrollDirection { + UP("up"), + RIGHT("right"), + DOWN("down"), + LEFT("left"); + + private final String direction; + + ScrollDirection(String direction) { + this.direction = direction; + } + } +} diff --git a/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java b/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java new file mode 100644 index 000000000..89e0a19cf --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java @@ -0,0 +1,38 @@ +package io.appium.java_client.flutter.commands; + +import com.google.common.base.Preconditions; +import io.appium.java_client.AppiumBy; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.openqa.selenium.WebElement; + +import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Accessors(chain = true) +@Getter +@Setter +public class WaitParameter extends FlutterCommandParameter { + private WebElement element; + private AppiumBy.FlutterBy locator; + private Duration timeout; + + @Override + public Map toJson() { + Preconditions.checkArgument(element != null || locator != null, + "Must supply a valid element or locator to wait for"); + Map params = new HashMap<>(); + Optional.ofNullable(element) + .ifPresent(element -> params.put("element", element)); + Optional.ofNullable(locator) + .ifPresent(locator -> params.put("locator", parseFlutterLocator(locator))); + Optional.ofNullable(timeout) + .ifPresent(timeout -> params.put("timeout", timeout)); + + return Collections.unmodifiableMap(params); + } +} diff --git a/src/main/java/io/appium/java_client/remote/AutomationName.java b/src/main/java/io/appium/java_client/remote/AutomationName.java index 7df904c4d..e941d516b 100644 --- a/src/main/java/io/appium/java_client/remote/AutomationName.java +++ b/src/main/java/io/appium/java_client/remote/AutomationName.java @@ -38,4 +38,6 @@ public interface AutomationName { // Third-party drivers // https://github.com/YOU-i-Labs/appium-youiengine-driver String YOUI_ENGINE = "youiengine"; + //https://github.com/AppiumTestDistribution/appium-flutter-integration-driver + String FLUTTER_INTEGRATION = "FlutterIntegration"; } From c809510e63120ca1117a01d195094a804f11c99b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 07:45:37 +0300 Subject: [PATCH 370/501] build(deps): Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.15.0 (#2204) Bumps org.apache.commons:commons-lang3 from 3.14.0 to 3.15.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3488703d7..b4656f8a5 100644 --- a/build.gradle +++ b/build.gradle @@ -233,7 +233,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('org.apache.commons:commons-lang3:3.14.0') + implementation('org.apache.commons:commons-lang3:3.15.0') } targets.configureEach { From 62a3a6fdcb082bd1884645838f4a584f97fc207d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 00:41:20 +0300 Subject: [PATCH 371/501] build(deps): Bump org.owasp.dependencycheck from 10.0.2 to 10.0.3 (#2205) Bumps org.owasp.dependencycheck from 10.0.2 to 10.0.3. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b4656f8a5..b65d41661 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '10.0.2' + id 'org.owasp.dependencycheck' version '10.0.3' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 6bd38a15ed5f971d7172d2f7edb4d069538d1d15 Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Wed, 24 Jul 2024 06:09:03 +0530 Subject: [PATCH 372/501] feat: Add support for FlutterIOSDriver (#2206) --- .github/workflows/gradle.yml | 25 ++++--- .../java_client/android/BaseFlutterTest.java | 50 ++++++++++---- .../java_client/android/CommandTest.java | 60 +++++++++++++++- .../java_client/android/FinderTests.java | 10 +-- .../flutter/FlutterDriverOptions.java | 51 ++++++++++++++ .../flutter/FlutterIntegrationTestDriver.java | 23 +++++++ .../SupportsGestureOnFlutterElements.java | 35 ++++++++++ .../flutter/android/FlutterAndroidDriver.java | 7 +- .../commands/DoubleClickParameter.java | 34 +++++++++ .../commands/DragAndDropParameter.java | 35 ++++++++++ .../flutter/commands/LongPressParameter.java | 33 +++++++++ .../flutter/commands/ScrollParameter.java | 4 +- .../flutter/commands/WaitParameter.java | 4 +- .../flutter/ios/FlutterIOSDriver.java | 69 +++++++++++++++++++ ...pportsFlutterElementWaitTimeoutOption.java | 36 ++++++++++ ...portsFlutterServerLaunchTimeoutOption.java | 36 ++++++++++ .../SupportsFlutterSystemPortOption.java | 33 +++++++++ 17 files changed, 506 insertions(+), 39 deletions(-) create mode 100644 src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java create mode 100644 src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java create mode 100644 src/main/java/io/appium/java_client/flutter/SupportsGestureOnFlutterElements.java create mode 100644 src/main/java/io/appium/java_client/flutter/commands/DoubleClickParameter.java create mode 100644 src/main/java/io/appium/java_client/flutter/commands/DragAndDropParameter.java create mode 100644 src/main/java/io/appium/java_client/flutter/commands/LongPressParameter.java create mode 100644 src/main/java/io/appium/java_client/flutter/ios/FlutterIOSDriver.java create mode 100644 src/main/java/io/appium/java_client/flutter/options/SupportsFlutterElementWaitTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/flutter/options/SupportsFlutterServerLaunchTimeoutOption.java create mode 100644 src/main/java/io/appium/java_client/flutter/options/SupportsFlutterSystemPortOption.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 8cdab0ef7..93527e84a 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -27,6 +27,7 @@ env: IOS_DEVICE_NAME: iPhone 15 IOS_PLATFORM_VERSION: "17.5" FLUTTER_ANDROID_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/app-debug.apk" + FLUTTER_IOS_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/ios.zip" jobs: build: @@ -38,6 +39,10 @@ jobs: # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available platform: macos-14 e2e-tests: ios + - java: 17 + # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available + platform: macos-14 + e2e-tests: flutter-ios - java: 17 platform: ubuntu-latest e2e-tests: android @@ -71,19 +76,19 @@ jobs: - name: Build with Gradle run: | latest_snapshot=$(curl -sf https://oss.sonatype.org/content/repositories/snapshots/org/seleniumhq/selenium/selenium-api/ | \ - python -c "import sys,re; print(re.findall(r'\d+\.\d+\.\d+-SNAPSHOT', sys.stdin.read())[-1])") + python -c "import sys,re; print(re.findall(r'\d+\.\d+\.\d+-SNAPSHOT', sys.stdin.read())[-1])") echo ">>> $latest_snapshot" echo "latest_snapshot=$latest_snapshot" >> "$GITHUB_ENV" ./gradlew clean build -PisCI -Pselenium.version=$latest_snapshot - name: Install Node.js - if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-android' + if: ${{ matrix.e2e-tests }} uses: actions/setup-node@v4 with: node-version: 'lts/*' - name: Install Appium - if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-android' + if: ${{ matrix.e2e-tests }} run: npm install --location=global appium - name: Install UIA2 driver @@ -91,7 +96,7 @@ jobs: run: appium driver install uiautomator2 - name: Install Flutter Integration driver - if: matrix.e2e-tests == 'flutter-android' + if: matrix.e2e-tests == 'flutter-android' || matrix.e2e-tests == 'flutter-ios' run: appium driver install appium-flutter-integration-driver --source npm - name: Run Android E2E tests @@ -117,22 +122,26 @@ jobs: target: ${{ env.ANDROID_EMU_TARGET }} - name: Select Xcode - if: matrix.e2e-tests == 'ios' + if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: "${{ env.XCODE_VERSION }}" - name: Prepare iOS simulator - if: matrix.e2e-tests == 'ios' + if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' uses: futureware-tech/simulator-action@v3 with: model: "${{ env.IOS_DEVICE_NAME }}" os_version: "${{ env.IOS_PLATFORM_VERSION }}" - name: Install XCUITest driver - if: matrix.e2e-tests == 'ios' + if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' run: appium driver install xcuitest - name: Prebuild XCUITest driver - if: matrix.e2e-tests == 'ios' + if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' run: appium driver run xcuitest build-wda - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' run: ./gradlew e2eIosTest -PisCI -Pselenium.version=$latest_snapshot + + - name: Run Flutter iOS E2E tests + if: matrix.e2e-tests == 'flutter-ios' + run: ./gradlew e2eFlutterTest -Pplatform="ios" -Pselenium.version=$latest_snapshot -PisCI -PflutterApp=${{ env.FLUTTER_IOS_APP }} diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java index e18112d4a..b2dc6f1eb 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java @@ -2,9 +2,12 @@ import io.appium.java_client.AppiumBy; import io.appium.java_client.android.options.UiAutomator2Options; +import io.appium.java_client.flutter.FlutterDriverOptions; +import io.appium.java_client.flutter.FlutterIntegrationTestDriver; import io.appium.java_client.flutter.android.FlutterAndroidDriver; import io.appium.java_client.flutter.commands.ScrollParameter; -import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.flutter.ios.FlutterIOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.junit.jupiter.api.AfterAll; @@ -12,10 +15,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.openqa.selenium.By; -import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.WebElement; import java.net.MalformedURLException; +import java.time.Duration; import java.util.Optional; class BaseFlutterTest { @@ -29,7 +32,7 @@ class BaseFlutterTest { protected static final int PORT = 4723; private static AppiumDriverLocalService service; - protected static FlutterAndroidDriver driver; + protected static FlutterIntegrationTestDriver driver; protected static final By LOGIN_BUTTON = AppiumBy.flutterText("Login"); /** @@ -45,35 +48,52 @@ public static void beforeClass() { } @BeforeEach - public void startSession() throws MalformedURLException { + void startSession() throws MalformedURLException { + FlutterDriverOptions flutterOptions = new FlutterDriverOptions() + .setFlutterServerLaunchTimeout(Duration.ofMinutes(2)) + .setFlutterSystemPort(9999) + .setFlutterElementWaitTimeout(Duration.ofSeconds(10)); if (IS_ANDROID) { - // TODO: update it with FlutterDriverOptions once implemented - UiAutomator2Options options = new UiAutomator2Options() - .setAutomationName(AutomationName.FLUTTER_INTEGRATION) - .setApp(System.getProperty("flutterApp")) - .eventTimings(); - driver = new FlutterAndroidDriver(service.getUrl(), options); + driver = new FlutterAndroidDriver(service.getUrl(), flutterOptions + .setUiAutomator2Options(new UiAutomator2Options() + .setApp(System.getProperty("flutterApp")) + .eventTimings()) + ); } else { - throw new InvalidArgumentException( - "Currently flutter driver implementation only supports android platform"); + String deviceName = System.getenv("IOS_DEVICE_NAME") != null + ? System.getenv("IOS_DEVICE_NAME") + : "iPhone 12"; + String platformVersion = System.getenv("IOS_PLATFORM_VERSION") != null + ? System.getenv("IOS_PLATFORM_VERSION") + : "14.5"; + driver = new FlutterIOSDriver(service.getUrl(), flutterOptions + .setXCUITestOptions(new XCUITestOptions() + .setApp(System.getProperty("flutterApp")) + .setDeviceName(deviceName) + .setPlatformVersion(platformVersion) + .setWdaLaunchTimeout(Duration.ofMinutes(4)) + .setSimulatorStartupTimeout(Duration.ofMinutes(5)) + .eventTimings() + ) + ); } } @AfterEach - public void stopSession() { + void stopSession() { if (driver != null) { driver.quit(); } } @AfterAll - public static void afterClass() { + static void afterClass() { if (service.isRunning()) { service.stop(); } } - public void openScreen(String screenTitle) { + void openScreen(String screenTitle) { ScrollParameter scrollOptions = new ScrollParameter( AppiumBy.flutterText(screenTitle), ScrollParameter.ScrollDirection.DOWN); WebElement element = driver.scrollTillVisible(scrollOptions); diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java index 80f32002d..efee1c74b 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java @@ -1,9 +1,13 @@ package io.appium.java_client.android; import io.appium.java_client.AppiumBy; +import io.appium.java_client.flutter.commands.DoubleClickParameter; +import io.appium.java_client.flutter.commands.DragAndDropParameter; +import io.appium.java_client.flutter.commands.LongPressParameter; import io.appium.java_client.flutter.commands.ScrollParameter; import io.appium.java_client.flutter.commands.WaitParameter; import org.junit.jupiter.api.Test; +import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -16,7 +20,7 @@ class CommandTest extends BaseFlutterTest { private static final AppiumBy.FlutterBy TOGGLE_BUTTON = AppiumBy.flutterKey("toggle_button"); @Test - public void testWaitCommand() { + void testWaitCommand() { WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); loginButton.click(); openScreen("Lazy Loading"); @@ -39,7 +43,7 @@ public void testWaitCommand() { } @Test - public void testScrollTillVisibleCommand() { + void testScrollTillVisibleCommand() { WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); loginButton.click(); openScreen("Vertical Swiping"); @@ -59,4 +63,56 @@ public void testScrollTillVisibleCommand() { assertFalse(Boolean.parseBoolean(lastElement.getAttribute("displayed"))); } + @Test + void testDoubleClickCommand() { + driver.findElement(BaseFlutterTest.LOGIN_BUTTON).click(); + openScreen("Double Tap"); + + WebElement doubleTapButton = driver + .findElement(AppiumBy.flutterKey("double_tap_button")) + .findElement(AppiumBy.flutterText("Double Tap")); + assertEquals("Double Tap", doubleTapButton.getText()); + + AppiumBy.FlutterBy okButton = AppiumBy.flutterText("Ok"); + AppiumBy.FlutterBy successPopup = AppiumBy.flutterTextContaining("Successful"); + + driver.performDoubleClick(new DoubleClickParameter().setElement(doubleTapButton)); + assertEquals(driver.findElement(successPopup).getText(), "Double Tap Successful"); + driver.findElement(okButton).click(); + + driver.performDoubleClick(new DoubleClickParameter() + .setElement(doubleTapButton) + .setOffset(new Point(10, 2)) + ); + assertEquals(driver.findElement(successPopup).getText(), "Double Tap Successful"); + driver.findElement(okButton).click(); + } + + @Test + void testLongPressCommand() { + driver.findElement(BaseFlutterTest.LOGIN_BUTTON).click(); + openScreen("Long Press"); + + AppiumBy.FlutterBy successPopup = AppiumBy.flutterText("It was a long press"); + WebElement longPressButton = driver + .findElement(AppiumBy.flutterKey("long_press_button")); + + driver.performLongPress(new LongPressParameter().setElement(longPressButton)); + assertEquals(driver.findElement(successPopup).getText(), "It was a long press"); + assertTrue(driver.findElement(successPopup).isDisplayed()); + } + + @Test + void testDragAndDropCommand() { + driver.findElement(BaseFlutterTest.LOGIN_BUTTON).click(); + openScreen("Drag & Drop"); + + driver.performDragAndDrop(new DragAndDropParameter( + driver.findElement(AppiumBy.flutterKey("drag_me")), + driver.findElement(AppiumBy.flutterKey("drop_zone")) + )); + assertTrue(driver.findElement(AppiumBy.flutterText("The box is dropped")).isDisplayed()); + assertEquals(driver.findElement(AppiumBy.flutterText("The box is dropped")).getText(), "The box is dropped"); + + } } diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java b/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java index dc2361869..e8f78e414 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java @@ -10,7 +10,7 @@ class FinderTests extends BaseFlutterTest { @Test - public void testFlutterByKey() { + void testFlutterByKey() { WebElement userNameField = driver.findElement(AppiumBy.flutterKey("username_text_field")); assertEquals("admin", userNameField.getText()); userNameField.clear(); @@ -19,13 +19,13 @@ public void testFlutterByKey() { } @Test - public void testFlutterByType() { + void testFlutterByType() { WebElement loginButton = driver.findElement(AppiumBy.flutterType("ElevatedButton")); assertEquals(loginButton.findElement(AppiumBy.flutterType("Text")).getText(), "Login"); } @Test - public void testFlutterText() { + void testFlutterText() { WebElement loginButton = driver.findElement(AppiumBy.flutterText("Login")); assertEquals(loginButton.getText(), "Login"); loginButton.click(); @@ -34,7 +34,7 @@ public void testFlutterText() { } @Test - public void testFlutterTextContaining() { + void testFlutterTextContaining() { WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); loginButton.click(); assertEquals(driver.findElement(AppiumBy.flutterTextContaining("Vertical")).getText(), @@ -42,7 +42,7 @@ public void testFlutterTextContaining() { } @Test - public void testFlutterSemanticsLabel() { + void testFlutterSemanticsLabel() { WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); loginButton.click(); openScreen("Lazy Loading"); diff --git a/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java b/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java new file mode 100644 index 000000000..e50b5d134 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java @@ -0,0 +1,51 @@ +package io.appium.java_client.flutter; + +import io.appium.java_client.android.options.UiAutomator2Options; +import io.appium.java_client.flutter.options.SupportsFlutterElementWaitTimeoutOption; +import io.appium.java_client.flutter.options.SupportsFlutterServerLaunchTimeoutOption; +import io.appium.java_client.flutter.options.SupportsFlutterSystemPortOption; +import io.appium.java_client.ios.options.XCUITestOptions; +import io.appium.java_client.remote.AutomationName; +import io.appium.java_client.remote.options.BaseOptions; +import org.openqa.selenium.Capabilities; + +import java.util.Map; + +/** + * https://github.com/AppiumTestDistribution/appium-flutter-integration-driver#capabilities-for-appium-flutter-integration-driver + */ +public class FlutterDriverOptions extends BaseOptions implements + SupportsFlutterSystemPortOption, + SupportsFlutterServerLaunchTimeoutOption, + SupportsFlutterElementWaitTimeoutOption { + + public FlutterDriverOptions() { + setDefaultOptions(); + } + + public FlutterDriverOptions(Capabilities source) { + super(source); + setDefaultOptions(); + } + + public FlutterDriverOptions(Map source) { + super(source); + setDefaultOptions(); + } + + public FlutterDriverOptions setUiAutomator2Options(UiAutomator2Options uiAutomator2Options) { + return setDefaultOptions(merge(uiAutomator2Options)); + } + + public FlutterDriverOptions setXCUITestOptions(XCUITestOptions xcuiTestOptions) { + return setDefaultOptions(merge(xcuiTestOptions)); + } + + private void setDefaultOptions() { + setDefaultOptions(this); + } + + private FlutterDriverOptions setDefaultOptions(FlutterDriverOptions flutterDriverOptions) { + return flutterDriverOptions.setAutomationName(AutomationName.FLUTTER_INTEGRATION); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java b/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java new file mode 100644 index 000000000..dce74507c --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java @@ -0,0 +1,23 @@ +package io.appium.java_client.flutter; + +import org.openqa.selenium.WebDriver; + +/** + * The {@code FlutterDriver} interface represents a driver that controls interactions with + * Flutter applications, extending WebDriver and providing additional capabilities for + * interacting with Flutter-specific elements and behaviors. + * + *

    This interface serves as a common entity for drivers that support Flutter applications + * on different platforms, such as Android and iOS.

    + * + * @see WebDriver + * @see SupportsGestureOnFlutterElements + * @see SupportsScrollingOfFlutterElements + * @see SupportsWaitingForFlutterElements + */ +public interface FlutterIntegrationTestDriver extends + WebDriver, + SupportsGestureOnFlutterElements, + SupportsScrollingOfFlutterElements, + SupportsWaitingForFlutterElements { +} diff --git a/src/main/java/io/appium/java_client/flutter/SupportsGestureOnFlutterElements.java b/src/main/java/io/appium/java_client/flutter/SupportsGestureOnFlutterElements.java new file mode 100644 index 000000000..7e80e8a97 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/SupportsGestureOnFlutterElements.java @@ -0,0 +1,35 @@ +package io.appium.java_client.flutter; + +import io.appium.java_client.flutter.commands.DoubleClickParameter; +import io.appium.java_client.flutter.commands.DragAndDropParameter; +import io.appium.java_client.flutter.commands.LongPressParameter; + +public interface SupportsGestureOnFlutterElements extends CanExecuteFlutterScripts { + + /** + * Performs a double click action on an element. + * + * @param parameter The parameters for double-clicking, specifying element details. + */ + default void performDoubleClick(DoubleClickParameter parameter) { + executeFlutterCommand("doubleClick", parameter); + } + + /** + * Performs a long press action on an element. + * + * @param parameter The parameters for long pressing, specifying element details. + */ + default void performLongPress(LongPressParameter parameter) { + executeFlutterCommand("longPress", parameter); + } + + /** + * Performs a drag-and-drop action between two elements. + * + * @param parameter The parameters for drag-and-drop, specifying source and target elements. + */ + default void performDragAndDrop(DragAndDropParameter parameter) { + executeFlutterCommand("dragAndDrop", parameter); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java b/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java index f7be154ff..8bbf45cbf 100644 --- a/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java +++ b/src/main/java/io/appium/java_client/flutter/android/FlutterAndroidDriver.java @@ -2,8 +2,7 @@ import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.flutter.SupportsScrollingOfFlutterElements; -import io.appium.java_client.flutter.SupportsWaitingForFlutterElements; +import io.appium.java_client.flutter.FlutterIntegrationTestDriver; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; @@ -16,9 +15,7 @@ /** * Custom AndroidDriver implementation with additional Flutter-specific capabilities. */ -public class FlutterAndroidDriver extends AndroidDriver implements - SupportsWaitingForFlutterElements, - SupportsScrollingOfFlutterElements { +public class FlutterAndroidDriver extends AndroidDriver implements FlutterIntegrationTestDriver { public FlutterAndroidDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, capabilities); diff --git a/src/main/java/io/appium/java_client/flutter/commands/DoubleClickParameter.java b/src/main/java/io/appium/java_client/flutter/commands/DoubleClickParameter.java new file mode 100644 index 000000000..859f26057 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/commands/DoubleClickParameter.java @@ -0,0 +1,34 @@ +package io.appium.java_client.flutter.commands; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.openqa.selenium.Point; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.Require; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Accessors(chain = true) +@Setter +@Getter +public class DoubleClickParameter extends FlutterCommandParameter { + private WebElement element; + private Point offset; + + + @Override + public Map toJson() { + Require.precondition(element != null || offset != null, + "Must supply a valid element or offset to perform flutter gesture event"); + + Map params = new HashMap<>(); + Optional.ofNullable(element).ifPresent(element -> params.put("origin", element)); + Optional.ofNullable(offset).ifPresent(offset -> + params.put("offset", Map.of("x", offset.getX(), "y", offset.getY()))); + return Collections.unmodifiableMap(params); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/commands/DragAndDropParameter.java b/src/main/java/io/appium/java_client/flutter/commands/DragAndDropParameter.java new file mode 100644 index 000000000..14bc04cbf --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/commands/DragAndDropParameter.java @@ -0,0 +1,35 @@ +package io.appium.java_client.flutter.commands; + +import lombok.Getter; +import lombok.experimental.Accessors; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.Require; + +import java.util.Map; + +@Accessors(chain = true) +@Getter +public class DragAndDropParameter extends FlutterCommandParameter { + private final WebElement source; + private final WebElement target; + + /** + * Constructs a new instance of {@code DragAndDropParameter} with the given source and target {@link WebElement}s. + * Throws an {@link IllegalArgumentException} if either {@code source} or {@code target} is {@code null}. + * + * @param source The source {@link WebElement} from which the drag operation starts. + * @param target The target {@link WebElement} where the drag operation ends. + * @throws IllegalArgumentException if {@code source} or {@code target} is {@code null}. + */ + public DragAndDropParameter(WebElement source, WebElement target) { + Require.precondition(source != null && target != null, + "Must supply valid source and target element to perform drag and drop event"); + this.source = source; + this.target = target; + } + + @Override + public Map toJson() { + return Map.of("source", source, "target", target); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/commands/LongPressParameter.java b/src/main/java/io/appium/java_client/flutter/commands/LongPressParameter.java new file mode 100644 index 000000000..36f80772d --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/commands/LongPressParameter.java @@ -0,0 +1,33 @@ +package io.appium.java_client.flutter.commands; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.openqa.selenium.Point; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.Require; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Accessors(chain = true) +@Setter +@Getter +public class LongPressParameter extends FlutterCommandParameter { + private WebElement element; + private Point offset; + + @Override + public Map toJson() { + Require.precondition(element != null || offset != null, + "Must supply a valid element or offset to perform flutter gesture event"); + + Map params = new HashMap<>(); + Optional.ofNullable(element).ifPresent(element -> params.put("origin", element)); + Optional.ofNullable(offset).ifPresent(offset -> + params.put("offset", Map.of("x", offset.getX(), "y", offset.getY()))); + return Collections.unmodifiableMap(params); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java b/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java index 695cb060d..773ece810 100644 --- a/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java +++ b/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java @@ -1,11 +1,11 @@ package io.appium.java_client.flutter.commands; -import com.google.common.base.Preconditions; import io.appium.java_client.AppiumBy; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.Require; import java.time.Duration; import java.util.Collections; @@ -45,7 +45,7 @@ public ScrollParameter(AppiumBy.FlutterBy scrollTo) { * @throws IllegalArgumentException if scrollTo is null */ public ScrollParameter(AppiumBy.FlutterBy scrollTo, ScrollDirection scrollDirection) { - Preconditions.checkArgument(scrollTo != null, "Must supply a valid locator for scrollTo"); + Require.precondition(scrollTo != null, "Must supply a valid locator for scrollTo"); this.scrollTo = scrollTo; this.scrollDirection = scrollDirection; } diff --git a/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java b/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java index 89e0a19cf..d9f057032 100644 --- a/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java +++ b/src/main/java/io/appium/java_client/flutter/commands/WaitParameter.java @@ -1,11 +1,11 @@ package io.appium.java_client.flutter.commands; -import com.google.common.base.Preconditions; import io.appium.java_client.AppiumBy; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.Require; import java.time.Duration; import java.util.Collections; @@ -23,7 +23,7 @@ public class WaitParameter extends FlutterCommandParameter { @Override public Map toJson() { - Preconditions.checkArgument(element != null || locator != null, + Require.precondition(element != null || locator != null, "Must supply a valid element or locator to wait for"); Map params = new HashMap<>(); Optional.ofNullable(element) diff --git a/src/main/java/io/appium/java_client/flutter/ios/FlutterIOSDriver.java b/src/main/java/io/appium/java_client/flutter/ios/FlutterIOSDriver.java new file mode 100644 index 000000000..2d8c9c991 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/ios/FlutterIOSDriver.java @@ -0,0 +1,69 @@ +package io.appium.java_client.flutter.ios; + +import io.appium.java_client.AppiumClientConfig; +import io.appium.java_client.flutter.FlutterIntegrationTestDriver; +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.remote.HttpCommandExecutor; +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.HttpClient; + +import java.net.URL; + +/** + * Custom IOSDriver implementation with additional Flutter-specific capabilities. + */ +public class FlutterIOSDriver extends IOSDriver implements FlutterIntegrationTestDriver { + + public FlutterIOSDriver(HttpCommandExecutor executor, Capabilities capabilities) { + super(executor, capabilities); + } + + public FlutterIOSDriver(URL remoteAddress, Capabilities capabilities) { + super(remoteAddress, capabilities); + } + + public FlutterIOSDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(remoteAddress, httpClientFactory, capabilities); + } + + public FlutterIOSDriver(AppiumDriverLocalService service, Capabilities capabilities) { + super(service, capabilities); + } + + public FlutterIOSDriver( + AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(service, httpClientFactory, capabilities); + } + + public FlutterIOSDriver(AppiumServiceBuilder builder, Capabilities capabilities) { + super(builder, capabilities); + } + + public FlutterIOSDriver( + AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(builder, httpClientFactory, capabilities); + } + + public FlutterIOSDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities) { + super(httpClientFactory, capabilities); + } + + public FlutterIOSDriver(ClientConfig clientConfig, Capabilities capabilities) { + super(clientConfig, capabilities); + } + + public FlutterIOSDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) { + super(appiumClientConfig, capabilities); + } + + public FlutterIOSDriver(URL remoteSessionAddress) { + super(remoteSessionAddress); + } + + public FlutterIOSDriver(Capabilities capabilities) { + super(capabilities); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterElementWaitTimeoutOption.java b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterElementWaitTimeoutOption.java new file mode 100644 index 000000000..794c955d4 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterElementWaitTimeoutOption.java @@ -0,0 +1,36 @@ +package io.appium.java_client.flutter.options; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsFlutterElementWaitTimeoutOption> extends + Capabilities, CanSetCapability { + String FLUTTER_ELEMENT_WAIT_TIMEOUT_OPTION = "flutterElementWaitTimeout"; + + /** + * Sets the Flutter element wait timeout. + * Defaults to 5 seconds. + * + * @param timeout The duration to wait for Flutter elements during findElement method + * @return self instance for chaining. + */ + default T setFlutterElementWaitTimeout(Duration timeout) { + return amend(FLUTTER_ELEMENT_WAIT_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Retrieves the current Flutter element wait timeout if set. + * + * @return An {@link Optional} containing the duration of the Flutter element wait timeout, or empty if not set. + */ + default Optional getFlutterElementWaitTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(FLUTTER_ELEMENT_WAIT_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterServerLaunchTimeoutOption.java b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterServerLaunchTimeoutOption.java new file mode 100644 index 000000000..52b51a8eb --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterServerLaunchTimeoutOption.java @@ -0,0 +1,36 @@ +package io.appium.java_client.flutter.options; + +import io.appium.java_client.internal.CapabilityHelpers; +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.time.Duration; +import java.util.Optional; + +public interface SupportsFlutterServerLaunchTimeoutOption> extends + Capabilities, CanSetCapability { + String FLUTTER_SERVER_LAUNCH_TIMEOUT_OPTION = "flutterServerLaunchTimeout"; + + /** + * Timeout to wait for FlutterServer to be pingable, + * e.g. finishes building. Defaults to 60000ms. + * + * @param timeout Timeout to wait until FlutterServer is listening. + * @return self instance for chaining. + */ + default T setFlutterServerLaunchTimeout(Duration timeout) { + return amend(FLUTTER_SERVER_LAUNCH_TIMEOUT_OPTION, timeout.toMillis()); + } + + /** + * Get the maximum timeout to wait until FlutterServer is listening. + * + * @return Timeout value. + */ + default Optional getFlutterServerLaunchTimeout() { + return Optional.ofNullable( + CapabilityHelpers.toDuration(getCapability(FLUTTER_SERVER_LAUNCH_TIMEOUT_OPTION)) + ); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterSystemPortOption.java b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterSystemPortOption.java new file mode 100644 index 000000000..3f25ccec3 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterSystemPortOption.java @@ -0,0 +1,33 @@ +package io.appium.java_client.flutter.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toInteger; + +public interface SupportsFlutterSystemPortOption> extends + Capabilities, CanSetCapability { + String FLUTTER_SYSTEM_PORT_OPTION = "flutterSystemPort"; + + /** + * Set the port where Flutter server starts. + * + * @param flutterSystemPort is the port number + * @return self instance for chaining. + */ + default T setFlutterSystemPort(int flutterSystemPort) { + return amend(FLUTTER_SYSTEM_PORT_OPTION, flutterSystemPort); + } + + /** + * Get the number of the port Flutter server starts on the system. + * + * @return Port number + */ + default Optional getFlutterSystemPort() { + return Optional.ofNullable(toInteger(getCapability(FLUTTER_SYSTEM_PORT_OPTION))); + } +} From 2caff36b16c6c39b19e44646ac7817d07dfc1b77 Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Thu, 25 Jul 2024 12:33:26 +0530 Subject: [PATCH 373/501] feat: add flutter driver commands to support camera mocking (#2207) * feat: add flutter driver commands to support camera mocking --- .../java_client/android/BaseFlutterTest.java | 10 +++- .../java_client/android/CommandTest.java | 24 +++++++++ src/e2eFlutterTest/resources/second_qr.png | Bin 0 -> 132652 bytes src/e2eFlutterTest/resources/success_qr.png | Bin 0 -> 32757 bytes .../flutter/CanExecuteFlutterScripts.java | 15 +++++- .../flutter/FlutterDriverOptions.java | 4 +- .../flutter/FlutterIntegrationTestDriver.java | 3 +- .../flutter/SupportsFlutterCameraMocking.java | 47 ++++++++++++++++++ .../SupportsFlutterEnableMockCamera.java | 33 ++++++++++++ 9 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 src/e2eFlutterTest/resources/second_qr.png create mode 100644 src/e2eFlutterTest/resources/success_qr.png create mode 100644 src/main/java/io/appium/java_client/flutter/SupportsFlutterCameraMocking.java create mode 100644 src/main/java/io/appium/java_client/flutter/options/SupportsFlutterEnableMockCamera.java diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java index b2dc6f1eb..a0dd5ccaa 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java @@ -10,6 +10,7 @@ import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; +import io.appium.java_client.service.local.flags.GeneralServerFlag; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -43,6 +44,10 @@ public static void beforeClass() { service = new AppiumServiceBuilder() .withIPAddress("127.0.0.1") .usingPort(PORT) + // Flutter driver mocking command requires adb_shell permission to set certain permissions + // to the AUT. This can be removed once the server logic is updated to use a different approach + // for setting the permission + .withArgument(GeneralServerFlag.ALLOW_INSECURE, "adb_shell") .build(); service.start(); } @@ -52,11 +57,14 @@ void startSession() throws MalformedURLException { FlutterDriverOptions flutterOptions = new FlutterDriverOptions() .setFlutterServerLaunchTimeout(Duration.ofMinutes(2)) .setFlutterSystemPort(9999) - .setFlutterElementWaitTimeout(Duration.ofSeconds(10)); + .setFlutterElementWaitTimeout(Duration.ofSeconds(10)) + .setFlutterEnableMockCamera(true); + if (IS_ANDROID) { driver = new FlutterAndroidDriver(service.getUrl(), flutterOptions .setUiAutomator2Options(new UiAutomator2Options() .setApp(System.getProperty("flutterApp")) + .setAutoGrantPermissions(true) .eventTimings()) ); } else { diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java index efee1c74b..d8f587e52 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java @@ -1,6 +1,7 @@ package io.appium.java_client.android; import io.appium.java_client.AppiumBy; +import io.appium.java_client.TestUtils; import io.appium.java_client.flutter.commands.DoubleClickParameter; import io.appium.java_client.flutter.commands.DragAndDropParameter; import io.appium.java_client.flutter.commands.LongPressParameter; @@ -10,6 +11,8 @@ import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -115,4 +118,25 @@ void testDragAndDropCommand() { assertEquals(driver.findElement(AppiumBy.flutterText("The box is dropped")).getText(), "The box is dropped"); } + + @Test + void testCameraMocking() throws IOException { + driver.findElement(BaseFlutterTest.LOGIN_BUTTON).click(); + openScreen("Image Picker"); + + final String successQr = driver.injectMockImage( + TestUtils.resourcePathToAbsolutePath("success_qr.png").toFile()); + driver.injectMockImage( + TestUtils.resourcePathToAbsolutePath("second_qr.png").toFile()); + + driver.findElement(AppiumBy.flutterKey("capture_image")).click(); + driver.findElement(AppiumBy.flutterText("PICK")).click(); + assertTrue(driver.findElement(AppiumBy.flutterText("SecondInjectedImage")).isDisplayed()); + + driver.activateInjectedImage(successQr); + + driver.findElement(AppiumBy.flutterKey("capture_image")).click(); + driver.findElement(AppiumBy.flutterText("PICK")).click(); + assertTrue(driver.findElement(AppiumBy.flutterText("Success!")).isDisplayed()); + } } diff --git a/src/e2eFlutterTest/resources/second_qr.png b/src/e2eFlutterTest/resources/second_qr.png new file mode 100644 index 0000000000000000000000000000000000000000..355548c30e2066dccf7f2cbf5e990eff59801677 GIT binary patch literal 132652 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 e|N7x2c$sT16K9I5mue}_+y**5hr(AVh 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 S^YP!2q$&#P^0n{GLjDhG!;-iF literal 0 HcmV?d00001 diff --git a/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java b/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java index f8eaf3af4..e844388be 100644 --- a/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java +++ b/src/main/java/io/appium/java_client/flutter/CanExecuteFlutterScripts.java @@ -3,6 +3,8 @@ import io.appium.java_client.flutter.commands.FlutterCommandParameter; import org.openqa.selenium.JavascriptExecutor; +import java.util.Map; + public interface CanExecuteFlutterScripts extends JavascriptExecutor { /** @@ -13,8 +15,19 @@ public interface CanExecuteFlutterScripts extends JavascriptExecutor { * @return The result of executing the script. */ default Object executeFlutterCommand(String scriptName, FlutterCommandParameter parameter) { + return executeFlutterCommand(scriptName, parameter.toJson()); + } + + /** + * Executes a Flutter-specific script using JavascriptExecutor. + * + * @param scriptName The name of the Flutter script to execute. + * @param args The args for the Flutter command in Map format. + * @return The result of executing the script. + */ + default Object executeFlutterCommand(String scriptName, Map args) { String commandName = String.format("flutter: %s", scriptName); - return executeScript(commandName, parameter.toJson()); + return executeScript(commandName, args); } } diff --git a/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java b/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java index e50b5d134..6a00c0510 100644 --- a/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java +++ b/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java @@ -2,6 +2,7 @@ import io.appium.java_client.android.options.UiAutomator2Options; import io.appium.java_client.flutter.options.SupportsFlutterElementWaitTimeoutOption; +import io.appium.java_client.flutter.options.SupportsFlutterEnableMockCamera; import io.appium.java_client.flutter.options.SupportsFlutterServerLaunchTimeoutOption; import io.appium.java_client.flutter.options.SupportsFlutterSystemPortOption; import io.appium.java_client.ios.options.XCUITestOptions; @@ -17,7 +18,8 @@ public class FlutterDriverOptions extends BaseOptions implements SupportsFlutterSystemPortOption, SupportsFlutterServerLaunchTimeoutOption, - SupportsFlutterElementWaitTimeoutOption { + SupportsFlutterElementWaitTimeoutOption, + SupportsFlutterEnableMockCamera { public FlutterDriverOptions() { setDefaultOptions(); diff --git a/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java b/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java index dce74507c..4eb74e82a 100644 --- a/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java +++ b/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java @@ -19,5 +19,6 @@ public interface FlutterIntegrationTestDriver extends WebDriver, SupportsGestureOnFlutterElements, SupportsScrollingOfFlutterElements, - SupportsWaitingForFlutterElements { + SupportsWaitingForFlutterElements, + SupportsFlutterCameraMocking { } diff --git a/src/main/java/io/appium/java_client/flutter/SupportsFlutterCameraMocking.java b/src/main/java/io/appium/java_client/flutter/SupportsFlutterCameraMocking.java new file mode 100644 index 000000000..6ffad1089 --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/SupportsFlutterCameraMocking.java @@ -0,0 +1,47 @@ +package io.appium.java_client.flutter; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Base64; +import java.util.Map; + +/** + * This interface extends {@link CanExecuteFlutterScripts} and provides methods + * to support mocking of camera inputs in Flutter applications. + */ +public interface SupportsFlutterCameraMocking extends CanExecuteFlutterScripts { + + /** + * Injects a mock image into the Flutter application using the provided file. + * + * @param image the image file to be mocked (must be in PNG format) + * @return an {@code String} representing a unique id of the injected image + * @throws IOException if an I/O error occurs while reading the image file + */ + default String injectMockImage(File image) throws IOException { + String base64EncodedImage = Base64.getEncoder().encodeToString(Files.readAllBytes(image.toPath())); + return injectMockImage(base64EncodedImage); + } + + /** + * Injects a mock image into the Flutter application using the provided Base64-encoded image string. + * + * @param base64Image the Base64-encoded string representation of the image (must be in PNG format) + * @return an {@code String} representing the result of the injection operation + */ + default String injectMockImage(String base64Image) { + return (String) executeFlutterCommand("injectImage", Map.of( + "base64Image", base64Image + )); + } + + /** + * Activates the injected image identified by the specified image ID in the Flutter application. + * + * @param imageId the ID of the injected image to activate + */ + default void activateInjectedImage(String imageId) { + executeFlutterCommand("activateInjectedImage", Map.of("imageId", imageId)); + } +} diff --git a/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterEnableMockCamera.java b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterEnableMockCamera.java new file mode 100644 index 000000000..baffaf96d --- /dev/null +++ b/src/main/java/io/appium/java_client/flutter/options/SupportsFlutterEnableMockCamera.java @@ -0,0 +1,33 @@ +package io.appium.java_client.flutter.options; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsFlutterEnableMockCamera> extends + Capabilities, CanSetCapability { + String FLUTTER_ENABLE_MOCK_CAMERA_OPTION = "flutterEnableMockCamera"; + + /** + * Sets the 'flutterEnableMockCamera' capability to the specified value. + * + * @param value the value to set for the 'flutterEnableMockCamera' capability + * @return an instance of type {@code T} with the updated capability set + */ + default T setFlutterEnableMockCamera(boolean value) { + return amend(FLUTTER_ENABLE_MOCK_CAMERA_OPTION, value); + } + + /** + * Retrieves the current value of the 'flutterEnableMockCamera' capability, if available. + * + * @return an {@code Optional} containing the current value of the capability, + */ + default Optional doesFlutterEnableMockCamera() { + return Optional.ofNullable(toSafeBoolean(getCapability(FLUTTER_ENABLE_MOCK_CAMERA_OPTION))); + } +} From 8c750162ef4a8d3e3e4421b20513f870007266d7 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Fri, 26 Jul 2024 14:04:31 +0800 Subject: [PATCH 374/501] release: v9.3.0 (#2208) --- CHANGELOG.md | 22 ++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44838a04f..09c42fd19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +_9.3.0_ +- **[ENHANCEMENTS]** + - Add support for FlutterIOSDriver. [#2206](https://github.com/appium/java-client/pull/2206) + - add support for FlutterAndroidDriver. [#2203](https://github.com/appium/java-client/pull/2203) + - Add locator types supported by flutter integration driver. [#2201](https://github.com/appium/java-client/pull/2201) + - add flutter driver commands to support camera mocking. [#2207](https://github.com/appium/java-client/pull/2207) + - Add ability to use secure WebSocket to listen Logcat messages. [#2182](https://github.com/appium/java-client/pull/2182) + - Add mobile: replacements to clipboard API wrappers. [#2188](https://github.com/appium/java-client/pull/2188) +- **[DEPRECATION]** + - Deprecate obsolete TouchAction helpers. [#2199](https://github.com/appium/java-client/pull/2199) +- **[REFACTOR]** + - Bump iOS version in CI. [#2167](https://github.com/appium/java-client/pull/2167) +- **[DOCUMENTATION]** + - README updates. [#2193](https://github.com/appium/java-client/pull/2193) +- **[DEPENDENCY UPDATES]** + - `org.junit.jupiter:junit-jupiter` was updated to 5.10.3. + - `org.projectlombok:lombok` was updated to 1.18.34. + - `io.github.bonigarcia:webdrivermanager` was updated to 5.9.1. + - `org.owasp.dependencycheck` was updated to 10.0.3. + - `org.apache.commons:commons-lang3` was updated to 3.15.0. + _9.2.3_ - **[BUG FIX]** - Properly represent `FeaturesMatchingResult` model if `multiple` option is enabled [#2170](https://github.com/appium/java-client/pull/2170) diff --git a/gradle.properties b/gradle.properties index 44154a53b..10017f9d5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.19.0 # Please increment the value in a release -appiumClient.version=9.2.3 +appiumClient.version=9.3.0 From 567deee4ae069965e7da4f4e9bd1a05a09dfcfb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:00:22 +0300 Subject: [PATCH 375/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2209) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.9.1 to 5.9.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.9.1...webdrivermanager-5.9.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b65d41661..ec4e247a6 100644 --- a/build.gradle +++ b/build.gradle @@ -213,7 +213,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:5.9.1') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.2') { exclude group: 'org.seleniumhq.selenium' } } @@ -257,7 +257,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:5.9.1') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.2') { exclude group: 'org.seleniumhq.selenium' } } From a64ee0dc68d1e224aafae185c206cb799ca24a0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:55:55 +0300 Subject: [PATCH 376/501] build(deps): Bump org.hamcrest:hamcrest from 2.2 to 3.0 (#2212) Bumps [org.hamcrest:hamcrest](https://github.com/hamcrest/JavaHamcrest) from 2.2 to 3.0. - [Release notes](https://github.com/hamcrest/JavaHamcrest/releases) - [Changelog](https://github.com/hamcrest/JavaHamcrest/blob/master/CHANGES.md) - [Commits](https://github.com/hamcrest/JavaHamcrest/compare/v2.2...v3.0) --- updated-dependencies: - dependency-name: org.hamcrest:hamcrest dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ec4e247a6..11b7edff3 100644 --- a/build.gradle +++ b/build.gradle @@ -197,7 +197,7 @@ testing { dependencies { implementation 'org.junit.jupiter:junit-jupiter:5.10.3' runtimeOnly 'org.junit.platform:junit-platform-launcher' - implementation 'org.hamcrest:hamcrest:2.2' + implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" } targets.configureEach { From 76ddf4388414aabba94496f2c84901e189c1d135 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:16:26 +0300 Subject: [PATCH 377/501] build(deps): Bump gradle/actions from 3 to 4 (#2213) Bumps [gradle/actions](https://github.com/gradle/actions) from 3 to 4. - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/v3...v4) --- updated-dependencies: - dependency-name: gradle/actions dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 72a15d717..c2f33a25a 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -24,4 +24,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/actions/wrapper-validation@v3 + - uses: gradle/actions/wrapper-validation@v4 From f4496a990dfdc010ff7c8b91a335893277007457 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 5 Aug 2024 17:22:46 +0300 Subject: [PATCH 378/501] ci: Use the `setup-gradle` action (#2214) - https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#why-use-the-setup-gradle-action - https://github.com/gradle/actions/releases/tag/v4.0.0-rc.1: wrapper validation is now enabled in the setup-gradle action by default, removing the need to use a separate workflow file with the `gradle/actions/wrapper-validation` action - https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#incompatibility-with-other-caching-mechanisms --- .../workflows/gradle-wrapper-validation.yml | 27 ------------------- .github/workflows/gradle.yml | 4 ++- .github/workflows/publish.yml | 7 +++-- 3 files changed, 8 insertions(+), 30 deletions(-) delete mode 100644 .github/workflows/gradle-wrapper-validation.yml diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml deleted file mode 100644 index c2f33a25a..000000000 --- a/.github/workflows/gradle-wrapper-validation.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: "Validate Gradle Wrapper" - -on: - push: - branches: - - master - paths: - - 'gradlew' - - 'gradlew.bat' - - 'gradle/wrapper/**' - - '.github/workflows/gradle-wrapper-validation.yml' - pull_request: - branches: - - master - paths: - - 'gradlew' - - 'gradlew.bat' - - 'gradle/wrapper/**' - - '.github/workflows/gradle-wrapper-validation.yml' - -jobs: - validation: - name: "Validation" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: gradle/actions/wrapper-validation@v4 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 93527e84a..e960bf822 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -71,7 +71,9 @@ jobs: with: distribution: 'zulu' java-version: ${{ matrix.java }} - cache: 'gradle' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build with Gradle run: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 96fcfce38..6b2a253c2 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,11 +12,14 @@ jobs: with: java-version: '11' distribution: 'zulu' - cache: 'gradle' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Publish package env: MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} PGP_SECRET: ${{ secrets.SIGNING_KEY }} PGP_PASSPHRASE: ${{ secrets.SIGNING_PASSWORD }} - run: ./gradlew publish \ No newline at end of file + run: ./gradlew publish From 7e23de25ef8a4145e3f0cbbc82eacca28b6c3496 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 5 Aug 2024 18:46:44 +0300 Subject: [PATCH 379/501] build: bump Gradle from `8.7` to `8.9` (#2215) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 +++++-- gradlew.bat | 2 ++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 11b7edff3..7955434a5 100644 --- a/build.gradle +++ b/build.gradle @@ -179,7 +179,7 @@ signing { } wrapper { - gradleVersion = '8.7' + gradleVersion = '8.9' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch delta 8703 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 Ojj7^59?Sdh$^Qpp*~F>< delta 8662 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e7646dead..dedd5d1e6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e46..9b42019c7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## From 1d4c1d0dbdcf11e92587987623f08fe1a520e4b9 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 5 Aug 2024 19:22:41 +0300 Subject: [PATCH 380/501] docs: Add recent clients versions to the compatibility matrix (#2216) --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index edbb5cc83..91e61c688 100644 --- a/README.md +++ b/README.md @@ -93,16 +93,16 @@ dependencies { ``` ### Compatibility Matrix - Appium Java Client | Selenium client --------------------------------------------------------------------------------------------|----------------- - `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0` - `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` - `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` - N/A | `4.14.0` - `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` - `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` - `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` - `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` + Appium Java Client | Selenium client +----------------------------------------------------------------------------------------------------|----------------- + `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0` + `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` + `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` + N/A | `4.14.0` + `8.5.0`, `8.5.1`, `8.6.0` | `4.9.1`, `4.10.0`, `4.11.0`, `4.12.0`, `4.12.1` (known issue: appium/java-client#2004), `4.13.0` + `8.4.0` | `4.8.2`, `4.8.3`, `4.9.0` + `8.3.0` | `4.7.0`, `4.7.1`, `4.7.2`, `4.8.0`, `4.8.1` + `8.2.1` | `4.5.0`, `4.5.1`, `4.5.2`, `4.5.3`, `4.6.0` #### Why is it so complicated? From 9a49ef8cdef2625c071a927b8d5aaac8287010d2 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 5 Aug 2024 19:23:21 +0300 Subject: [PATCH 381/501] build(deps): Bump JaCoCo from `0.8.11` to `0.8.12` (#2217) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7955434a5..bd7225b23 100644 --- a/build.gradle +++ b/build.gradle @@ -74,7 +74,7 @@ dependencyCheck { } jacoco { - toolVersion = '0.8.11' + toolVersion = '0.8.12' } tasks.withType(JacocoReport).configureEach { From 546d6cc2588859a83eb10836281ceadcc8701e63 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 5 Aug 2024 20:03:45 +0300 Subject: [PATCH 382/501] build(deps): Bump Checkstyle from `10.14.2` to `10.17.0` (#2218) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bd7225b23..9c3f23dca 100644 --- a/build.gradle +++ b/build.gradle @@ -90,7 +90,7 @@ jacocoTestReport.dependsOn test apply plugin: 'checkstyle' checkstyle { - toolVersion = '10.14.2' + toolVersion = '10.17.0' configFile = configDirectory.file('appium-style.xml').get().getAsFile() showViolations = true ignoreFailures = false From 62303cec207a4a7d75e026d329032704d47e3750 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:48:01 +0300 Subject: [PATCH 383/501] build(deps): Bump org.apache.commons:commons-lang3 from 3.15.0 to 3.16.0 (#2220) Bumps org.apache.commons:commons-lang3 from 3.15.0 to 3.16.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9c3f23dca..6197189ef 100644 --- a/build.gradle +++ b/build.gradle @@ -233,7 +233,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('org.apache.commons:commons-lang3:3.15.0') + implementation('org.apache.commons:commons-lang3:3.16.0') } targets.configureEach { From bbb38ec04e3ddbe86b1bc4ec81aba1a6da4bef59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 17:16:41 +0300 Subject: [PATCH 384/501] build(deps): Bump slf4jVersion from 2.0.13 to 2.0.16 (#2221) Bumps `slf4jVersion` from 2.0.13 to 2.0.16. Updates `org.slf4j:slf4j-api` from 2.0.13 to 2.0.16 Updates `org.slf4j:slf4j-simple` from 2.0.13 to 2.0.16 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6197189ef..320c44bc9 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.13' + slf4jVersion = '2.0.16' } dependencies { From b96c86803dedf639bc342b4b38d35e393de2ea2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:05:09 +0300 Subject: [PATCH 385/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.10.3 to 5.11.0 (#2223) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.3 to 5.11.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.3...r5.11.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 320c44bc9..a4a58564b 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.10.3' + implementation 'org.junit.jupiter:junit-jupiter:5.11.0' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From f8ef9c18da59eaec1e948edbbe36971777cdaa78 Mon Sep 17 00:00:00 2001 From: MummanaSubramanya Date: Thu, 29 Aug 2024 16:46:17 +0200 Subject: [PATCH 386/501] fix: Scroll issue in flutter integration driver (#2227) --- .../java_client/android/CommandTest.java | 31 ++++++++++++++++--- .../flutter/commands/ScrollParameter.java | 9 +++--- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java index d8f587e52..0f056e51a 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java @@ -12,7 +12,9 @@ import org.openqa.selenium.WebElement; import java.io.IOException; +import java.time.Duration; +import static java.lang.Boolean.parseBoolean; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -52,18 +54,37 @@ void testScrollTillVisibleCommand() { openScreen("Vertical Swiping"); WebElement firstElement = driver.scrollTillVisible(new ScrollParameter(AppiumBy.flutterText("Java"))); - assertTrue(Boolean.parseBoolean(firstElement.getAttribute("displayed"))); + assertTrue(parseBoolean(firstElement.getAttribute("displayed"))); WebElement lastElement = driver.scrollTillVisible(new ScrollParameter(AppiumBy.flutterText("Protractor"))); - assertTrue(Boolean.parseBoolean(lastElement.getAttribute("displayed"))); - assertFalse(Boolean.parseBoolean(firstElement.getAttribute("displayed"))); + assertTrue(parseBoolean(lastElement.getAttribute("displayed"))); + assertFalse(parseBoolean(firstElement.getAttribute("displayed"))); firstElement = driver.scrollTillVisible( new ScrollParameter(AppiumBy.flutterText("Java"), ScrollParameter.ScrollDirection.UP) ); - assertTrue(Boolean.parseBoolean(firstElement.getAttribute("displayed"))); - assertFalse(Boolean.parseBoolean(lastElement.getAttribute("displayed"))); + assertTrue(parseBoolean(firstElement.getAttribute("displayed"))); + assertFalse(parseBoolean(lastElement.getAttribute("displayed"))); + } + + @Test + void testScrollTillVisibleWithScrollParametersCommand() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Vertical Swiping"); + + ScrollParameter scrollParameter = new ScrollParameter(AppiumBy.flutterText("Playwright")); + scrollParameter + .setScrollView(AppiumBy.flutterType("Scrollable")) + .setMaxScrolls(30) + .setDelta(30) + // Drag duration currently works when the value is greater than 33 secs + .setDragDuration(Duration.ofMillis(35000)) + .setSettleBetweenScrollsTimeout(5000); + + WebElement element = driver.scrollTillVisible(scrollParameter); + assertTrue(parseBoolean(element.getAttribute("displayed"))); } @Test diff --git a/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java b/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java index 773ece810..d2a2674c7 100644 --- a/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java +++ b/src/main/java/io/appium/java_client/flutter/commands/ScrollParameter.java @@ -4,7 +4,6 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import org.openqa.selenium.WebElement; import org.openqa.selenium.internal.Require; import java.time.Duration; @@ -18,7 +17,7 @@ @Setter public class ScrollParameter extends FlutterCommandParameter { private AppiumBy.FlutterBy scrollTo; - private WebElement scrollView; + private AppiumBy.FlutterBy scrollView; private ScrollDirection scrollDirection; private Integer delta; private Integer maxScrolls; @@ -56,13 +55,13 @@ public Map toJson() { params.put("finder", parseFlutterLocator(scrollTo)); Optional.ofNullable(scrollView) - .ifPresent(scrollView -> params.put("scrollView", scrollView)); + .ifPresent(scrollView -> params.put("scrollView", parseFlutterLocator(scrollView))); Optional.ofNullable(delta) .ifPresent(delta -> params.put("delta", delta)); Optional.ofNullable(maxScrolls) - .ifPresent(maxScrolls -> params.put("delta", maxScrolls)); + .ifPresent(maxScrolls -> params.put("maxScrolls", maxScrolls)); Optional.ofNullable(settleBetweenScrollsTimeout) - .ifPresent(timeout -> params.put("delta", settleBetweenScrollsTimeout)); + .ifPresent(timeout -> params.put("settleBetweenScrollsTimeout", settleBetweenScrollsTimeout)); Optional.ofNullable(scrollDirection) .ifPresent(direction -> params.put("scrollDirection", direction.getDirection())); Optional.ofNullable(dragDuration) From 34a8d5f154f7337db400e2566e643c1ea4052ae3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:01:49 +0200 Subject: [PATCH 387/501] build(deps): Bump org.owasp.dependencycheck from 10.0.3 to 10.0.4 (#2229) Bumps org.owasp.dependencycheck from 10.0.3 to 10.0.4. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a4a58564b..a95746877 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '10.0.3' + id 'org.owasp.dependencycheck' version '10.0.4' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 9b3194e29857b6204f51d7f198d3583d2d904e50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:48:55 +0300 Subject: [PATCH 388/501] build(deps): Bump org.apache.commons:commons-lang3 from 3.16.0 to 3.17.0 (#2228) Bumps org.apache.commons:commons-lang3 from 3.16.0 to 3.17.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a95746877..e0fc588ce 100644 --- a/build.gradle +++ b/build.gradle @@ -233,7 +233,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('org.apache.commons:commons-lang3:3.16.0') + implementation('org.apache.commons:commons-lang3:3.17.0') } targets.configureEach { From 81c9a589cda621bb74164b0b40260899f63aff05 Mon Sep 17 00:00:00 2001 From: Nick Chursin Date: Wed, 25 Sep 2024 14:58:36 +0300 Subject: [PATCH 389/501] ci: Build WDA for specific device (#2236) --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e960bf822..89a292f87 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -139,7 +139,7 @@ jobs: run: appium driver install xcuitest - name: Prebuild XCUITest driver if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' - run: appium driver run xcuitest build-wda + run: appium driver run xcuitest build-wda --sdk=${{ env.IOS_PLATFORM_VERSION }} --name='${{ env.IOS_DEVICE_NAME }}' - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' run: ./gradlew e2eIosTest -PisCI -Pselenium.version=$latest_snapshot From 87b222552ca481b3a8886b78592707d38e48227d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:24:18 +0300 Subject: [PATCH 390/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.11.0 to 5.11.1 (#2237) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.0 to 5.11.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.0...r5.11.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e0fc588ce..8220a2889 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.11.0' + implementation 'org.junit.jupiter:junit-jupiter:5.11.1' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 2721bf48ac64fb7f6e577ec6ae5f63604f6a7f84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:13:34 +0300 Subject: [PATCH 391/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.11.1 to 5.11.2 (#2240) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.1 to 5.11.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.1...r5.11.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8220a2889..f5ecfa68c 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.11.1' + implementation 'org.junit.jupiter:junit-jupiter:5.11.2' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 45bb1d7b2b423fc3b86e79ce31eb09d5fb90da4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:11:09 +0200 Subject: [PATCH 392/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.11.2 to 5.11.3 (#2242) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.2 to 5.11.3. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.2...r5.11.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f5ecfa68c..f9e92bece 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.11.2' + implementation 'org.junit.jupiter:junit-jupiter:5.11.3' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 778dc6442c55d5a4acbb81a381fc4dba49fd8828 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:22:08 +0200 Subject: [PATCH 393/501] build(deps): Bump org.owasp.dependencycheck from 10.0.4 to 11.0.0 (#2241) Bumps org.owasp.dependencycheck from 10.0.4 to 11.0.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f9e92bece..1bc70ed78 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '10.0.4' + id 'org.owasp.dependencycheck' version '11.0.0' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 9276c948e597eb3f6073b29fd50dc93680b88342 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:05:54 +0200 Subject: [PATCH 394/501] build(deps): Bump org.owasp.dependencycheck from 11.0.0 to 11.1.0 (#2244) Bumps org.owasp.dependencycheck from 11.0.0 to 11.1.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1bc70ed78..60eb40ea4 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '11.0.0' + id 'org.owasp.dependencycheck' version '11.1.0' id 'com.github.johnrengelman.shadow' version '8.1.1' } From c9d72208710fcfda2847d27e8c33a6c2718c5667 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:21:30 +0200 Subject: [PATCH 395/501] build(deps): Bump futureware-tech/simulator-action from 3 to 4 (#2243) Bumps [futureware-tech/simulator-action](https://github.com/futureware-tech/simulator-action) from 3 to 4. - [Release notes](https://github.com/futureware-tech/simulator-action/releases) - [Changelog](https://github.com/futureware-tech/simulator-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/futureware-tech/simulator-action/compare/v3...v4) --- updated-dependencies: - dependency-name: futureware-tech/simulator-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 89a292f87..252710957 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -130,7 +130,7 @@ jobs: xcode-version: "${{ env.XCODE_VERSION }}" - name: Prepare iOS simulator if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' - uses: futureware-tech/simulator-action@v3 + uses: futureware-tech/simulator-action@v4 with: model: "${{ env.IOS_DEVICE_NAME }}" os_version: "${{ env.IOS_PLATFORM_VERSION }}" From 1c581182d859ad37aeffe6431bbdaf2025e335b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 23:01:32 +0200 Subject: [PATCH 396/501] build(deps): Bump org.projectlombok:lombok from 1.18.34 to 1.18.36 (#2245) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.34 to 1.18.36. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.34...v1.18.36) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 60eb40ea4..4e0b67886 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.34' - annotationProcessor 'org.projectlombok:lombok:1.18.34' + compileOnly 'org.projectlombok:lombok:1.18.36' + annotationProcessor 'org.projectlombok:lombok:1.18.36' if (project.hasProperty("isCI")) { api "org.seleniumhq.selenium:selenium-api:${seleniumVersion}" From 42480feca9845bbbb569b13d995b80980bf4ca33 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 27 Nov 2024 08:49:46 +0100 Subject: [PATCH 397/501] chore: Bump the minimum java client version to 4.26.0 (#2246) --- gradle.properties | 2 +- .../io/appium/java_client/AppiumDriver.java | 23 +++++----------- .../appium/java_client/AppiumFluentWait.java | 26 +++++-------------- .../remote/AppiumCommandExecutor.java | 11 ++++---- .../service/local/AppiumServiceBuilder.java | 6 +---- 5 files changed, 22 insertions(+), 46 deletions(-) diff --git a/gradle.properties b/gradle.properties index 10017f9d5..1bd7b6aed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.19.0 +selenium.version=4.26.0 # Please increment the value in a release appiumClient.version=9.3.0 diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index c8d660e9f..a8757843c 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -17,7 +17,6 @@ package io.appium.java_client; import io.appium.java_client.internal.CapabilityHelpers; -import io.appium.java_client.internal.ReflectionHelpers; import io.appium.java_client.internal.SessionHelpers; import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumW3CHttpCommandCodec; @@ -27,7 +26,6 @@ import lombok.Getter; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; -import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.OutputType; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.UnsupportedCommandException; @@ -152,12 +150,10 @@ public AppiumDriver(Capabilities capabilities) { */ public AppiumDriver(URL remoteSessionAddress, String platformName, String automationName) { super(); - ReflectionHelpers.setPrivateFieldValue( - RemoteWebDriver.class, this, "capabilities", new ImmutableCapabilities( - Map.of( - PLATFORM_NAME, platformName, - APPIUM_PREFIX + AUTOMATION_NAME_OPTION, automationName - ) + this.capabilities = new ImmutableCapabilities( + Map.of( + PLATFORM_NAME, platformName, + APPIUM_PREFIX + AUTOMATION_NAME_OPTION, automationName ) ); SessionHelpers.SessionAddress sessionAddress = SessionHelpers.parseSessionAddress(remoteSessionAddress); @@ -168,7 +164,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa executor.setResponseCodec(new W3CHttpResponseCodec()); setCommandExecutor(executor); this.executeMethod = new AppiumExecutionMethod(this); - locationContext = new RemoteLocationContext(executeMethod); + this.locationContext = new RemoteLocationContext(executeMethod); super.setErrorHandler(ERROR_HANDLER); this.remoteAddress = executor.getAddressOfRemoteServer(); @@ -293,10 +289,7 @@ protected void startSession(Capabilities capabilities) { && isNullOrEmpty((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { rawCapabilities.remove(CapabilityType.BROWSER_NAME); } - MutableCapabilities returnedCapabilities = new BaseOptions<>(rawCapabilities); - ReflectionHelpers.setPrivateFieldValue( - RemoteWebDriver.class, this, "capabilities", returnedCapabilities - ); + this.capabilities = new BaseOptions<>(rawCapabilities); setSessionId(response.getSessionId()); } @@ -345,8 +338,6 @@ public AppiumDriver markExtensionAbsence(String extName) { } protected HttpClient getHttpClient() { - return ReflectionHelpers.getPrivateFieldValue( - HttpCommandExecutor.class, getCommandExecutor(), "client", HttpClient.class - ); + return ((HttpCommandExecutor) getCommandExecutor()).client; } } diff --git a/src/main/java/io/appium/java_client/AppiumFluentWait.java b/src/main/java/io/appium/java_client/AppiumFluentWait.java index 6361a5652..a284e1ebb 100644 --- a/src/main/java/io/appium/java_client/AppiumFluentWait.java +++ b/src/main/java/io/appium/java_client/AppiumFluentWait.java @@ -17,7 +17,6 @@ package io.appium.java_client; import com.google.common.base.Throwables; -import io.appium.java_client.internal.ReflectionHelpers; import lombok.AccessLevel; import lombok.Getter; import org.openqa.selenium.TimeoutException; @@ -114,43 +113,32 @@ public AppiumFluentWait withPollDelay(Duration pollDelay) { return this; } - private B getPrivateFieldValue(String fieldName, Class fieldType) { - return ReflectionHelpers.getPrivateFieldValue(FluentWait.class, this, fieldName, fieldType); - } - - private Object getPrivateFieldValue(String fieldName) { - return getPrivateFieldValue(fieldName, Object.class); - } - protected Clock getClock() { - return getPrivateFieldValue("clock", Clock.class); + return clock; } protected Duration getTimeout() { - return getPrivateFieldValue("timeout", Duration.class); + return timeout; } protected Duration getInterval() { - return getPrivateFieldValue("interval", Duration.class); + return interval; } protected Sleeper getSleeper() { - return getPrivateFieldValue("sleeper", Sleeper.class); + return sleeper; } - @SuppressWarnings("unchecked") protected List> getIgnoredExceptions() { - return getPrivateFieldValue("ignoredExceptions", List.class); + return ignoredExceptions; } - @SuppressWarnings("unchecked") protected Supplier getMessageSupplier() { - return getPrivateFieldValue("messageSupplier", Supplier.class); + return messageSupplier; } - @SuppressWarnings("unchecked") protected T getInput() { - return (T) getPrivateFieldValue("input"); + return (T) input; } /** diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 118f0ff81..a689e7d33 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -119,12 +119,14 @@ public AppiumCommandExecutor(Map additionalCommands, this(additionalCommands, service, HttpClient.Factory.createDefault(), appiumClientConfig); } + @Deprecated @SuppressWarnings("SameParameterValue") protected B getPrivateFieldValue( Class cls, String fieldName, Class fieldType) { return ReflectionHelpers.getPrivateFieldValue(cls, this, fieldName, fieldType); } + @Deprecated @SuppressWarnings("SameParameterValue") protected void setPrivateFieldValue( Class cls, String fieldName, Object newValue) { @@ -137,20 +139,19 @@ protected Map getAdditionalCommands() { } protected CommandCodec getCommandCodec() { - //noinspection unchecked - return getPrivateFieldValue(HttpCommandExecutor.class, "commandCodec", CommandCodec.class); + return this.commandCodec; } public void setCommandCodec(CommandCodec newCodec) { - setPrivateFieldValue(HttpCommandExecutor.class, "commandCodec", newCodec); + this.commandCodec = newCodec; } public void setResponseCodec(ResponseCodec codec) { - setPrivateFieldValue(HttpCommandExecutor.class, "responseCodec", codec); + this.responseCodec = codec; } protected HttpClient getClient() { - return getPrivateFieldValue(HttpCommandExecutor.class, "client", HttpClient.class); + return this.client; } /** diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index ad3729e77..5dadb6403 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -20,7 +20,6 @@ import com.google.gson.GsonBuilder; import io.appium.java_client.android.options.context.SupportsChromedriverExecutableOption; import io.appium.java_client.android.options.signing.SupportsKeystoreOptions; -import io.appium.java_client.internal.ReflectionHelpers; import io.appium.java_client.remote.MobileBrowserType; import io.appium.java_client.remote.options.SupportsAppOption; import io.appium.java_client.service.local.flags.GeneralServerFlag; @@ -400,10 +399,7 @@ protected List createArgs() { @Override protected void loadSystemProperties() { - File driverExecutable = ReflectionHelpers.getPrivateFieldValue( - DriverService.Builder.class, this, "exe", File.class - ); - if (driverExecutable == null) { + if (this.exe == null) { usingDriverExecutable(findDefaultExecutable()); } } From 7fc702e6fdff0c5df33e9c986bd1b2ff9a029a2a Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Sun, 15 Dec 2024 20:35:46 +0300 Subject: [PATCH 398/501] fix: Fix compatibility with latest Selenium snapshots (#2249) --- src/main/java/io/appium/java_client/AppiumDriver.java | 10 ++++++---- .../java_client/remote/AppiumCommandExecutor.java | 8 ++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index a8757843c..8d0bf3cb1 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -31,6 +31,7 @@ import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.ErrorHandler; import org.openqa.selenium.remote.ExecuteMethod; @@ -242,22 +243,23 @@ public Map getStatus() { * @param methodName The name of custom appium command. */ public void addCommand(HttpMethod httpMethod, String url, String methodName) { + CommandInfo commandInfo; switch (httpMethod) { case GET: - MobileCommand.commandRepository.put(methodName, MobileCommand.getC(url)); + commandInfo = MobileCommand.getC(url); break; case POST: - MobileCommand.commandRepository.put(methodName, MobileCommand.postC(url)); + commandInfo = MobileCommand.postC(url); break; case DELETE: - MobileCommand.commandRepository.put(methodName, MobileCommand.deleteC(url)); + commandInfo = MobileCommand.deleteC(url); break; default: throw new WebDriverException(String.format("Unsupported HTTP Method: %s. Only %s methods are supported", httpMethod, Arrays.toString(HttpMethod.values()))); } - ((AppiumCommandExecutor) getCommandExecutor()).refreshAdditionalCommands(); + ((AppiumCommandExecutor) getCommandExecutor()).defineCommand(methodName, commandInfo); } @Override diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index a689e7d33..d22084c3b 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -133,7 +133,7 @@ protected void setPrivateFieldValue( ReflectionHelpers.setPrivateFieldValue(cls, this, fieldName, newValue); } - protected Map getAdditionalCommands() { + public Map getAdditionalCommands() { //noinspection unchecked return getPrivateFieldValue(HttpCommandExecutor.class, "additionalCommands", Map.class); } @@ -192,7 +192,11 @@ private Response createSession(Command command) throws IOException { } public void refreshAdditionalCommands() { - getAdditionalCommands().forEach(this::defineCommand); + getAdditionalCommands().forEach(super::defineCommand); + } + + public void defineCommand(String commandName, CommandInfo info) { + super.defineCommand(commandName, info); } @SuppressWarnings("unchecked") From d01161d5f852ff381ea4e1d27dc08bba05132b4b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 16 Dec 2024 08:30:18 +0100 Subject: [PATCH 399/501] feat: Implement HasBiDi interface support in AppiumDriver (#2250) --- .github/workflows/gradle.yml | 1 + .../android/AndroidContextTest.java | 7 +- .../android/AndroidFunctionTest.java | 3 +- .../io/appium/java_client/ios/AppIOSTest.java | 1 + .../java_client/ios/BaseIOSWebViewTest.java | 1 - .../appium/java_client/ios/IOSBiDiTest.java | 42 +++ .../java_client/ios/IOSContextTest.java | 5 +- .../java_client/ios/IOSWebViewTest.java | 5 + .../io/appium/java_client/AppiumDriver.java | 254 ++++++++++++------ .../appium/java_client/HasBrowserCheck.java | 4 +- .../utils/WebDriverUnpackUtility.java | 5 +- .../remote/AppiumCommandExecutor.java | 5 +- .../remote/options/BaseOptions.java | 3 +- .../options/SupportsWebSocketUrlOption.java | 54 ++++ .../java/io/appium/java_client/TestUtils.java | 4 + 15 files changed, 296 insertions(+), 98 deletions(-) create mode 100644 src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java create mode 100644 src/main/java/io/appium/java_client/remote/options/SupportsWebSocketUrlOption.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 252710957..cd70a8203 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -19,6 +19,7 @@ concurrency: cancel-in-progress: true env: + CI: true ANDROID_SDK_VERSION: "28" ANDROID_EMU_NAME: test ANDROID_EMU_TARGET: default diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidContextTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidContextTest.java index fdc47664b..1a9a5657d 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidContextTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidContextTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -31,7 +32,7 @@ public class AndroidContextTest extends BaseAndroidTest { } @Test public void testGetContext() { - assertEquals("NATIVE_APP", driver.getContext()); + assertEquals(NATIVE_CONTEXT, driver.getContext()); } @Test public void testGetContextHandles() { @@ -42,8 +43,8 @@ public class AndroidContextTest extends BaseAndroidTest { driver.getContextHandles(); driver.context("WEBVIEW_io.appium.android.apis"); assertEquals(driver.getContext(), "WEBVIEW_io.appium.android.apis"); - driver.context("NATIVE_APP"); - assertEquals(driver.getContext(), "NATIVE_APP"); + driver.context(NATIVE_CONTEXT); + assertEquals(driver.getContext(), NATIVE_CONTEXT); } @Test public void testContextError() { diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidFunctionTest.java index 79d327ae1..0db6f2647 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidFunctionTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidFunctionTest.java @@ -18,6 +18,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; import static java.time.Duration.ofMillis; import static java.time.Duration.ofSeconds; import static org.hamcrest.MatcherAssert.assertThat; @@ -75,7 +76,7 @@ public static void startWebViewActivity() { @BeforeEach public void setUp() { - driver.context("NATIVE_APP"); + driver.context(NATIVE_CONTEXT); } @Test diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java index 25574d727..595114978 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java @@ -21,6 +21,7 @@ public static void beforeClass() { .setDeviceName(DEVICE_NAME) .setCommandTimeouts(Duration.ofSeconds(240)) .setApp(TEST_APP_ZIP) + .enableBiDi() .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); try { driver = new IOSDriver(service.getUrl(), options); diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 752a0c539..2ffe6c79c 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -39,7 +39,6 @@ public static void beforeClass() { .setDeviceName(DEVICE_NAME) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) .setCommandTimeouts(Duration.ofSeconds(240)) - .setShowIosLog(true) .setApp(VODQA_ZIP); Supplier createDriver = () -> new IOSDriver(service.getUrl(), options); try { diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java new file mode 100644 index 000000000..e25d3f515 --- /dev/null +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java @@ -0,0 +1,42 @@ +/* + * 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 org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.bidi.log.LogEntry; +import org.openqa.selenium.bidi.module.LogInspector; + +import java.util.concurrent.CopyOnWriteArrayList; + +import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class IOSBiDiTest extends AppIOSTest { + + @Test + @Disabled("Need to resolve compatibility issues") + public void listenForIosLogs() { + var logs = new CopyOnWriteArrayList(); + try (var logInspector = new LogInspector(NATIVE_CONTEXT, driver)) { + logInspector.onLog(logs::add); + driver.getPageSource(); + } + assertFalse(logs.isEmpty()); + } + +} diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java index f2ac548b1..c7e0af42f 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java @@ -19,6 +19,7 @@ import io.appium.java_client.NoSuchContextException; import org.junit.jupiter.api.Test; +import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -27,7 +28,7 @@ public class IOSContextTest extends BaseIOSWebViewTest { @Test public void testGetContext() { - assertEquals("NATIVE_APP", driver.getContext()); + assertEquals(NATIVE_CONTEXT, driver.getContext()); } @Test public void testGetContextHandles() { @@ -38,7 +39,7 @@ public class IOSContextTest extends BaseIOSWebViewTest { driver.getContextHandles(); findAndSwitchToWebView(); assertThat(driver.getContext(), containsString("WEBVIEW")); - driver.context("NATIVE_APP"); + driver.context(NATIVE_CONTEXT); } @Test public void testContextError() { diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java index 60943342e..da68eeecb 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java @@ -1,6 +1,8 @@ package io.appium.java_client.ios; import io.appium.java_client.AppiumBy; +import io.appium.java_client.TestUtils; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -15,6 +17,9 @@ public class IOSWebViewTest extends BaseIOSWebViewTest { @Test public void webViewPageTestCase() throws InterruptedException { + // this test is not stable in the CI env + Assumptions.assumeFalse(TestUtils.isCiEnv()); + new WebDriverWait(driver, LOOKUP_TIMEOUT) .until(ExpectedConditions.presenceOfElementLocated(By.id("login"))) .click(); diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 8d0bf3cb1..01065fe48 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -21,6 +21,7 @@ import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.AppiumW3CHttpCommandCodec; import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.SupportsWebSocketUrlOption; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import lombok.Getter; @@ -30,6 +31,9 @@ import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.UnsupportedCommandException; import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.bidi.BiDi; +import org.openqa.selenium.bidi.BiDiException; +import org.openqa.selenium.bidi.HasBiDi; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.DriverCommand; @@ -43,6 +47,9 @@ import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; +import javax.annotation.Nonnull; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.Collections; @@ -67,7 +74,8 @@ public class AppiumDriver extends RemoteWebDriver implements LogsEvents, HasBrowserCheck, CanRememberExtensionPresence, - HasSettings { + HasSettings, + HasBiDi { private static final ErrorHandler ERROR_HANDLER = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters @@ -77,6 +85,9 @@ public class AppiumDriver extends RemoteWebDriver implements protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; private final Set absentExtensionNames = new HashSet<>(); + private URI biDiUri; + private BiDi biDi; + private boolean wasBiDiRequested = false; /** * Creates a new instance based on command {@code executor} and {@code capabilities}. @@ -146,8 +157,8 @@ public AppiumDriver(Capabilities capabilities) { * !!! This API is supposed to be used for **debugging purposes only**. * * @param remoteSessionAddress The address of the **running** session including the session identifier. - * @param platformName The name of the target platform. - * @param automationName The name of the target automation. + * @param platformName The name of the target platform. + * @param automationName The name of the target automation. */ public AppiumDriver(URL remoteSessionAddress, String platformName, String automationName) { super(); @@ -172,54 +183,6 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa setSessionId(sessionAddress.getId()); } - /** - * Changes platform name if it is not set and returns merged capabilities. - * - * @param originalCapabilities the given {@link Capabilities}. - * @param defaultName a platformName value which has to be set up - * @return {@link Capabilities} with changed platform name value or the original capabilities - */ - protected static Capabilities ensurePlatformName( - Capabilities originalCapabilities, String defaultName) { - return originalCapabilities.getPlatformName() == null - ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) - : originalCapabilities; - } - - /** - * Changes automation name if it is not set and returns merged capabilities. - * - * @param originalCapabilities the given {@link Capabilities}. - * @param defaultName a platformName value which has to be set up - * @return {@link Capabilities} with changed mobile automation name value or the original capabilities - */ - protected static Capabilities ensureAutomationName( - Capabilities originalCapabilities, String defaultName) { - String currentAutomationName = CapabilityHelpers.getCapability( - originalCapabilities, AUTOMATION_NAME_OPTION, String.class); - if (isNullOrEmpty(currentAutomationName)) { - String capabilityName = originalCapabilities.getCapabilityNames() - .contains(AUTOMATION_NAME_OPTION) ? AUTOMATION_NAME_OPTION : APPIUM_PREFIX + AUTOMATION_NAME_OPTION; - return originalCapabilities.merge(new ImmutableCapabilities(capabilityName, defaultName)); - } - return originalCapabilities; - } - - /** - * Changes platform and automation names if they are not set - * and returns merged capabilities. - * - * @param originalCapabilities the given {@link Capabilities}. - * @param defaultPlatformName a platformName value which has to be set up - * @param defaultAutomationName The default automation name to set up for this class - * @return {@link Capabilities} with changed platform/automation name value or the original capabilities - */ - protected static Capabilities ensurePlatformAndAutomationNames( - Capabilities originalCapabilities, String defaultPlatformName, String defaultAutomationName) { - Capabilities capsWithPlatformFixed = ensurePlatformName(originalCapabilities, defaultPlatformName); - return ensureAutomationName(capsWithPlatformFixed, defaultAutomationName); - } - @Override public ExecuteMethod getExecuteMethod() { return executeMethod; @@ -262,39 +225,6 @@ public void addCommand(HttpMethod httpMethod, String url, String methodName) { ((AppiumCommandExecutor) getCommandExecutor()).defineCommand(methodName, commandInfo); } - @Override - protected void startSession(Capabilities capabilities) { - var response = Optional.ofNullable( - execute(DriverCommand.NEW_SESSION(singleton(capabilities))) - ).orElseThrow(() -> new SessionNotCreatedException( - "The underlying command executor returned a null response." - )); - - var rawCapabilities = Optional.ofNullable(response.getValue()) - .map(value -> { - if (!(value instanceof Map)) { - throw new SessionNotCreatedException(String.format( - "The underlying command executor returned a response " - + "with a non well formed payload: %s", response) - ); - } - //noinspection unchecked - return (Map) value; - }) - .orElseThrow(() -> new SessionNotCreatedException( - "The underlying command executor returned a response without payload: " + response) - ); - - // TODO: remove this workaround for Selenium API enforcing some legacy capability values in major version - rawCapabilities.remove("platform"); - if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME) - && isNullOrEmpty((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) { - rawCapabilities.remove(CapabilityType.BROWSER_NAME); - } - this.capabilities = new BaseOptions<>(rawCapabilities); - setSessionId(response.getSessionId()); - } - @Override public Response execute(String driverCommand, Map parameters) { return super.execute(driverCommand, parameters); @@ -339,7 +269,163 @@ public AppiumDriver markExtensionAbsence(String extName) { return this; } + @Override + public Optional maybeGetBiDi() { + return Optional.ofNullable(this.biDi); + } + + @Override + @Nonnull + public BiDi getBiDi() { + var webSocketUrl = ((BaseOptions) this.capabilities).getWebSocketUrl().orElseThrow( + () -> { + var suffix = wasBiDiRequested + ? "Do both the server and the driver declare BiDi support?" + : String.format("Did you set %s to true?", SupportsWebSocketUrlOption.WEB_SOCKET_URL); + return new BiDiException(String.format( + "BiDi is not enabled for this driver session. %s", suffix + )); + } + ); + if (this.biDiUri == null) { + throw new BiDiException( + String.format( + "BiDi is not enabled for this driver session. " + + "Is the %s '%s' received from the create session response valid?", + SupportsWebSocketUrlOption.WEB_SOCKET_URL, webSocketUrl + ) + ); + } + if (this.biDi == null) { + // This should not happen + throw new IllegalStateException(); + } + return this.biDi; + } + protected HttpClient getHttpClient() { return ((HttpCommandExecutor) getCommandExecutor()).client; } + + @Override + protected void startSession(Capabilities requestCapabilities) { + var response = Optional.ofNullable( + execute(DriverCommand.NEW_SESSION(singleton(requestCapabilities))) + ).orElseThrow(() -> new SessionNotCreatedException( + "The underlying command executor returned a null response." + )); + + var rawResponseCapabilities = Optional.ofNullable(response.getValue()) + .map(value -> { + if (!(value instanceof Map)) { + throw new SessionNotCreatedException(String.format( + "The underlying command executor returned a response " + + "with a non well formed payload: %s", response) + ); + } + //noinspection unchecked + return (Map) value; + }) + .orElseThrow(() -> new SessionNotCreatedException( + "The underlying command executor returned a response without payload: " + response) + ); + + // TODO: remove this workaround for Selenium API enforcing some legacy capability values in major version + rawResponseCapabilities.remove("platform"); + if (rawResponseCapabilities.containsKey(CapabilityType.BROWSER_NAME) + && isNullOrEmpty((String) rawResponseCapabilities.get(CapabilityType.BROWSER_NAME))) { + rawResponseCapabilities.remove(CapabilityType.BROWSER_NAME); + } + this.capabilities = new BaseOptions<>(rawResponseCapabilities); + this.wasBiDiRequested = Boolean.TRUE.equals( + requestCapabilities.getCapability(SupportsWebSocketUrlOption.WEB_SOCKET_URL) + ); + if (wasBiDiRequested) { + this.initBiDi((BaseOptions) capabilities); + } + setSessionId(response.getSessionId()); + } + + /** + * Changes platform name if it is not set and returns merged capabilities. + * + * @param originalCapabilities the given {@link Capabilities}. + * @param defaultName a platformName value which has to be set up + * @return {@link Capabilities} with changed platform name value or the original capabilities + */ + protected static Capabilities ensurePlatformName( + Capabilities originalCapabilities, String defaultName) { + return originalCapabilities.getPlatformName() == null + ? originalCapabilities.merge(new ImmutableCapabilities(PLATFORM_NAME, defaultName)) + : originalCapabilities; + } + + /** + * Changes automation name if it is not set and returns merged capabilities. + * + * @param originalCapabilities the given {@link Capabilities}. + * @param defaultName a platformName value which has to be set up + * @return {@link Capabilities} with changed mobile automation name value or the original capabilities + */ + protected static Capabilities ensureAutomationName( + Capabilities originalCapabilities, String defaultName) { + String currentAutomationName = CapabilityHelpers.getCapability( + originalCapabilities, AUTOMATION_NAME_OPTION, String.class); + if (isNullOrEmpty(currentAutomationName)) { + String capabilityName = originalCapabilities.getCapabilityNames() + .contains(AUTOMATION_NAME_OPTION) ? AUTOMATION_NAME_OPTION : APPIUM_PREFIX + AUTOMATION_NAME_OPTION; + return originalCapabilities.merge(new ImmutableCapabilities(capabilityName, defaultName)); + } + return originalCapabilities; + } + + /** + * Changes platform and automation names if they are not set + * and returns merged capabilities. + * + * @param originalCapabilities the given {@link Capabilities}. + * @param defaultPlatformName a platformName value which has to be set up + * @param defaultAutomationName The default automation name to set up for this class + * @return {@link Capabilities} with changed platform/automation name value or the original capabilities + */ + protected static Capabilities ensurePlatformAndAutomationNames( + Capabilities originalCapabilities, String defaultPlatformName, String defaultAutomationName) { + Capabilities capsWithPlatformFixed = ensurePlatformName(originalCapabilities, defaultPlatformName); + return ensureAutomationName(capsWithPlatformFixed, defaultAutomationName); + } + + private void initBiDi(BaseOptions responseCaps) { + var webSocketUrl = responseCaps.getWebSocketUrl(); + if (webSocketUrl.isEmpty()) { + return; + } + URISyntaxException uriSyntaxError = null; + try { + this.biDiUri = new URI(String.valueOf(webSocketUrl.get())); + } catch (URISyntaxException e) { + uriSyntaxError = e; + } + if (uriSyntaxError != null || this.biDiUri.getScheme() == null) { + var message = String.format( + "BiDi cannot be enabled for this driver session. " + + "Is the %s '%s' received from the create session response valid?", + SupportsWebSocketUrlOption.WEB_SOCKET_URL, webSocketUrl.get() + ); + if (uriSyntaxError == null) { + throw new BiDiException(message); + } + throw new BiDiException(message, uriSyntaxError); + } + var executor = getCommandExecutor(); + final HttpClient wsClient; + if (executor instanceof AppiumCommandExecutor) { + var wsConfig = ((AppiumCommandExecutor) executor).getAppiumClientConfig().baseUri(biDiUri); + wsClient = ((AppiumCommandExecutor) executor).getHttpClientFactory().createClient(wsConfig); + } else { + var wsConfig = AppiumClientConfig.defaultConfig().baseUri(biDiUri); + wsClient = HttpClient.Factory.createDefault().createClient(wsConfig); + } + var biDiConnection = new org.openqa.selenium.bidi.Connection(wsClient, biDiUri.toString()); + this.biDi = new BiDi(biDiConnection); + } } diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java index 76094b5ca..ebce4a3c5 100644 --- a/src/main/java/io/appium/java_client/HasBrowserCheck.java +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -10,6 +10,8 @@ import static java.util.Objects.requireNonNull; public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { + String NATIVE_CONTEXT = "NATIVE_APP"; + /** * Validates if the driver is currently in a web browser context. * @@ -32,7 +34,7 @@ default boolean isBrowser() { } try { var context = ((ContextAware) this).getContext(); - return context != null && !context.toUpperCase().contains("NATIVE_APP"); + return context != null && !context.toUpperCase().contains(NATIVE_CONTEXT); } catch (WebDriverException e) { return false; } diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 190f9c4ae..8b59d7ba6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -28,12 +28,11 @@ import java.util.Optional; +import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; public final class WebDriverUnpackUtility { - private static final String NATIVE_APP_PATTERN = "NATIVE_APP"; - private WebDriverUnpackUtility() { } @@ -109,7 +108,7 @@ public static ContentType getCurrentContentType(SearchContext context) { var contextAware = unpackObjectFromSearchContext(context, ContextAware.class); if (contextAware.map(ContextAware::getContext) - .filter(c -> c.toUpperCase().contains(NATIVE_APP_PATTERN)).isPresent()) { + .filter(c -> c.toUpperCase().contains(NATIVE_CONTEXT)).isPresent()) { return NATIVE_MOBILE_SPECIFIC; } diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index d22084c3b..84ac2c089 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -19,6 +19,7 @@ import com.google.common.base.Throwables; import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.internal.ReflectionHelpers; +import lombok.Getter; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Command; @@ -54,9 +55,9 @@ public class AppiumCommandExecutor extends HttpCommandExecutor { private final Optional serviceOptional; - + @Getter private final HttpClient.Factory httpClientFactory; - + @Getter private final AppiumClientConfig appiumClientConfig; /** diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index dff4f5c44..7e3ade21f 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -49,7 +49,8 @@ public class BaseOptions> extends MutableCapabilities i SupportsFullResetOption, SupportsNewCommandTimeoutOption, SupportsBrowserNameOption, - SupportsPlatformVersionOption { + SupportsPlatformVersionOption, + SupportsWebSocketUrlOption { /** * Creates new instance with no preset capabilities. diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsWebSocketUrlOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsWebSocketUrlOption.java new file mode 100644 index 000000000..1e14174cc --- /dev/null +++ b/src/main/java/io/appium/java_client/remote/options/SupportsWebSocketUrlOption.java @@ -0,0 +1,54 @@ +/* + * 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.remote.options; + +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsWebSocketUrlOption> extends + Capabilities, CanSetCapability { + String WEB_SOCKET_URL = "webSocketUrl"; + + /** + * Enable BiDi session support. + * + * @return self instance for chaining. + */ + default T enableBiDi() { + return amend(WEB_SOCKET_URL, true); + } + + /** + * Whether to enable BiDi session support. + * + * @return self instance for chaining. + */ + default T setWebSocketUrl(boolean value) { + return amend(WEB_SOCKET_URL, value); + } + + /** + * For input capabilities: whether enable BiDi session support is enabled. + * For session creation response capabilities: BiDi web socket URL. + * + * @return If called on request capabilities if BiDi support is enabled for the driver session + */ + default Optional getWebSocketUrl() { + return Optional.ofNullable(getCapability(WEB_SOCKET_URL)); + } +} diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index 1d650777c..73d104469 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -78,4 +78,8 @@ public static Point getCenter(WebElement webElement, @Nullable Point location) { } return new Point(location.x + dim.width / 2, location.y + dim.height / 2); } + + public static boolean isCiEnv() { + return System.getenv("CI") != null; + } } From f8b7510b70d34625afd84c84cf09752dffbbe54a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:53:12 +0200 Subject: [PATCH 400/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.11.3 to 5.11.4 (#2251) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4e0b67886..3b677ed9f 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.11.3' + implementation 'org.junit.jupiter:junit-jupiter:5.11.4' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 3a149c9a8bf2fc7e44a8e64680f449156a77e008 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:53:38 +0200 Subject: [PATCH 401/501] build(deps): Bump org.owasp.dependencycheck from 11.1.0 to 11.1.1 (#2248) Bumps org.owasp.dependencycheck from 11.1.0 to 11.1.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3b677ed9f..b64622565 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '11.1.0' + id 'org.owasp.dependencycheck' version '11.1.1' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 39ee841a8979a4deb1be484120848027018987d2 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 7 Jan 2025 12:19:08 +0100 Subject: [PATCH 402/501] test: Reenable BiDi logging tests for iOS (#2254) --- .../appium/java_client/ios/IOSBiDiTest.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java index e25d3f515..d6288165d 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSBiDiTest.java @@ -16,8 +16,8 @@ package io.appium.java_client.ios; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.openqa.selenium.bidi.Event; import org.openqa.selenium.bidi.log.LogEntry; import org.openqa.selenium.bidi.module.LogInspector; @@ -29,8 +29,23 @@ public class IOSBiDiTest extends AppIOSTest { @Test - @Disabled("Need to resolve compatibility issues") - public void listenForIosLogs() { + public void listenForIosLogsGeneric() { + var logs = new CopyOnWriteArrayList<>(); + var listenerId = driver.getBiDi().addListener( + NATIVE_CONTEXT, + new Event("log.entryAdded", m -> m), + logs::add + ); + try { + driver.getPageSource(); + } finally { + driver.getBiDi().removeListener(listenerId); + } + assertFalse(logs.isEmpty()); + } + + @Test + public void listenForIosLogsSpecific() { var logs = new CopyOnWriteArrayList(); try (var logInspector = new LogInspector(NATIVE_CONTEXT, driver)) { logInspector.onLog(logs::add); From f75963dff9ea9a4037915c034c48079bc4169888 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:19:15 +0300 Subject: [PATCH 403/501] build(deps): Bump org.owasp.dependencycheck from 11.1.1 to 12.0.0 (#2255) Bumps org.owasp.dependencycheck from 11.1.1 to 12.0.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b64622565..88f4d7558 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '11.1.1' + id 'org.owasp.dependencycheck' version '12.0.0' id 'com.github.johnrengelman.shadow' version '8.1.1' } From a13724b56b45f641031a9c75ad2a7a9041a79ec9 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 13 Jan 2025 23:01:42 +0100 Subject: [PATCH 404/501] test: Add Android BiDi events test (#2256) --- .../java_client/android/AndroidBiDiTest.java | 57 +++++++++++++++++++ .../java_client/android/BaseAndroidTest.java | 1 + 2 files changed, 58 insertions(+) create mode 100644 src/e2eAndroidTest/java/io/appium/java_client/android/AndroidBiDiTest.java diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidBiDiTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidBiDiTest.java new file mode 100644 index 000000000..9901b50d6 --- /dev/null +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidBiDiTest.java @@ -0,0 +1,57 @@ +/* + * 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 org.junit.jupiter.api.Test; +import org.openqa.selenium.bidi.Event; +import org.openqa.selenium.bidi.log.LogEntry; +import org.openqa.selenium.bidi.module.LogInspector; + +import java.util.concurrent.CopyOnWriteArrayList; + +import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class AndroidBiDiTest extends BaseAndroidTest { + + @Test + public void listenForAndroidLogsGeneric() { + var logs = new CopyOnWriteArrayList<>(); + var listenerId = driver.getBiDi().addListener( + NATIVE_CONTEXT, + new Event("log.entryAdded", m -> m), + logs::add + ); + try { + driver.getPageSource(); + } finally { + driver.getBiDi().removeListener(listenerId); + } + assertFalse(logs.isEmpty()); + } + + @Test + public void listenForAndroidLogsSpecific() { + var logs = new CopyOnWriteArrayList(); + try (var logInspector = new LogInspector(NATIVE_CONTEXT, driver)) { + logInspector.onLog(logs::add); + driver.getPageSource(); + } + assertFalse(logs.isEmpty()); + } + +} diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java index 347304cf5..d56c8ca45 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/BaseAndroidTest.java @@ -44,6 +44,7 @@ public class BaseAndroidTest { UiAutomator2Options options = new UiAutomator2Options() .setDeviceName("Android Emulator") + .enableBiDi() .setApp(TestResources.API_DEMOS_APK.toString()) .eventTimings(); driver = new AndroidDriver(service.getUrl(), options); From f99533c46894d078519b0ad1aa9b1f114388cc5d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 17 Jan 2025 16:27:32 +0100 Subject: [PATCH 405/501] fix: Update the definition of 'logcatFilterSpecs' option (#2258) --- .../adb/SupportsLogcatFilterSpecsOption.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java index 6aca7a15e..e671e4848 100644 --- a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java @@ -20,6 +20,7 @@ import io.appium.java_client.remote.options.CanSetCapability; import org.openqa.selenium.Capabilities; +import java.util.List; import java.util.Optional; public interface SupportsLogcatFilterSpecsOption> extends @@ -27,25 +28,28 @@ public interface SupportsLogcatFilterSpecsOption> exten String LOGCAT_FILTER_SPECS_OPTION = "logcatFilterSpecs"; /** - * Series of tag[:priority] where tag is a log component tag (or * for all) - * and priority is: V Verbose, D Debug, I Info, W Warn, E Error, F Fatal, - * S Silent (supress all output). '' means ':d' and tag by itself means tag:v. - * If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS. - * If no filterspec is found, filter defaults to '*:I'. + * Allows to customize logcat output filtering. * - * @param format The filter specifier. + * @param format The filter specifier. Consists from series of `tag[:priority]` items, + * where `tag` is a log component tag (or `*` to match any value) + * and `priority`: V (Verbose), D (Debug), I (Info), W (Warn), E (Error), F (Fatal), + * S (Silent - supresses all output). `tag` without `priority` defaults to `tag:v`. + * If not specified, filterspec is set from ANDROID_LOG_TAGS environment variable. + * If no filterspec is found, filter defaults to `*:I`, which means + * to only show log lines with any tag and the log level INFO or higher. * @return self instance for chaining. */ - default T setLogcatFilterSpecs(String format) { + default T setLogcatFilterSpecs(List format) { return amend(LOGCAT_FILTER_SPECS_OPTION, format); } /** * Get the logcat filter format. * - * @return Format specifier. + * @return Format specifier. See the documentation on {@link #setLogcatFilterSpecs(List)} for more details. */ - default Optional getLogcatFilterSpecs() { - return Optional.ofNullable((String) getCapability(LOGCAT_FILTER_SPECS_OPTION)); + default Optional> getLogcatFilterSpecs() { + //noinspection unchecked + return Optional.ofNullable((List) getCapability(LOGCAT_FILTER_SPECS_OPTION)); } } From eac05b1bb13bfefeab758c4438ad31e6b49876f1 Mon Sep 17 00:00:00 2001 From: Auto81 <48491431+Auto81@users.noreply.github.com> Date: Mon, 20 Jan 2025 20:15:03 +0000 Subject: [PATCH 406/501] fix: Use WeakHashMap for caching proxy classes (#2260) --- .../io/appium/java_client/proxy/Helpers.java | 7 ++-- .../tests/combined/CombinedWidgetTest.java | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index d162c3ed5..7224d763d 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -31,9 +31,9 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; +import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import java.util.WeakHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -50,7 +50,8 @@ public class Helpers { // the performance and to avoid extensive memory usage for our case, where // the amount of instrumented proxy classes we create is low in comparison to the amount // of proxy instances. - private static final ConcurrentMap> CACHED_PROXY_CLASSES = new ConcurrentHashMap<>(); + private static final Map> CACHED_PROXY_CLASSES = + Collections.synchronizedMap(new WeakHashMap<>()); private Helpers() { } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java index 3c1c9145d..26e0d2f74 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedWidgetTest.java @@ -12,20 +12,29 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.lessThan; import static org.openqa.selenium.support.PageFactory.initElements; @SuppressWarnings({"unchecked", "unused"}) public class CombinedWidgetTest { + /** + * Based on how many Proxy Classes are created during this test class, + * this number is used to determine if the cache is being purged correctly between tests. + */ + private static final int THRESHOLD_SIZE = 50; + /** * Test data generation. * @@ -57,6 +66,7 @@ public static Stream data() { @ParameterizedTest @MethodSource("data") void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, Class widgetClass) { + assertProxyClassCacheGrowth(); initElements(new AppiumFieldDecorator(driver), app); assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSubWidget().getSelfReference().getClass(), @@ -161,4 +171,32 @@ public List getWidgets() { return multipleWidgets; } } + + + /** + * Assert proxy class cache growth for this test class. + * The (@link io.appium.java_client.proxy.Helpers#CACHED_PROXY_CLASSES) should be populated during these tests. + * Prior to the Caching issue being resolved + * - the CACHED_PROXY_CLASSES would grow indefinitely, resulting in an Out Of Memory exception. + * - this ParameterizedTest would have the CACHED_PROXY_CLASSES grow to 266 entries. + */ + private void assertProxyClassCacheGrowth() { + System.gc(); //Trying to force a collection for more accurate check numbers + assertThat( + "Proxy Class Cache threshold is " + THRESHOLD_SIZE, + getCachedProxyClassesSize(), + lessThan(THRESHOLD_SIZE) + ); + } + + private int getCachedProxyClassesSize() { + try { + Field cpc = Class.forName("io.appium.java_client.proxy.Helpers").getDeclaredField("CACHED_PROXY_CLASSES"); + cpc.setAccessible(true); + Map cachedProxyClasses = (Map) cpc.get(null); + return cachedProxyClasses.size(); + } catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } } From b8240570b1ed5fc590d742506253374a0c14e0ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:15:28 +0100 Subject: [PATCH 407/501] build(deps): Bump org.owasp.dependencycheck from 12.0.0 to 12.0.1 (#2261) Bumps org.owasp.dependencycheck from 12.0.0 to 12.0.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 88f4d7558..86a8dbff8 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.0.0' + id 'org.owasp.dependencycheck' version '12.0.1' id 'com.github.johnrengelman.shadow' version '8.1.1' } From 75d095c465ed0d8f20b24f3a8c9e62fc4a902190 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 21 Jan 2025 17:37:43 +0300 Subject: [PATCH 408/501] release: v9.4.0 (#2262) --- CHANGELOG.md | 12 ++++++++++++ README.md | 5 +++-- gradle.properties | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09c42fd19..afce5b183 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.4.0_ +- **[ENHANCEMENTS]** + - Implement `HasBiDi` interface support in `AppiumDriver` [#2250](https://github.com/appium/java-client/pull/2250), [#2254](https://github.com/appium/java-client/pull/2254), [#2256](https://github.com/appium/java-client/pull/2256) + - Add compatibility with Selenium `4.28.0` [#2249](https://github.com/appium/java-client/pull/2249) +- **[BUG FIX]** + - Fix scroll issue in flutter integration driver [#2227](https://github.com/appium/java-client/pull/2227) + - Fix the definition of `logcatFilterSpecs` option [#2258](https://github.com/appium/java-client/pull/2258) + - Use `WeakHashMap` for caching proxy classes [#2260](https://github.com/appium/java-client/pull/2260) +- **[DEPENDENCY UPDATES]** + - Bump minimum supported Selenium version from `4.19.0` to `4.26.0` [#2246](https://github.com/appium/java-client/pull/2246) + - Bump Apache Commons Lang from `3.15.0` to `3.16.1` [#2220](https://github.com/appium/java-client/pull/2220), [#2228](https://github.com/appium/java-client/pull/2228) + - Bump SLF4J from `2.0.13` to `2.0.16` [#2221](https://github.com/appium/java-client/pull/2221) _9.3.0_ - **[ENHANCEMENTS]** diff --git a/README.md b/README.md index 91e61c688..2ca984af3 100644 --- a/README.md +++ b/README.md @@ -94,8 +94,9 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client -----------------------------------------------------------------------------------------------------|----------------- - `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0` +----------------------------------------------------------------------------------------------------|----------------------------- +`9.4.0` | `4.26.0`, `4.27.0`, `4.28.0` + `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0`, `4.23.1`, `4.24.0`, `4.25.0`, `4.26.0`, `4.27.0` `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` N/A | `4.14.0` diff --git a/gradle.properties b/gradle.properties index 1bd7b6aed..4f5bf63fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.26.0 # Please increment the value in a release -appiumClient.version=9.3.0 +appiumClient.version=9.4.0 From 8d882c75faebdc2e6dbde79a0bd388ab2ada45d7 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 27 Jan 2025 18:55:00 +0300 Subject: [PATCH 409/501] build(deps): Use new coordinates of Gradle Shadow plugin (#2264) The maintenance of the plugin was transferred to the GradleUp organization to ensure future development, see https://github.com/GradleUp/shadow/issues/908. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 86a8dbff8..3ec8bb004 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '12.0.1' - id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.gradleup.shadow' version '8.3.5' } repositories { From 2745ecf55f33a20205579f3d0659a1373eb68315 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:21:41 +0300 Subject: [PATCH 410/501] build(deps): Bump com.gradleup.shadow from 8.3.5 to 8.3.6 (#2265) Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 8.3.5 to 8.3.6. - [Release notes](https://github.com/GradleUp/shadow/releases) - [Commits](https://github.com/GradleUp/shadow/compare/8.3.5...8.3.6) --- updated-dependencies: - dependency-name: com.gradleup.shadow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3ec8bb004..5ce55a488 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '12.0.1' - id 'com.gradleup.shadow' version '8.3.5' + id 'com.gradleup.shadow' version '8.3.6' } repositories { From 265bde644a6a4006d980c549231efc24886ed274 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 10:43:56 +0300 Subject: [PATCH 411/501] build(deps): Bump com.google.code.gson:gson from 2.11.0 to 2.12.1 (#2267) Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.11.0 to 2.12.1. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.11.0...gson-parent-2.12.1) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5ce55a488..0e8e00c21 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ dependencies { } } } - implementation 'com.google.code.gson:gson:2.11.0' + implementation 'com.google.code.gson:gson:2.12.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" } From 15229beab2e4738612606d34ab26a306d85b1e1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:46:13 +0300 Subject: [PATCH 412/501] build(deps): Bump org.owasp.dependencycheck from 12.0.1 to 12.0.2 (#2266) Bumps org.owasp.dependencycheck from 12.0.1 to 12.0.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0e8e00c21..783d39e24 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.0.1' + id 'org.owasp.dependencycheck' version '12.0.2' id 'com.gradleup.shadow' version '8.3.6' } From eda193c37049ba92742ca882ad39490fa4561945 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 19:59:46 +0300 Subject: [PATCH 413/501] build(deps): Bump org.owasp.dependencycheck from 12.0.2 to 12.1.0 (#2269) Bumps org.owasp.dependencycheck from 12.0.2 to 12.1.0. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 783d39e24..9ccff1500 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.0.2' + id 'org.owasp.dependencycheck' version '12.1.0' id 'com.gradleup.shadow' version '8.3.6' } From 6b6de17409a26c080597e95ffee15c2a430b101a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 20:27:58 +0300 Subject: [PATCH 414/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2270) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.9.2 to 5.9.3. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.9.2...webdrivermanager-5.9.3) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 9ccff1500..90fa79f9a 100644 --- a/build.gradle +++ b/build.gradle @@ -213,7 +213,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:5.9.2') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.3') { exclude group: 'org.seleniumhq.selenium' } } @@ -257,7 +257,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:5.9.2') { + implementation('io.github.bonigarcia:webdrivermanager:5.9.3') { exclude group: 'org.seleniumhq.selenium' } } From 3c5d12be5b15120a697b69e6e8b8b8d13185f6e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:12:43 +0300 Subject: [PATCH 415/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.11.4 to 5.12.0 (#2272) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.11.4 to 5.12.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.4...r5.12.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 90fa79f9a..3a164d7a9 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.11.4' + implementation 'org.junit.jupiter:junit-jupiter:5.12.0' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From eff2b601b1542b59d411d39055346b28915f2283 Mon Sep 17 00:00:00 2001 From: Alexander <2487708+alexanderkaiser@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:58:39 +0100 Subject: [PATCH 416/501] feat: Allow extension capability keys to contain dot characters (#2271) --- .../remote/options/W3CCapabilityKeys.java | 2 +- .../remote/options/BaseOptionsTest.java | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/test/java/io/appium/java_client/remote/options/BaseOptionsTest.java diff --git a/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java b/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java index b29150311..09ff1680f 100644 --- a/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java +++ b/src/main/java/io/appium/java_client/remote/options/W3CCapabilityKeys.java @@ -23,7 +23,7 @@ public class W3CCapabilityKeys implements Predicate { public static final W3CCapabilityKeys INSTANCE = new W3CCapabilityKeys(); private static final Predicate ACCEPTED_W3C_PATTERNS = Stream.of( - "^[\\w-]+:.*$", + "^[\\w-\\.]+:.*$", "^acceptInsecureCerts$", "^browserName$", "^browserVersion$", diff --git a/src/test/java/io/appium/java_client/remote/options/BaseOptionsTest.java b/src/test/java/io/appium/java_client/remote/options/BaseOptionsTest.java new file mode 100644 index 000000000..50e36818d --- /dev/null +++ b/src/test/java/io/appium/java_client/remote/options/BaseOptionsTest.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.remote.options; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BaseOptionsTest { + + @ParameterizedTest + @CsvSource({ + "test, appium:test", + "appium:test, appium:test", + "browserName, browserName", + "digital.ai:accessKey, digital.ai:accessKey", + "digital-ai:accessKey, digital-ai:accessKey", + "digital-ai:my_custom-cap:xyz, digital-ai:my_custom-cap:xyz", + "digital-ai:my_custom-cap?xyz, digital-ai:my_custom-cap?xyz", + }) + void verifyW3CMapping(String capName, String expected) { + var w3cName = BaseOptions.toW3cName(capName); + assertEquals(expected, w3cName); + } +} \ No newline at end of file From b74e807921f13ad6d3e050ebd37648265b7b0ae9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 12:07:48 +0300 Subject: [PATCH 417/501] build(deps): Bump slf4jVersion from 2.0.16 to 2.0.17 (#2274) Bumps `slf4jVersion` from 2.0.16 to 2.0.17. Updates `org.slf4j:slf4j-api` from 2.0.16 to 2.0.17 Updates `org.slf4j:slf4j-simple` from 2.0.16 to 2.0.17 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3a164d7a9..17f6e1ed4 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ java { ext { seleniumVersion = project.property('selenium.version') appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.16' + slf4jVersion = '2.0.17' } dependencies { From aa42e785c8f2128d56b596db3469a50234c32426 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 10 Mar 2025 14:01:24 +0100 Subject: [PATCH 418/501] feat: Add StorageClient (#2275) --- .../plugins/storage/StorageClient.java | 248 ++++++++++++++++++ .../plugins/storage/StorageItem.java | 10 + .../plugins/storage/StorageUtils.java | 90 +++++++ .../java_client/plugin/StorageTest.java | 62 +++++ 4 files changed, 410 insertions(+) create mode 100644 src/main/java/io/appium/java_client/plugins/storage/StorageClient.java create mode 100644 src/main/java/io/appium/java_client/plugins/storage/StorageItem.java create mode 100644 src/main/java/io/appium/java_client/plugins/storage/StorageUtils.java create mode 100644 src/test/java/io/appium/java_client/plugin/StorageTest.java diff --git a/src/main/java/io/appium/java_client/plugins/storage/StorageClient.java b/src/main/java/io/appium/java_client/plugins/storage/StorageClient.java new file mode 100644 index 000000000..013782ec8 --- /dev/null +++ b/src/main/java/io/appium/java_client/plugins/storage/StorageClient.java @@ -0,0 +1,248 @@ +/* + * 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.plugins.storage; + +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.json.Json; +import org.openqa.selenium.remote.ErrorCodec; +import org.openqa.selenium.remote.codec.AbstractHttpResponseCodec; +import org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec; +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.Contents; +import org.openqa.selenium.remote.http.HttpClient; +import org.openqa.selenium.remote.http.HttpHeader; +import org.openqa.selenium.remote.http.HttpMethod; +import org.openqa.selenium.remote.http.HttpRequest; +import org.openqa.selenium.remote.http.HttpResponse; +import org.openqa.selenium.remote.http.WebSocket; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +import static io.appium.java_client.plugins.storage.StorageUtils.calcSha1Digest; +import static io.appium.java_client.plugins.storage.StorageUtils.streamFileToWebSocket; + +/** + * This is a Java implementation of the Appium server storage plugin client. + * See the plugin README + * for more details. + */ +public class StorageClient { + public static final String PREFIX = "/storage"; + private final Json json = new Json(); + private final AbstractHttpResponseCodec responseCodec = new W3CHttpResponseCodec(); + private final ErrorCodec errorCodec = ErrorCodec.createDefault(); + + private final URL baseUrl; + private final HttpClient httpClient; + + public StorageClient(URL baseUrl) { + this.baseUrl = baseUrl; + this.httpClient = HttpClient.Factory.createDefault().createClient(baseUrl); + } + + public StorageClient(ClientConfig clientConfig) { + this.httpClient = HttpClient.Factory.createDefault().createClient(clientConfig); + this.baseUrl = clientConfig.baseUrl(); + } + + /** + * Adds a local file to the server storage. + * The remote file name is be set to the same value as the local file name. + * + * @param file File instance. + */ + public void add(File file) { + add(file, file.getName()); + } + + /** + * Adds a local file to the server storage. + * + * @param file File instance. + * @param name The remote file name. + */ + public void add(File file, String name) { + var request = new HttpRequest(HttpMethod.POST, formatPath(baseUrl, PREFIX, "add").toString()); + var httpResponse = httpClient.execute(setJsonPayload(request, Map.of( + "name", name, + "sha1", calcSha1Digest(file) + ))); + Map value = requireResponseValue(httpResponse); + final var wsTtlMs = (Long) value.get("ttlMs"); + //noinspection unchecked + var wsInfo = (Map) value.get("ws"); + var streamWsPathname = (String) wsInfo.get("stream"); + var eventWsPathname = (String) wsInfo.get("events"); + final var completion = new CountDownLatch(1); + final var lastException = new AtomicReference(null); + try (var streamWs = httpClient.openSocket( + new HttpRequest(HttpMethod.POST, formatPath(baseUrl, streamWsPathname).toString()), + new WebSocket.Listener() {} + ); var eventsWs = httpClient.openSocket( + new HttpRequest(HttpMethod.POST, formatPath(baseUrl, eventWsPathname).toString()), + new EventWsListener(lastException, completion) + )) { + streamFileToWebSocket(file, streamWs); + streamWs.close(); + if (!completion.await(wsTtlMs, TimeUnit.MILLISECONDS)) { + throw new IllegalStateException(String.format( + "Could not receive a confirmation about adding '%s' to the server storage within %sms timeout", + name, wsTtlMs + )); + } + var exc = lastException.get(); + if (exc != null) { + throw exc instanceof RuntimeException ? (RuntimeException) exc : new WebDriverException(exc); + } + } catch (InterruptedException e) { + throw new WebDriverException(e); + } + } + + /** + * Lists items that exist in the storage. + * + * @return All storage items. + */ + public List list() { + var request = new HttpRequest(HttpMethod.GET, formatPath(baseUrl, PREFIX, "list").toString()); + var httpResponse = httpClient.execute(request); + List> items = requireResponseValue(httpResponse); + return items.stream().map(item -> new StorageItem( + (String) item.get("name"), + (String) item.get("path"), + (Long) item.get("size") + )).collect(Collectors.toList()); + } + + /** + * Deletes an item from the server storage. + * + * @param name The name of the item to be deleted. + * @return true if the dletion was successful. + */ + public boolean delete(String name) { + var request = new HttpRequest(HttpMethod.POST, formatPath(baseUrl, PREFIX, "delete").toString()); + var httpResponse = httpClient.execute(setJsonPayload(request, Map.of( + "name", name + ))); + return requireResponseValue(httpResponse); + } + + /** + * Resets all items of the server storage. + */ + public void reset() { + var request = new HttpRequest(HttpMethod.POST, formatPath(baseUrl, PREFIX, "reset").toString()); + var httpResponse = httpClient.execute(request); + requireResponseValue(httpResponse); + } + + private static URL formatPath(URL url, String... suffixes) { + if (suffixes.length == 0) { + return url; + } + try { + var uri = url.toURI(); + var updatedPath = (uri.getPath() + "/" + String.join("/", suffixes)).replaceAll("(/{2,})", "/"); + return new URI( + uri.getScheme(), + uri.getAuthority(), + uri.getHost(), + uri.getPort(), + updatedPath, + uri.getQuery(), + uri.getFragment() + ).toURL(); + } catch (URISyntaxException | MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + + private HttpRequest setJsonPayload(HttpRequest request, Map payload) { + var strData = json.toJson(payload); + var data = strData.getBytes(StandardCharsets.UTF_8); + request.setHeader(HttpHeader.ContentLength.getName(), String.valueOf(data.length)); + request.setHeader(HttpHeader.ContentType.getName(), "application/json; charset=utf-8"); + request.setContent(Contents.bytes(data)); + return request; + } + + private T requireResponseValue(HttpResponse httpResponse) { + var response = responseCodec.decode(httpResponse); + var value = response.getValue(); + if (value instanceof WebDriverException) { + throw (WebDriverException) value; + } + //noinspection unchecked + return (T) response.getValue(); + } + + private final class EventWsListener implements WebSocket.Listener { + private final AtomicReference lastException; + private final CountDownLatch completion; + + public EventWsListener(AtomicReference lastException, CountDownLatch completion) { + this.lastException = lastException; + this.completion = completion; + } + + @Override + public void onBinary(byte[] data) { + extractException(new String(data, StandardCharsets.UTF_8)).ifPresent(lastException::set); + completion.countDown(); + } + + @Override + public void onText(CharSequence data) { + extractException(data.toString()).ifPresent(lastException::set); + completion.countDown(); + } + + @Override + public void onError(Throwable cause) { + lastException.set(cause); + completion.countDown(); + } + + private Optional extractException(String payload) { + try { + Map record = json.toType(payload, Json.MAP_TYPE); + //noinspection unchecked + var value = (Map) record.get("value"); + if ((Boolean) value.get("success")) { + return Optional.empty(); + } + return Optional.of(errorCodec.decode(record)); + } catch (Exception e) { + return Optional.of(new WebDriverException(payload, e)); + } + } + } +} diff --git a/src/main/java/io/appium/java_client/plugins/storage/StorageItem.java b/src/main/java/io/appium/java_client/plugins/storage/StorageItem.java new file mode 100644 index 000000000..17ae1472e --- /dev/null +++ b/src/main/java/io/appium/java_client/plugins/storage/StorageItem.java @@ -0,0 +1,10 @@ +package io.appium.java_client.plugins.storage; + +import lombok.Value; + +@Value +public class StorageItem { + String name; + String path; + long size; +} diff --git a/src/main/java/io/appium/java_client/plugins/storage/StorageUtils.java b/src/main/java/io/appium/java_client/plugins/storage/StorageUtils.java new file mode 100644 index 000000000..3ef6c943c --- /dev/null +++ b/src/main/java/io/appium/java_client/plugins/storage/StorageUtils.java @@ -0,0 +1,90 @@ +/* + * 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.plugins.storage; + +import org.openqa.selenium.remote.http.WebSocket; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Formatter; + +public class StorageUtils { + private static final int BUFFER_SIZE = 0xFFFF; + + private StorageUtils() { + } + + /** + * Calculates SHA1 hex digest of the given file. + * + * @param source The file instance to calculate the hash for. + * @return Hash digest represented as a string of hexadecimal numbers. + */ + public static String calcSha1Digest(File source) { + MessageDigest sha1sum; + try { + sha1sum = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + var buffer = new byte[BUFFER_SIZE]; + int bytesRead; + try (var in = new BufferedInputStream(new FileInputStream(source))) { + while ((bytesRead = in.read(buffer)) != -1) { + sha1sum.update(buffer, 0, bytesRead); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return byteToHex(sha1sum.digest()); + } + + /** + * Feeds the content of the given file to the provided web socket. + * + * @param source The source file instance. + * @param socket The destination web socket. + */ + public static void streamFileToWebSocket(File source, WebSocket socket) { + var buffer = new byte[BUFFER_SIZE]; + int bytesRead; + try (var in = new BufferedInputStream(new FileInputStream(source))) { + while ((bytesRead = in.read(buffer)) != -1) { + var currentBuffer = new byte[bytesRead]; + System.arraycopy(buffer, 0, currentBuffer, 0, bytesRead); + socket.sendBinary(currentBuffer); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static String byteToHex(final byte[] hash) { + var formatter = new Formatter(); + for (byte b : hash) { + formatter.format("%02x", b); + } + var result = formatter.toString(); + formatter.close(); + return result; + } +} diff --git a/src/test/java/io/appium/java_client/plugin/StorageTest.java b/src/test/java/io/appium/java_client/plugin/StorageTest.java new file mode 100644 index 000000000..b1042a971 --- /dev/null +++ b/src/test/java/io/appium/java_client/plugin/StorageTest.java @@ -0,0 +1,62 @@ +/* + * 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.plugin; + +import io.appium.java_client.TestUtils; +import io.appium.java_client.plugins.storage.StorageClient; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.MalformedURLException; +import java.net.URL; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class StorageTest { + private StorageClient storageClient; + + @BeforeEach + void before() throws MalformedURLException { + // These tests assume Appium server with storage plugin is already running + // at the given baseUrl + Assumptions.assumeFalse(TestUtils.isCiEnv()); + storageClient = new StorageClient(new URL("http://127.0.0.1:4723")); + storageClient.reset(); + } + + @Test + void shouldBeAbleToPerformBasicStorageActions() { + assertTrue(storageClient.list().isEmpty()); + var name = "hello appium - saved page.htm"; + var testFile = TestUtils.resourcePathToAbsolutePath("html/" + name).toFile(); + storageClient.add(testFile); + assertItemsCount(1); + assertTrue(storageClient.delete(name)); + assertItemsCount(0); + storageClient.add(testFile); + assertItemsCount(1); + storageClient.reset(); + assertItemsCount(0); + } + + private void assertItemsCount(int expected) { + var items = storageClient.list(); + assertEquals(expected, items.size()); + } +} From f2b824e1d5ff1e7179e791e16225839be100de36 Mon Sep 17 00:00:00 2001 From: muhammadyunus99 Date: Mon, 10 Mar 2025 20:33:43 +0200 Subject: [PATCH 419/501] docs: Replace deprecated new URL(String) with URI(String).toURL() (#2263) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2ca984af3..be1f8e546 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ UiAutomator2Options options = new UiAutomator2Options() .setApp("/home/myapp.apk"); AndroidDriver driver = new AndroidDriver( // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub - new URL("http://127.0.0.1:4723"), options + new URI("http://127.0.0.1:4723").toURL(), options ); try { WebElement el = driver.findElement(AppiumBy.xpath("//Button")); @@ -193,7 +193,7 @@ XCUITestOptions options = new XCUITestOptions() .setApp("/home/myapp.ipa"); IOSDriver driver = new IOSDriver( // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub - new URL("http://127.0.0.1:4723"), options + new URI("http://127.0.0.1:4723").toURL(), options ); try { WebElement el = driver.findElement(AppiumBy.accessibilityId("myId")); @@ -214,7 +214,7 @@ BaseOptions options = new BaseOptions() .amend("mycapability2", "capvalue2"); AppiumDriver driver = new AppiumDriver( // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub - new URL("http://127.0.0.1:4723"), options + new URI("http://127.0.0.1:4723").toURL(), options ); try { WebElement el = driver.findElement(AppiumBy.className("myClass")); From c145c7d3b1ba988f237d924712cb07abc5292fff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 20:35:22 +0300 Subject: [PATCH 420/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.12.0 to 5.12.1 (#2278) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.12.0 to 5.12.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.12.0...r5.12.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 17f6e1ed4..63cdc954c 100644 --- a/build.gradle +++ b/build.gradle @@ -195,7 +195,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.12.0' + implementation 'org.junit.jupiter:junit-jupiter:5.12.1' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From febcffb812dd18296fb2acdb5a7c6525d3303d51 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 27 Mar 2025 11:16:20 +0300 Subject: [PATCH 421/501] fix: Add explicit dependency on JSR 305 annotations library (#2280) --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 63cdc954c..095975515 100644 --- a/build.gradle +++ b/build.gradle @@ -67,6 +67,7 @@ dependencies { } implementation 'com.google.code.gson:gson:2.12.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" + implementation 'com.google.code.findbugs:jsr305:3.0.2' } dependencyCheck { From fcde595162266590c95fb7a7eade1e0611c0e340 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 12:52:36 +0300 Subject: [PATCH 422/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2279) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.9.3 to 6.0.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.9.3...webdrivermanager-6.0.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 095975515..33bb7fd4c 100644 --- a/build.gradle +++ b/build.gradle @@ -214,7 +214,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:5.9.3') { + implementation('io.github.bonigarcia:webdrivermanager:6.0.0') { exclude group: 'org.seleniumhq.selenium' } } @@ -258,7 +258,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:5.9.3') { + implementation('io.github.bonigarcia:webdrivermanager:6.0.0') { exclude group: 'org.seleniumhq.selenium' } } From 9a59abddfc670367155578291ae53b536c43284b Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 28 Mar 2025 08:20:50 +0300 Subject: [PATCH 423/501] refactor: Migrate from JSR 305 to JSpecify (#2281) --- build.gradle | 2 +- .../io/appium/java_client/AppiumClientConfig.java | 2 +- src/main/java/io/appium/java_client/AppiumDriver.java | 4 ++-- .../io/appium/java_client/CommandExecutionHelper.java | 2 +- .../java/io/appium/java_client/ComparesImages.java | 2 +- .../java/io/appium/java_client/ExecuteCDPCommand.java | 2 +- .../io/appium/java_client/ExecutesDriverScript.java | 2 +- .../java/io/appium/java_client/InteractsWithApps.java | 2 +- src/main/java/io/appium/java_client/Location.java | 3 +-- .../java/io/appium/java_client/MobileCommand.java | 2 +- .../io/appium/java_client/android/StartsActivity.java | 3 +-- .../java_client/internal/CapabilityHelpers.java | 2 +- .../internal/filters/AppiumUserAgentFilter.java | 7 +++---- .../pagefactory/AppiumElementLocatorFactory.java | 2 +- .../java_client/pagefactory/AppiumFieldDecorator.java | 6 +++--- .../java_client/pagefactory/WidgetInterceptor.java | 8 +++----- .../pagefactory/WidgetListInterceptor.java | 5 ++--- .../java_client/pagefactory/bys/ContentMappedBy.java | 4 ++-- .../pagefactory/bys/builder/AppiumByBuilder.java | 2 +- .../interceptors/InterceptorOfAListOfElements.java | 2 +- .../interceptors/InterceptorOfASingleElement.java | 5 ++--- .../pagefactory/utils/WebDriverUnpackUtility.java | 3 +-- .../java/io/appium/java_client/proxy/Helpers.java | 2 +- .../java_client/remote/AppiumCommandExecutor.java | 11 ++++++----- .../io/appium/java_client/remote/DirectConnect.java | 2 +- .../java_client/remote/SupportsContextSwitching.java | 2 +- .../java_client/remote/options/BaseOptions.java | 4 ++-- .../service/local/AppiumDriverLocalService.java | 2 +- .../service/local/AppiumServiceBuilder.java | 4 ++-- .../appium/java_client/ws/StringWebSocketClient.java | 2 +- src/test/java/io/appium/java_client/TestUtils.java | 2 +- 31 files changed, 48 insertions(+), 55 deletions(-) diff --git a/build.gradle b/build.gradle index 33bb7fd4c..1f97df659 100644 --- a/build.gradle +++ b/build.gradle @@ -67,7 +67,7 @@ dependencies { } implementation 'com.google.code.gson:gson:2.12.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" - implementation 'com.google.code.findbugs:jsr305:3.0.2' + implementation 'org.jspecify:jspecify:1.0.0' } dependencyCheck { diff --git a/src/main/java/io/appium/java_client/AppiumClientConfig.java b/src/main/java/io/appium/java_client/AppiumClientConfig.java index e6ebfd0bb..49097f341 100644 --- a/src/main/java/io/appium/java_client/AppiumClientConfig.java +++ b/src/main/java/io/appium/java_client/AppiumClientConfig.java @@ -18,12 +18,12 @@ import io.appium.java_client.internal.filters.AppiumIdempotencyFilter; import io.appium.java_client.internal.filters.AppiumUserAgentFilter; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.Credentials; import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.Filter; -import javax.annotation.Nullable; import javax.net.ssl.SSLContext; import java.net.Proxy; import java.net.URI; diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 01065fe48..4c641fd2b 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -25,6 +25,7 @@ import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import lombok.Getter; +import org.jspecify.annotations.NonNull; import org.openqa.selenium.Capabilities; import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.OutputType; @@ -47,7 +48,6 @@ import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; -import javax.annotation.Nonnull; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -275,7 +275,7 @@ public Optional maybeGetBiDi() { } @Override - @Nonnull + @NonNull public BiDi getBiDi() { var webSocketUrl = ((BaseOptions) this.capabilities).getWebSocketUrl().orElseThrow( () -> { diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index e64470b38..b56a2f4ac 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -16,9 +16,9 @@ package io.appium.java_client; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.remote.Response; -import javax.annotation.Nullable; import java.util.Collections; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/ComparesImages.java b/src/main/java/io/appium/java_client/ComparesImages.java index 5a9a58b1c..4f44d6e0a 100644 --- a/src/main/java/io/appium/java_client/ComparesImages.java +++ b/src/main/java/io/appium/java_client/ComparesImages.java @@ -23,8 +23,8 @@ import io.appium.java_client.imagecomparison.OccurrenceMatchingResult; import io.appium.java_client.imagecomparison.SimilarityMatchingOptions; import io.appium.java_client.imagecomparison.SimilarityMatchingResult; +import org.jspecify.annotations.Nullable; -import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.nio.file.Files; diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java index 8b9f18317..7114da787 100644 --- a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -16,9 +16,9 @@ package io.appium.java_client; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.remote.Response; -import javax.annotation.Nullable; import java.util.Collections; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/ExecutesDriverScript.java b/src/main/java/io/appium/java_client/ExecutesDriverScript.java index 1ffebedb9..2509dba85 100644 --- a/src/main/java/io/appium/java_client/ExecutesDriverScript.java +++ b/src/main/java/io/appium/java_client/ExecutesDriverScript.java @@ -18,9 +18,9 @@ import io.appium.java_client.driverscripts.ScriptOptions; import io.appium.java_client.driverscripts.ScriptValue; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.remote.Response; -import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index 9fe25dc24..0ca018abb 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -22,10 +22,10 @@ import io.appium.java_client.appmanagement.BaseOptions; import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions; import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.UnsupportedCommandException; -import javax.annotation.Nullable; import java.time.Duration; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/Location.java b/src/main/java/io/appium/java_client/Location.java index 336c09797..322665a42 100644 --- a/src/main/java/io/appium/java_client/Location.java +++ b/src/main/java/io/appium/java_client/Location.java @@ -19,8 +19,7 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; - -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * Represents the physical location. diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 029c1abb7..b4df90047 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -21,10 +21,10 @@ import io.appium.java_client.imagecomparison.ComparisonMode; import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions; import io.appium.java_client.screenrecording.BaseStopScreenRecordingOptions; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.http.HttpMethod; -import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Collections; 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 9f56d7b1a..23b0ad7a9 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -19,10 +19,9 @@ import io.appium.java_client.CanRememberExtensionPresence; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.UnsupportedCommandException; -import javax.annotation.Nullable; - import java.util.Map; import static io.appium.java_client.MobileCommand.CURRENT_ACTIVITY; diff --git a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java index 855a40cdb..345e60a9c 100644 --- a/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java +++ b/src/main/java/io/appium/java_client/internal/CapabilityHelpers.java @@ -16,9 +16,9 @@ package io.appium.java_client.internal; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.Capabilities; -import javax.annotation.Nullable; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; diff --git a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java index d4f1842ce..b8086e1f8 100644 --- a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java @@ -17,14 +17,13 @@ package io.appium.java_client.internal.filters; import io.appium.java_client.internal.Config; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.remote.http.AddSeleniumUserAgent; import org.openqa.selenium.remote.http.Filter; import org.openqa.selenium.remote.http.HttpHandler; import org.openqa.selenium.remote.http.HttpHeader; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - /** * Manage Appium Client configurations. */ @@ -41,7 +40,7 @@ public class AppiumUserAgentFilter implements Filter { */ public static final String USER_AGENT = buildUserAgentHeaderValue(AddSeleniumUserAgent.USER_AGENT); - private static String buildUserAgentHeaderValue(@Nonnull String previousUA) { + private static String buildUserAgentHeaderValue(@NonNull String previousUA) { return String.format("%s%s (%s)", USER_AGENT_PREFIX, Config.main().getValue(VERSION_KEY, String.class), previousUA); } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java index 77b3120fc..f423d1dca 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -19,9 +19,9 @@ import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder; import io.appium.java_client.pagefactory.locator.CacheableElementLocatorFactory; import io.appium.java_client.pagefactory.locator.CacheableLocator; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.SearchContext; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 05fa41a42..ccbed8fac 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -19,6 +19,8 @@ import io.appium.java_client.internal.CapabilityHelpers; import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.locator.CacheableLocator; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; @@ -30,8 +32,6 @@ import org.openqa.selenium.support.pagefactory.ElementLocatorFactory; import org.openqa.selenium.support.pagefactory.FieldDecorator; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -123,7 +123,7 @@ contextReference, duration, new WidgetByBuilder(platform, automation) ); } - @Nonnull + @NonNull private static WeakReference requireWebDriverReference(SearchContext searchContext) { var wd = unpackObjectFromSearchContext( checkNotNull(searchContext, "The provided search context cannot be null"), diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java index bfc358bd8..46d946628 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java @@ -19,11 +19,11 @@ import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.interceptors.InterceptorOfASingleElement; import io.appium.java_client.pagefactory.locator.CacheableLocator; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.PageFactory; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -48,11 +48,9 @@ public class WidgetInterceptor extends InterceptorOfASingleElement { * Proxy interceptor class for widgets. */ public WidgetInterceptor( - @Nullable - CacheableLocator locator, + @Nullable CacheableLocator locator, WeakReference driverReference, - @Nullable - WeakReference cachedElementReference, + @Nullable WeakReference cachedElementReference, Map> instantiationMap, Duration duration ) { diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java index ff9983f8c..bb4bb1889 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java @@ -19,10 +19,10 @@ import io.appium.java_client.pagefactory.bys.ContentType; import io.appium.java_client.pagefactory.interceptors.InterceptorOfAListOfElements; import io.appium.java_client.pagefactory.locator.CacheableLocator; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -50,8 +50,7 @@ public class WidgetListInterceptor extends InterceptorOfAListOfElements { * Proxy interceptor class for lists of widgets. */ public WidgetListInterceptor( - @Nullable - CacheableLocator locator, + @Nullable CacheableLocator locator, WeakReference driver, Map> instantiationMap, Class declaredType, diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java index 6c0c0f99f..14967c6d7 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/ContentMappedBy.java @@ -17,11 +17,11 @@ package io.appium.java_client.pagefactory.bys; import lombok.EqualsAndHashCode; +import org.jspecify.annotations.NonNull; import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; -import javax.annotation.Nonnull; import java.util.List; import java.util.Map; @@ -43,7 +43,7 @@ public ContentMappedBy(Map map) { * @param type required content type {@link ContentType} * @return self-reference. */ - public By useContent(@Nonnull ContentType type) { + public By useContent(@NonNull ContentType type) { requireNonNull(type); currentContent = type; return this; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java index 0e7146a0c..73f6717aa 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/AppiumByBuilder.java @@ -16,11 +16,11 @@ package io.appium.java_client.pagefactory.bys.builder; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.By; import org.openqa.selenium.support.pagefactory.AbstractAnnotations; import org.openqa.selenium.support.pagefactory.ByAll; -import javax.annotation.Nullable; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java index fc35f9992..3f8bd4fdf 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfAListOfElements.java @@ -17,10 +17,10 @@ package io.appium.java_client.pagefactory.interceptors; import io.appium.java_client.proxy.MethodCallListener; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; -import javax.annotation.Nullable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java index 738f49823..968ff824d 100644 --- a/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java +++ b/src/main/java/io/appium/java_client/pagefactory/interceptors/InterceptorOfASingleElement.java @@ -17,13 +17,13 @@ package io.appium.java_client.pagefactory.interceptors; import io.appium.java_client.proxy.MethodCallListener; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.WrapsDriver; import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.support.pagefactory.ElementLocator; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.Objects; @@ -34,8 +34,7 @@ public abstract class InterceptorOfASingleElement implements MethodCallListener private final WeakReference driverReference; public InterceptorOfASingleElement( - @Nullable - ElementLocator locator, + @Nullable ElementLocator locator, WeakReference driverReference ) { this.locator = locator; diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 8b59d7ba6..997460be5 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -18,14 +18,13 @@ import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.ContextAware; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WrapsDriver; import org.openqa.selenium.WrapsElement; -import javax.annotation.Nullable; - import java.util.Optional; import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index 7224d763d..f9fae7768 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -26,8 +26,8 @@ import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatchers; +import org.jspecify.annotations.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 84ac2c089..bf02271d3 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -20,6 +20,8 @@ import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.internal.ReflectionHelpers; import lombok.Getter; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Command; @@ -34,12 +36,11 @@ import org.openqa.selenium.remote.ResponseCodec; import org.openqa.selenium.remote.codec.w3c.W3CHttpCommandCodec; import org.openqa.selenium.remote.http.HttpClient; +import org.openqa.selenium.remote.http.HttpClient.Factory; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; import org.openqa.selenium.remote.service.DriverService; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.IOException; import java.net.ConnectException; import java.net.MalformedURLException; @@ -69,10 +70,10 @@ public class AppiumCommandExecutor extends HttpCommandExecutor { * @param appiumClientConfig take a look at {@link AppiumClientConfig} */ public AppiumCommandExecutor( - @Nonnull Map additionalCommands, + @NonNull Map additionalCommands, @Nullable DriverService service, - @Nullable HttpClient.Factory httpClientFactory, - @Nonnull AppiumClientConfig appiumClientConfig) { + @Nullable Factory httpClientFactory, + @NonNull AppiumClientConfig appiumClientConfig) { super(additionalCommands, appiumClientConfig, ofNullable(httpClientFactory).orElseGet(AppiumCommandExecutor::getDefaultClientFactory) diff --git a/src/main/java/io/appium/java_client/remote/DirectConnect.java b/src/main/java/io/appium/java_client/remote/DirectConnect.java index 809fdc736..fb1a05c51 100644 --- a/src/main/java/io/appium/java_client/remote/DirectConnect.java +++ b/src/main/java/io/appium/java_client/remote/DirectConnect.java @@ -18,8 +18,8 @@ import lombok.AccessLevel; import lombok.Getter; +import org.jspecify.annotations.Nullable; -import javax.annotation.Nullable; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java index b126e4fa1..7fad6f0e5 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java +++ b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java @@ -19,12 +19,12 @@ import io.appium.java_client.ExecutesMethod; import io.appium.java_client.MobileCommand; import io.appium.java_client.NoSuchContextException; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.ContextAware; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Response; -import javax.annotation.Nullable; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; diff --git a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java index 7e3ade21f..cc544022c 100644 --- a/src/main/java/io/appium/java_client/remote/options/BaseOptions.java +++ b/src/main/java/io/appium/java_client/remote/options/BaseOptions.java @@ -16,6 +16,7 @@ package io.appium.java_client.remote.options; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.Capabilities; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.Platform; @@ -23,7 +24,6 @@ import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.CapabilityType; -import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Map; @@ -164,4 +164,4 @@ public Object getCapability(String capabilityName) { public static String toW3cName(String capName) { return W3CCapabilityKeys.INSTANCE.test(capName) ? capName : APPIUM_PREFIX + capName; } -} \ No newline at end of file +} diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 8026300ad..1ded306b8 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -18,13 +18,13 @@ import lombok.Getter; import lombok.SneakyThrows; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.os.ExternalProcess; import org.openqa.selenium.remote.service.DriverService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.event.Level; -import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 5dadb6403..3a3529926 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -25,13 +25,13 @@ import io.appium.java_client.service.local.flags.GeneralServerFlag; import io.appium.java_client.service.local.flags.ServerArgument; import lombok.SneakyThrows; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.os.ExecutableFinder; import org.openqa.selenium.remote.Browser; import org.openqa.selenium.remote.service.DriverService; -import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -471,4 +471,4 @@ protected AppiumDriverLocalService createDriverService(File nodeJSExecutable, in return new AppiumDriverLocalService(ipAddress, nodeJSExecutable, nodeJSPort, startupTimeout, nodeArguments, nodeEnvironment).withBasePath(basePath); } -} \ No newline at end of file +} diff --git a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java index 33c5d8aa6..f080c061c 100644 --- a/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java +++ b/src/main/java/io/appium/java_client/ws/StringWebSocketClient.java @@ -16,12 +16,12 @@ package io.appium.java_client.ws; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.WebSocket; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.net.URI; import java.util.List; diff --git a/src/test/java/io/appium/java_client/TestUtils.java b/src/test/java/io/appium/java_client/TestUtils.java index 73d104469..5f8b11ddf 100644 --- a/src/test/java/io/appium/java_client/TestUtils.java +++ b/src/test/java/io/appium/java_client/TestUtils.java @@ -1,11 +1,11 @@ package io.appium.java_client; +import org.jspecify.annotations.Nullable; import org.openqa.selenium.Dimension; import org.openqa.selenium.Point; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebElement; -import javax.annotation.Nullable; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; From 6a6aeeaae792b5ee87cc21edbe3f2fa46601d181 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:17:22 +0300 Subject: [PATCH 424/501] build(deps): Bump org.projectlombok:lombok from 1.18.36 to 1.18.38 (#2284) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.36 to 1.18.38. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.36...v1.18.38) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-version: 1.18.38 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1f97df659..e3a702ad6 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,8 @@ ext { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.36' - annotationProcessor 'org.projectlombok:lombok:1.18.36' + compileOnly 'org.projectlombok:lombok:1.18.38' + annotationProcessor 'org.projectlombok:lombok:1.18.38' if (project.hasProperty("isCI")) { api "org.seleniumhq.selenium:selenium-api:${seleniumVersion}" From 05a4bdf1b7e6f7016d44e08aa8dcc41ba5f1bd43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:17:47 +0300 Subject: [PATCH 425/501] build(deps): Bump org.owasp.dependencycheck from 12.1.0 to 12.1.1 (#2283) Bumps org.owasp.dependencycheck from 12.1.0 to 12.1.1. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-version: 12.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e3a702ad6..26a41a51b 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.1.0' + id 'org.owasp.dependencycheck' version '12.1.1' id 'com.gradleup.shadow' version '8.3.6' } From cad009af51085961579a9483762bb25c9de0bc22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:18:11 +0300 Subject: [PATCH 426/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2285) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-6.0.0...webdrivermanager-6.0.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 26a41a51b..2434c9ccb 100644 --- a/build.gradle +++ b/build.gradle @@ -214,7 +214,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:6.0.0') { + implementation('io.github.bonigarcia:webdrivermanager:6.0.1') { exclude group: 'org.seleniumhq.selenium' } } @@ -258,7 +258,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:6.0.0') { + implementation('io.github.bonigarcia:webdrivermanager:6.0.1') { exclude group: 'org.seleniumhq.selenium' } } From 80806c5e3feb3efe892487fbafd52fc837b498c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:20:45 +0300 Subject: [PATCH 427/501] build(deps): Bump com.google.code.gson:gson from 2.12.1 to 2.13.0 (#2286) Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.12.1 to 2.13.0. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.12.1...gson-parent-2.13.0) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-version: 2.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2434c9ccb..6ad4f7987 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ dependencies { } } } - implementation 'com.google.code.gson:gson:2.12.1' + implementation 'com.google.code.gson:gson:2.13.0' implementation "org.slf4j:slf4j-api:${slf4jVersion}" implementation 'org.jspecify:jspecify:1.0.0' } From 12a0f004d85c89f953d1bca2058ea98c9d960235 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 19:59:51 +0300 Subject: [PATCH 428/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.12.1 to 5.12.2 (#2287) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.12.1 to 5.12.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.12.1...r5.12.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.12.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6ad4f7987..dcad66d7e 100644 --- a/build.gradle +++ b/build.gradle @@ -196,7 +196,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.12.1' + implementation 'org.junit.jupiter:junit-jupiter:5.12.2' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 0cd5eae713c095847b181d937404a7a0be5783fb Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 26 Apr 2025 16:33:46 +0200 Subject: [PATCH 429/501] ci: Tune CC title script --- .github/workflows/pr-title.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 393ca3bd6..1658a2957 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -1,6 +1,7 @@ name: Conventional Commits on: pull_request: + types: [opened, edited, synchronize, reopened] jobs: From cafe304df716f3bedcb9e0a99870aa31f1aa2f72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 16:59:41 +0300 Subject: [PATCH 430/501] build(deps): Bump com.google.code.gson:gson from 2.13.0 to 2.13.1 (#2290) Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.13.0 to 2.13.1. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.13.0...gson-parent-2.13.1) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-version: 2.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dcad66d7e..6f9dec120 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ dependencies { } } } - implementation 'com.google.code.gson:gson:2.13.0' + implementation 'com.google.code.gson:gson:2.13.1' implementation "org.slf4j:slf4j-api:${slf4jVersion}" implementation 'org.jspecify:jspecify:1.0.0' } From 5f2bc1a4d417ee09e0207f62b35d659b368daf2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 18:27:33 +0300 Subject: [PATCH 431/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2289) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-6.0.1...webdrivermanager-6.1.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6f9dec120..5304c65c4 100644 --- a/build.gradle +++ b/build.gradle @@ -214,7 +214,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:6.0.1') { + implementation('io.github.bonigarcia:webdrivermanager:6.1.0') { exclude group: 'org.seleniumhq.selenium' } } @@ -258,7 +258,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:6.0.1') { + implementation('io.github.bonigarcia:webdrivermanager:6.1.0') { exclude group: 'org.seleniumhq.selenium' } } From 3e5f9e2045913d35b859bc37b55453dcebe94324 Mon Sep 17 00:00:00 2001 From: Max B Date: Mon, 28 Apr 2025 12:26:13 -0500 Subject: [PATCH 432/501] feat: Swap check for Widget and WebElement (#2277) --- .../pagefactory/AppiumFieldDecorator.java | 4 +- .../DesktopBrowserCompatibilityTest.java | 3 + .../widget/tests/DefaultStubWidget.java | 83 ++++++++++++++++++- .../tests/combined/CombinedAppTest.java | 4 + 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index ccbed8fac..792932cd4 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -193,8 +193,8 @@ protected boolean isDecoratableList(Field field) { * @return a field value or null. */ public Object decorate(ClassLoader ignored, Field field) { - Object result = defaultElementFieldDecorator.decorate(ignored, field); - return result == null ? decorateWidget(field) : result; + Object result = decorateWidget(field); + return result == null ? defaultElementFieldDecorator.decorate(ignored, field) : result; } @Nullable diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index 40c672ae7..911fefc02 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -21,6 +21,7 @@ import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.pagefactory.HowToUseLocators; +import io.appium.java_client.pagefactory.Widget; import io.appium.java_client.pagefactory.iOSXCUITFindBy; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -37,6 +38,7 @@ import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -69,6 +71,7 @@ public class DesktopBrowserCompatibilityTest { assertNotEquals(0, main.size()); assertNull(trap1); assertNull(trap2); + foundLinks.forEach(element -> assertFalse(Widget.class.isAssignableFrom(element.getClass()))); } finally { driver.quit(); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java index 5977646d7..7de8cf327 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/DefaultStubWidget.java @@ -1,11 +1,17 @@ package io.appium.java_client.pagefactory_tests.widget.tests; import io.appium.java_client.pagefactory.Widget; +import org.jspecify.annotations.Nullable; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.Point; +import org.openqa.selenium.Rectangle; +import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import java.util.List; -public class DefaultStubWidget extends Widget { +public class DefaultStubWidget extends Widget implements WebElement { protected DefaultStubWidget(WebElement element) { super(element); } @@ -22,4 +28,79 @@ public List getSubWidgets() { public String toString() { return getWrappedElement().toString(); } + + @Override + public void click() { + getWrappedElement().click(); + } + + @Override + public void submit() { + getWrappedElement().submit(); + } + + @Override + public void sendKeys(CharSequence... keysToSend) { + getWrappedElement().sendKeys(keysToSend); + } + + @Override + public void clear() { + getWrappedElement().clear(); + } + + @Override + public String getTagName() { + return getWrappedElement().getTagName(); + } + + @Override + public @Nullable String getAttribute(String name) { + return getWrappedElement().getAttribute(name); + } + + @Override + public boolean isSelected() { + return getWrappedElement().isSelected(); + } + + @Override + public boolean isEnabled() { + return getWrappedElement().isEnabled(); + } + + @Override + public String getText() { + return getWrappedElement().getText(); + } + + @Override + public boolean isDisplayed() { + return getWrappedElement().isDisplayed(); + } + + @Override + public Point getLocation() { + return getWrappedElement().getLocation(); + } + + @Override + public Dimension getSize() { + return getWrappedElement().getSize(); + } + + @Override + public Rectangle getRect() { + return getWrappedElement().getRect(); + } + + @Override + public String getCssValue(String propertyName) { + return getWrappedElement().getCssValue(propertyName); + } + + @Override + public X getScreenshotAs(OutputType target) throws WebDriverException { + return getWrappedElement().getScreenshotAs(target); + } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java index c3ee905fb..c7e50ef5f 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/combined/CombinedAppTest.java @@ -6,10 +6,12 @@ import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; import io.appium.java_client.pagefactory_tests.widget.tests.DefaultStubWidget; import io.appium.java_client.pagefactory_tests.widget.tests.android.DefaultAndroidWidget; +import org.hamcrest.Matchers; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import java.util.List; import java.util.stream.Stream; @@ -58,6 +60,8 @@ void checkThatWidgetsAreCreatedCorrectly(AbstractApp app, WebDriver driver, assertThat("Expected widget class was " + widgetClass.getName(), app.getWidget().getSelfReference().getClass(), equalTo(widgetClass)); + assertThat(app.getWidget().getSelfReference(), + Matchers.instanceOf(WebElement.class)); List> classes = app.getWidgets().stream().map(abstractWidget -> abstractWidget .getSelfReference().getClass()) From 5560a56181f7a314090df534cf153f01975ab388 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 20 May 2025 00:27:54 +0300 Subject: [PATCH 433/501] fix: Make unit tests compatible with Selenium 4.33.0+ (#2293) --- .../widget/tests/AbstractStubWebDriver.java | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java index 636d33c4e..d31a5bf93 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/widget/tests/AbstractStubWebDriver.java @@ -11,6 +11,7 @@ import org.openqa.selenium.logging.Logs; import org.openqa.selenium.remote.Response; +import java.time.Duration; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -155,20 +156,72 @@ public Cookie getCookieNamed(String name) { @Override public Timeouts timeouts() { return new Timeouts() { - @Override + /** + * Does nothing. + * + * @param time The amount of time to wait. + * @param unit The unit of measure for {@code time}. + * @return A self reference. + * @deprecated Kept for the backward compatibility, should be removed when a minimum Selenium + * version is bumped to 4.33.0 or higher. + */ + @Deprecated public Timeouts implicitlyWait(long time, TimeUnit unit) { return this; } - @Override + public Timeouts implicitlyWait(Duration duration) { + return this; + } + + /** + * Does nothing. + * + * @param time The timeout value. + * @param unit The unit of time. + * @return A self reference. + * @deprecated Kept for the backward compatibility, should be removed when Selenium client removes + * this method from its interface. + */ + @Deprecated public Timeouts setScriptTimeout(long time, TimeUnit unit) { return this; } - @Override + /** + * Does nothing. + * + * @param duration The timeout value. + * @return A self reference. + * @deprecated Kept for the backward compatibility, should be removed when Selenium client removes + * this method from its interface. + */ + @Deprecated + public Timeouts setScriptTimeout(Duration duration) { + return this; + } + + public Timeouts scriptTimeout(Duration duration) { + return this; + } + + /** + * Does nothing. + * + * @param time The timeout value. + * @param unit The unit of time. + * @return A self reference. + * @deprecated Kept for the backward compatibility, should be removed when Selenium client removes + * this method from its interface. + */ + @Deprecated public Timeouts pageLoadTimeout(long time, TimeUnit unit) { return this; } + + public Timeouts pageLoadTimeout(Duration duration) { + return this; + } }; } From 29843c1450ae1b01497bc03f6a3a45b896b484ef Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Fri, 23 May 2025 16:06:35 +0300 Subject: [PATCH 434/501] build: Bump build dependencies (#2291) * build: Bump Gradle from `8.9` to `8.14` * build: Bump JaCoCo from `0.8.12` to `0.8.13` * build: Bump Checkstyle from `10.17.0` to `10.23.1` * fix: Fix Checkstyle violations in Javadocs New Checkstyle versions introduced a number of improvements/fixes in Javadocs checks, that resulted in new violations reported. * fix: Fix typo in Javadocs --- build.gradle | 6 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 43764 bytes gradlew | 9 +++-- gradlew.bat | 4 +-- .../service/local/ServerBuilderTest.java | 2 +- .../java/io/appium/java_client/AppiumBy.java | 8 ++--- .../nativekey/KeyEventMetaModifier.java | 34 +++++++++--------- .../android/options/EspressoOptions.java | 5 ++- .../android/options/UiAutomator2Options.java | 5 ++- .../java_client/chromium/ChromiumDriver.java | 5 +-- .../chromium/options/ChromiumOptions.java | 2 +- .../flutter/FlutterDriverOptions.java | 5 ++- .../flutter/FlutterIntegrationTestDriver.java | 4 +-- .../gecko/options/GeckoOptions.java | 5 ++- .../ios/options/XCUITestOptions.java | 5 ++- .../java_client/mac/options/Mac2Options.java | 5 ++- .../safari/options/SafariOptions.java | 5 ++- .../windows/options/WindowsOptions.java | 2 +- 18 files changed, 66 insertions(+), 45 deletions(-) diff --git a/build.gradle b/build.gradle index 5304c65c4..c01d2c328 100644 --- a/build.gradle +++ b/build.gradle @@ -75,7 +75,7 @@ dependencyCheck { } jacoco { - toolVersion = '0.8.12' + toolVersion = '0.8.13' } tasks.withType(JacocoReport).configureEach { @@ -91,7 +91,7 @@ jacocoTestReport.dependsOn test apply plugin: 'checkstyle' checkstyle { - toolVersion = '10.17.0' + toolVersion = '10.23.1' configFile = configDirectory.file('appium-style.xml').get().getAsFile() showViolations = true ignoreFailures = false @@ -180,7 +180,7 @@ signing { } wrapper { - gradleVersion = '8.9' + gradleVersion = '8.14' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 35074 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

    9HXbnx{yu=160arMI&0;a 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 z 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 delta 34964 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

    Gn4F+B~IivciU9^t0j-Mgao3 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 diff --git a/gradlew b/gradlew index f5feea6d6..23d15a936 100755 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -206,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -214,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c7..5eed7ee84 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java index d482284b2..bf1df1fe3 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -50,7 +50,7 @@ class ServerBuilderTest { private static final String PATH_TO_APPIUM_NODE_IN_PROPERTIES = getProperty(APPIUM_PATH); /** - * This is the path to the stub main.js file + * This is the path to the stub main.js file. */ private static final Path PATH_T0_TEST_MAIN_JS = TestUtils.resourcePathToAbsolutePath("main.js"); diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index aca01fea7..4314dc891 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -84,10 +84,10 @@ public static By androidDataMatcher(final String dataMatcherString) { } /** - * Refer to https://developer.android.com/training/testing/ui-automator + * Refer to UI Automator . * * @param uiautomatorText is Android UIAutomator string - * @return an instance of {@link AppiumBy.ByAndroidUIAutomator} + * @return an instance of {@link ByAndroidUIAutomator} */ public static By androidUIAutomator(final String uiautomatorText) { return new ByAndroidUIAutomator(uiautomatorText); @@ -169,9 +169,9 @@ public static By custom(final String selector) { * as for OpenCV library. * @return an instance of {@link ByImage} * @see - * The documentation on Image Comparison Features + * The documentation on Image Comparison Features * @see - * The settings available for lookup fine-tuning + * The settings available for lookup fine-tuning * @since Appium 1.8.2 */ public static By image(final String b64Template) { diff --git a/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java b/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java index e4f998b99..b32de52bc 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java +++ b/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java @@ -23,103 +23,103 @@ public enum KeyEventMetaModifier { */ SELECTING(0x800), /** - *

    This mask is used to check whether one of the ALT meta keys is pressed.

    + * This mask is used to check whether one of the ALT meta keys is pressed. * * @see AndroidKey#ALT_LEFT * @see AndroidKey#ALT_RIGHT */ ALT_ON(0x02), /** - *

    This mask is used to check whether the left ALT meta key is pressed.

    + * This mask is used to check whether the left ALT meta key is pressed. * * @see AndroidKey#ALT_LEFT */ ALT_LEFT_ON(0x10), /** - *

    This mask is used to check whether the right the ALT meta key is pressed.

    + * This mask is used to check whether the right the ALT meta key is pressed. * * @see AndroidKey#ALT_RIGHT */ ALT_RIGHT_ON(0x20), /** - *

    This mask is used to check whether one of the SHIFT meta keys is pressed.

    + * This mask is used to check whether one of the SHIFT meta keys is pressed. * * @see AndroidKey#SHIFT_LEFT * @see AndroidKey#SHIFT_RIGHT */ SHIFT_ON(0x1), /** - *

    This mask is used to check whether the left SHIFT meta key is pressed.

    + * This mask is used to check whether the left SHIFT meta key is pressed. * * @see AndroidKey#SHIFT_LEFT */ SHIFT_LEFT_ON(0x40), /** - *

    This mask is used to check whether the right SHIFT meta key is pressed.

    + * This mask is used to check whether the right SHIFT meta key is pressed. * * @see AndroidKey#SHIFT_RIGHT */ SHIFT_RIGHT_ON(0x80), /** - *

    This mask is used to check whether the SYM meta key is pressed.

    + * This mask is used to check whether the SYM meta key is pressed. */ SYM_ON(0x4), /** - *

    This mask is used to check whether the FUNCTION meta key is pressed.

    + * This mask is used to check whether the FUNCTION meta key is pressed. */ FUNCTION_ON(0x8), /** - *

    This mask is used to check whether one of the CTRL meta keys is pressed.

    + * This mask is used to check whether one of the CTRL meta keys is pressed. * * @see AndroidKey#CTRL_LEFT * @see AndroidKey#CTRL_RIGHT */ CTRL_ON(0x1000), /** - *

    This mask is used to check whether the left CTRL meta key is pressed.

    + * This mask is used to check whether the left CTRL meta key is pressed. * * @see AndroidKey#CTRL_LEFT */ CTRL_LEFT_ON(0x2000), /** - *

    This mask is used to check whether the right CTRL meta key is pressed.

    + * This mask is used to check whether the right CTRL meta key is pressed. * * @see AndroidKey#CTRL_RIGHT */ CTRL_RIGHT_ON(0x4000), /** - *

    This mask is used to check whether one of the META meta keys is pressed.

    + * This mask is used to check whether one of the META meta keys is pressed. * * @see AndroidKey#META_LEFT * @see AndroidKey#META_RIGHT */ META_ON(0x10000), /** - *

    This mask is used to check whether the left META meta key is pressed.

    + * This mask is used to check whether the left META meta key is pressed. * * @see AndroidKey#META_LEFT */ META_LEFT_ON(0x20000), /** - *

    This mask is used to check whether the right META meta key is pressed.

    + * This mask is used to check whether the right META meta key is pressed. * * @see AndroidKey#META_RIGHT */ META_RIGHT_ON(0x40000), /** - *

    This mask is used to check whether the CAPS LOCK meta key is on.

    + * This mask is used to check whether the CAPS LOCK meta key is on. * * @see AndroidKey#CAPS_LOCK */ CAPS_LOCK_ON(0x100000), /** - *

    This mask is used to check whether the NUM LOCK meta key is on.

    + * This mask is used to check whether the NUM LOCK meta key is on. * * @see AndroidKey#NUM_LOCK */ NUM_LOCK_ON(0x200000), /** - *

    This mask is used to check whether the SCROLL LOCK meta key is on.

    + * This mask is used to check whether the SCROLL LOCK meta key is on. * * @see AndroidKey#SCROLL_LOCK */ diff --git a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java index 8cbe2cf33..da14a620e 100644 --- a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java +++ b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java @@ -101,7 +101,10 @@ import java.util.Map; /** - * https://github.com/appium/appium-espresso-driver#capabilities + * Provides options specific to the Espresso Driver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class EspressoOptions extends BaseOptions implements // General options: https://github.com/appium/appium-uiautomator2-driver#general diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java index 3c6a7bc51..77115496f 100644 --- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java +++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java @@ -107,7 +107,10 @@ import java.util.Map; /** - * https://github.com/appium/appium-uiautomator2-driver#capabilities + * Provides options specific to the UiAutomator2 Driver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class UiAutomator2Options extends BaseOptions implements // General options: https://github.com/appium/appium-uiautomator2-driver#general diff --git a/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java b/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java index e6366f708..d7e34242e 100644 --- a/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java +++ b/src/main/java/io/appium/java_client/chromium/ChromiumDriver.java @@ -29,10 +29,11 @@ import java.net.URL; /** - *

    ChromiumDriver is an officially supported Appium driver created to automate Mobile browsers + * ChromiumDriver is an officially supported Appium driver created to automate Mobile browsers * and web views based on the Chromium engine. The driver uses W3CWebDriver protocol and is built - * on top of chromium driver server.

    + * on top of chromium driver server. *
    + * *

    Read appium-chromium-driver * for more details on how to configure and use it.

    */ diff --git a/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java b/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java index dfc5d7d02..2f25eeff4 100644 --- a/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java +++ b/src/main/java/io/appium/java_client/chromium/options/ChromiumOptions.java @@ -24,7 +24,7 @@ import java.util.Map; /** - *

    Options class that sets options for Chromium when testing websites.

    + * Options class that sets options for Chromium when testing websites. *
    * @see appium-chromium-driver usage section */ diff --git a/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java b/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java index 6a00c0510..2e5a83430 100644 --- a/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java +++ b/src/main/java/io/appium/java_client/flutter/FlutterDriverOptions.java @@ -13,7 +13,10 @@ import java.util.Map; /** - * https://github.com/AppiumTestDistribution/appium-flutter-integration-driver#capabilities-for-appium-flutter-integration-driver + * Provides options specific to the Appium Flutter Integration Driver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class FlutterDriverOptions extends BaseOptions implements SupportsFlutterSystemPortOption, diff --git a/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java b/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java index 4eb74e82a..1d11378e2 100644 --- a/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java +++ b/src/main/java/io/appium/java_client/flutter/FlutterIntegrationTestDriver.java @@ -7,8 +7,8 @@ * Flutter applications, extending WebDriver and providing additional capabilities for * interacting with Flutter-specific elements and behaviors. * - *

    This interface serves as a common entity for drivers that support Flutter applications - * on different platforms, such as Android and iOS.

    + *

    This interface serves as a common entity for drivers that support Flutter applications + * on different platforms, such as Android and iOS.

    * * @see WebDriver * @see SupportsGestureOnFlutterElements diff --git a/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java b/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java index 084400142..2e1b4f1fd 100644 --- a/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java +++ b/src/main/java/io/appium/java_client/gecko/options/GeckoOptions.java @@ -31,7 +31,10 @@ import java.util.Map; /** - * https://github.com/appium/appium-geckodriver#usage + * Provides options specific to the Geckodriver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class GeckoOptions extends BaseOptions implements SupportsBrowserNameOption, diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index 53465b4dd..081099bc7 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -119,7 +119,10 @@ import java.util.Map; /** - * https://github.com/appium/appium-xcuitest-driver#capabilities + * Provides options specific to the XCUITest Driver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class XCUITestOptions extends BaseOptions implements // General options: https://github.com/appium/appium-xcuitest-driver#general diff --git a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java index 5325ee284..230c04c90 100644 --- a/src/main/java/io/appium/java_client/mac/options/Mac2Options.java +++ b/src/main/java/io/appium/java_client/mac/options/Mac2Options.java @@ -27,7 +27,10 @@ import java.util.Optional; /** - * https://github.com/appium/appium-mac2-driver#capabilities + * Provides options specific to the Appium Mac2 Driver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class Mac2Options extends BaseOptions implements SupportsSystemPortOption, diff --git a/src/main/java/io/appium/java_client/safari/options/SafariOptions.java b/src/main/java/io/appium/java_client/safari/options/SafariOptions.java index fa170587b..9639509a1 100644 --- a/src/main/java/io/appium/java_client/safari/options/SafariOptions.java +++ b/src/main/java/io/appium/java_client/safari/options/SafariOptions.java @@ -31,7 +31,10 @@ import java.util.Map; /** - * https://github.com/appium/appium-safari-driver#usage + * Provides options specific to the Safari Driver. + * + *

    For more details, refer to the + * capabilities documentation

    */ public class SafariOptions extends BaseOptions implements SupportsBrowserNameOption, diff --git a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java index fd4d125b0..257c2807a 100644 --- a/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java +++ b/src/main/java/io/appium/java_client/windows/options/WindowsOptions.java @@ -28,7 +28,7 @@ import java.util.Optional; /** - * https://github.com/appium/appium-windows-driver#usage + * https://github.com/appium/appium-windows-driver#usage. */ public class WindowsOptions extends BaseOptions implements SupportsAppOption, From e98bf2dc46a23f1e0eeb39eafe1e73599d363503 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 2 Jun 2025 21:50:42 +0300 Subject: [PATCH 435/501] fix: Fix Selenium 4.34.0+ compatibility (#2298) --- README.md | 3 ++- .../io/appium/java_client/HasBrowserCheck.java | 6 +++--- .../utils/WebDriverUnpackUtility.java | 11 ++++++----- .../remote/SupportsContextSwitching.java | 3 +-- .../java_client/events/stubs/EmptyWebDriver.java | 16 +--------------- 5 files changed, 13 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index be1f8e546..2f0c390ee 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,8 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ----------------------------------------------------------------------------------------------------|----------------------------- -`9.4.0` | `4.26.0`, `4.27.0`, `4.28.0` +- | `4.34.0` +`9.4.0` | `4.26.0`, `4.27.0`, `4.28.0`, `4.28.1`, `4.29.0`, `4.30.0`, `4.31.0`, `4.32.0`, `4.33.0` `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0`, `4.23.1`, `4.24.0`, `4.25.0`, `4.26.0`, `4.27.0` `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` `9.0.0` | `4.14.1`, `4.15.0`, `4.16.0` (partially [corrupted](https://github.com/SeleniumHQ/selenium/issues/13256)), `4.16.1` diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java index ebce4a3c5..eea25072e 100644 --- a/src/main/java/io/appium/java_client/HasBrowserCheck.java +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -1,7 +1,7 @@ package io.appium.java_client; import io.appium.java_client.internal.CapabilityHelpers; -import org.openqa.selenium.ContextAware; +import io.appium.java_client.remote.SupportsContextSwitching; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType; @@ -29,11 +29,11 @@ default boolean isBrowser() { // ignore } } - if (!(this instanceof ContextAware)) { + if (!(this instanceof SupportsContextSwitching)) { return false; } try { - var context = ((ContextAware) this).getContext(); + var context = ((SupportsContextSwitching) this).getContext(); return context != null && !context.toUpperCase().contains(NATIVE_CONTEXT); } catch (WebDriverException e) { return false; diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 997460be5..8afc2d9cf 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -18,8 +18,8 @@ import io.appium.java_client.HasBrowserCheck; import io.appium.java_client.pagefactory.bys.ContentType; +import io.appium.java_client.remote.SupportsContextSwitching; import org.jspecify.annotations.Nullable; -import org.openqa.selenium.ContextAware; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WrapsDriver; @@ -92,12 +92,13 @@ public static WebDriver unpackWebDriverFromSearchContext(@Nullable SearchContext * {@link WebDriver} or {@link org.openqa.selenium.WebElement} or some other * user's extension/implementation. * Note: if you want to use your own implementation then it should - * implement {@link ContextAware} or {@link WrapsDriver} or {@link HasBrowserCheck} + * implement {@link SupportsContextSwitching} or {@link WrapsDriver} or {@link HasBrowserCheck} * @return current content type. It depends on current context. If current context is * NATIVE_APP it will return {@link ContentType#NATIVE_MOBILE_SPECIFIC}. * {@link ContentType#HTML_OR_DEFAULT} will be returned if the current context is WEB_VIEW. * {@link ContentType#HTML_OR_DEFAULT} also will be returned if the given - * {@link SearchContext} instance doesn't implement {@link ContextAware} and {@link WrapsDriver} + * {@link SearchContext} instance doesn't implement {@link SupportsContextSwitching} and + * {@link WrapsDriver} */ public static ContentType getCurrentContentType(SearchContext context) { var browserCheckHolder = unpackObjectFromSearchContext(context, HasBrowserCheck.class); @@ -105,8 +106,8 @@ public static ContentType getCurrentContentType(SearchContext context) { return NATIVE_MOBILE_SPECIFIC; } - var contextAware = unpackObjectFromSearchContext(context, ContextAware.class); - if (contextAware.map(ContextAware::getContext) + var contextAware = unpackObjectFromSearchContext(context, SupportsContextSwitching.class); + if (contextAware.map(SupportsContextSwitching::getContext) .filter(c -> c.toUpperCase().contains(NATIVE_CONTEXT)).isPresent()) { return NATIVE_MOBILE_SPECIFIC; } diff --git a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java index 7fad6f0e5..c576583dc 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java +++ b/src/main/java/io/appium/java_client/remote/SupportsContextSwitching.java @@ -20,7 +20,6 @@ import io.appium.java_client.MobileCommand; import io.appium.java_client.NoSuchContextException; import org.jspecify.annotations.Nullable; -import org.openqa.selenium.ContextAware; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Response; @@ -32,7 +31,7 @@ import static java.util.Objects.requireNonNull; -public interface SupportsContextSwitching extends WebDriver, ContextAware, ExecutesMethod { +public interface SupportsContextSwitching extends WebDriver, ExecutesMethod { /** * Switches to the given context. * diff --git a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java index c07df5b68..f4d4aab96 100644 --- a/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/stubs/EmptyWebDriver.java @@ -19,7 +19,6 @@ import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.ContextAware; import org.openqa.selenium.Cookie; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.JavascriptExecutor; @@ -39,8 +38,7 @@ import java.util.Map; import java.util.Set; -public class EmptyWebDriver implements WebDriver, ContextAware, - JavascriptExecutor, HasCapabilities, TakesScreenshot { +public class EmptyWebDriver implements WebDriver, JavascriptExecutor, HasCapabilities, TakesScreenshot { public EmptyWebDriver() { } @@ -48,18 +46,6 @@ private static List createStubList() { return List.of(new StubWebElement(), new StubWebElement()); } - public WebDriver context(String name) { - return null; - } - - public Set getContextHandles() { - return null; - } - - public String getContext() { - return ""; - } - public void get(String url) { } From bb0dd5c332774ed201fdd833de7cd069a8127af1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 23:18:17 +0300 Subject: [PATCH 436/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.12.2 to 5.13.0 (#2297) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.12.2 to 5.13.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.12.2...r5.13.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c01d2c328..d364ca4db 100644 --- a/build.gradle +++ b/build.gradle @@ -196,7 +196,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.12.2' + implementation 'org.junit.jupiter:junit-jupiter:5.13.0' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 7f4efc6eabf8deb4da0f3d3d43017076c0fdb7f0 Mon Sep 17 00:00:00 2001 From: VZEROALL Date: Tue, 3 Jun 2025 19:42:09 +0300 Subject: [PATCH 437/501] docs: Fix typo in compatibility matrix (#2299) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f0c390ee..8ded039d1 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ----------------------------------------------------------------------------------------------------|----------------------------- -- | `4.34.0` +`next` | `4.34.0` `9.4.0` | `4.26.0`, `4.27.0`, `4.28.0`, `4.28.1`, `4.29.0`, `4.30.0`, `4.31.0`, `4.32.0`, `4.33.0` `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0`, `4.23.1`, `4.24.0`, `4.25.0`, `4.26.0`, `4.27.0` `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` From 987a05239f3f14e877c2ffda7b9f8fd4f87b5904 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 15:40:20 +0300 Subject: [PATCH 438/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.13.0 to 5.13.1 (#2301) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.13.0 to 5.13.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.13.0...r5.13.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d364ca4db..19622b5ea 100644 --- a/build.gradle +++ b/build.gradle @@ -196,7 +196,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.13.0' + implementation 'org.junit.jupiter:junit-jupiter:5.13.1' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From b4569726fde332b6c67d7a9735256eef27f1e052 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 15:40:37 +0300 Subject: [PATCH 439/501] build(deps): Bump org.owasp.dependencycheck from 12.1.1 to 12.1.2 (#2300) Bumps org.owasp.dependencycheck from 12.1.1 to 12.1.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-version: 12.1.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 19622b5ea..1852342cc 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.1.1' + id 'org.owasp.dependencycheck' version '12.1.2' id 'com.gradleup.shadow' version '8.3.6' } From 5813ac53d8bdccc2dfb453ad2b49b8d09e2aa12d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 15:45:38 +0300 Subject: [PATCH 440/501] build(deps): Bump org.owasp.dependencycheck from 12.1.2 to 12.1.3 (#2302) Bumps org.owasp.dependencycheck from 12.1.2 to 12.1.3. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-version: 12.1.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1852342cc..1c3a87f8e 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.1.2' + id 'org.owasp.dependencycheck' version '12.1.3' id 'com.gradleup.shadow' version '8.3.6' } From 765f943154726ad0a12eee60e420d0ffc82c669e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 29 Jun 2025 22:01:07 +0200 Subject: [PATCH 441/501] feat: Use prebuilt WDA package to speed up the CI pipeline (#2304) --- .github/workflows/{gradle.yml => ci.yml} | 7 ++- .../java_client/android/BaseFlutterTest.java | 23 +++++--- .../io/appium/java_client/ios/AppIOSTest.java | 3 + .../appium/java_client/ios/BaseIOSTest.java | 2 + .../java_client/ios/BaseIOSWebViewTest.java | 3 + .../java_client/ios/BaseSafariTest.java | 3 + .../ios/options/XCUITestOptions.java | 4 ++ .../wda/SupportsPrebuiltWdaPathOption.java | 50 ++++++++++++++++ .../wda/SupportsUsePreinstalledWdaOption.java | 59 +++++++++++++++++++ 9 files changed, 143 insertions(+), 11 deletions(-) rename .github/workflows/{gradle.yml => ci.yml} (94%) create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsPrebuiltWdaPathOption.java create mode 100644 src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePreinstalledWdaOption.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/ci.yml similarity index 94% rename from .github/workflows/gradle.yml rename to .github/workflows/ci.yml index cd70a8203..591678f6d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ env: IOS_PLATFORM_VERSION: "17.5" FLUTTER_ANDROID_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/app-debug.apk" FLUTTER_IOS_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/ios.zip" + PREBUILT_WDA_PATH: ${{ github.workspace }}/wda/WebDriverAgentRunner-Runner.app jobs: build: @@ -135,12 +136,14 @@ jobs: with: model: "${{ env.IOS_DEVICE_NAME }}" os_version: "${{ env.IOS_PLATFORM_VERSION }}" + wait_for_boot: true + shutdown_after_job: false - name: Install XCUITest driver if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' run: appium driver install xcuitest - - name: Prebuild XCUITest driver + - name: Download prebuilt WDA if: matrix.e2e-tests == 'ios' || matrix.e2e-tests == 'flutter-ios' - run: appium driver run xcuitest build-wda --sdk=${{ env.IOS_PLATFORM_VERSION }} --name='${{ env.IOS_DEVICE_NAME }}' + run: appium driver run xcuitest download-wda-sim --platform=ios --outdir=$(dirname "$PREBUILT_WDA_PATH") - name: Run iOS E2E tests if: matrix.e2e-tests == 'ios' run: ./gradlew e2eIosTest -PisCI -Pselenium.version=$latest_snapshot diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java index a0dd5ccaa..1c502c4f4 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java @@ -35,6 +35,7 @@ class BaseFlutterTest { private static AppiumDriverLocalService service; protected static FlutterIntegrationTestDriver driver; protected static final By LOGIN_BUTTON = AppiumBy.flutterText("Login"); + private static String PREBUILT_WDA_PATH = System.getenv("PREBUILT_WDA_PATH"); /** * initialization. @@ -74,15 +75,19 @@ void startSession() throws MalformedURLException { String platformVersion = System.getenv("IOS_PLATFORM_VERSION") != null ? System.getenv("IOS_PLATFORM_VERSION") : "14.5"; - driver = new FlutterIOSDriver(service.getUrl(), flutterOptions - .setXCUITestOptions(new XCUITestOptions() - .setApp(System.getProperty("flutterApp")) - .setDeviceName(deviceName) - .setPlatformVersion(platformVersion) - .setWdaLaunchTimeout(Duration.ofMinutes(4)) - .setSimulatorStartupTimeout(Duration.ofMinutes(5)) - .eventTimings() - ) + XCUITestOptions xcuiTestOptions = new XCUITestOptions() + .setApp(System.getProperty("flutterApp")) + .setDeviceName(deviceName) + .setPlatformVersion(platformVersion) + .setWdaLaunchTimeout(Duration.ofMinutes(4)) + .setSimulatorStartupTimeout(Duration.ofMinutes(5)) + .eventTimings(); + if (PREBUILT_WDA_PATH != null) { + xcuiTestOptions.usePreinstalledWda().setPrebuiltWdaPath(PREBUILT_WDA_PATH); + } + driver = new FlutterIOSDriver( + service.getUrl(), + flutterOptions.setXCUITestOptions(xcuiTestOptions) ); } } diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java index 595114978..8de7d60e7 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java @@ -23,6 +23,9 @@ public static void beforeClass() { .setApp(TEST_APP_ZIP) .enableBiDi() .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); + if (PREBUILT_WDA_PATH != null) { + options.usePreinstalledWda().setPrebuiltWdaPath(PREBUILT_WDA_PATH); + } try { driver = new IOSDriver(service.getUrl(), options); } catch (SessionNotCreatedException e) { diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java index cc571b6fa..73772390f 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java @@ -36,6 +36,8 @@ public class BaseIOSTest { : "14.5"; public static final Duration WDA_LAUNCH_TIMEOUT = Duration.ofMinutes(4); public static final Duration SERVER_START_TIMEOUT = Duration.ofMinutes(3); + protected static String PREBUILT_WDA_PATH = System.getenv("PREBUILT_WDA_PATH"); + /** * Starts a local server. diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 2ffe6c79c..2371a7b72 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -40,6 +40,9 @@ public static void beforeClass() { .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) .setCommandTimeouts(Duration.ofSeconds(240)) .setApp(VODQA_ZIP); + if (PREBUILT_WDA_PATH != null) { + options.usePreinstalledWda().setPrebuiltWdaPath(PREBUILT_WDA_PATH); + } Supplier createDriver = () -> new IOSDriver(service.getUrl(), options); try { driver = createDriver.get(); diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java index 710f5dbf1..7468e89e9 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseSafariTest.java @@ -34,6 +34,9 @@ public class BaseSafariTest extends BaseIOSTest { .setPlatformVersion(PLATFORM_VERSION) .setWebviewConnectTimeout(WEBVIEW_CONNECT_TIMEOUT) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT); + if (PREBUILT_WDA_PATH != null) { + options.usePreinstalledWda().setPrebuiltWdaPath(PREBUILT_WDA_PATH); + } driver = new IOSDriver(service.getUrl(), options); } } diff --git a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java index 081099bc7..41d5047a2 100644 --- a/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java +++ b/src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java @@ -55,6 +55,7 @@ import io.appium.java_client.ios.options.wda.SupportsKeychainOptions; import io.appium.java_client.ios.options.wda.SupportsMaxTypingFrequencyOption; import io.appium.java_client.ios.options.wda.SupportsMjpegServerPortOption; +import io.appium.java_client.ios.options.wda.SupportsPrebuiltWdaPathOption; import io.appium.java_client.ios.options.wda.SupportsProcessArgumentsOption; import io.appium.java_client.ios.options.wda.SupportsResultBundlePathOption; import io.appium.java_client.ios.options.wda.SupportsScreenshotQualityOption; @@ -66,6 +67,7 @@ import io.appium.java_client.ios.options.wda.SupportsUseNativeCachingStrategyOption; import io.appium.java_client.ios.options.wda.SupportsUseNewWdaOption; import io.appium.java_client.ios.options.wda.SupportsUsePrebuiltWdaOption; +import io.appium.java_client.ios.options.wda.SupportsUsePreinstalledWdaOption; import io.appium.java_client.ios.options.wda.SupportsUseSimpleBuildTestOption; import io.appium.java_client.ios.options.wda.SupportsUseXctestrunFileOption; import io.appium.java_client.ios.options.wda.SupportsWaitForIdleTimeoutOption; @@ -156,6 +158,8 @@ public class XCUITestOptions extends BaseOptions implements SupportsWdaBaseUrlOption, SupportsShowXcodeLogOption, SupportsUsePrebuiltWdaOption, + SupportsUsePreinstalledWdaOption, + SupportsPrebuiltWdaPathOption, SupportsShouldUseSingletonTestManagerOption, SupportsWaitForIdleTimeoutOption, SupportsUseXctestrunFileOption, diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsPrebuiltWdaPathOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsPrebuiltWdaPathOption.java new file mode 100644 index 000000000..7754f232c --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsPrebuiltWdaPathOption.java @@ -0,0 +1,50 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +public interface SupportsPrebuiltWdaPathOption> extends + Capabilities, CanSetCapability { + String PREBUILT_WDA_PATH_OPTION = "prebuiltWDAPath"; + + /** + * The full path to the prebuilt WebDriverAgent-Runner application + * package to be installed if appium:usePreinstalledWDA capability + * is enabled. The package's bundle identifier could be customized via + * appium:updatedWDABundleId capability. + * + * @param path The full path to the bundle .app file on the server file system. + * @return self instance for chaining. + */ + default T setPrebuiltWdaPath(String path) { + return amend(PREBUILT_WDA_PATH_OPTION, path); + } + + /** + * Get prebuilt WebDriverAgent path. + * + * @return The full path to the bundle .app file on the server file system. + */ + default Optional getPrebuiltWdaPath() { + return Optional.ofNullable((String) getCapability(PREBUILT_WDA_PATH_OPTION)); + } +} diff --git a/src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePreinstalledWdaOption.java b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePreinstalledWdaOption.java new file mode 100644 index 000000000..0ae2dbcfd --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/options/wda/SupportsUsePreinstalledWdaOption.java @@ -0,0 +1,59 @@ +/* + * 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.options.wda; + +import io.appium.java_client.remote.options.BaseOptions; +import io.appium.java_client.remote.options.CanSetCapability; +import org.openqa.selenium.Capabilities; + +import java.util.Optional; + +import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean; + +public interface SupportsUsePreinstalledWdaOption> extends + Capabilities, CanSetCapability { + String USE_PREINSTALLED_WDA_OPTION = "usePreinstalledWDA"; + + /** + * Whether to launch a preinstalled WebDriverAgentRunner application using a custom XCTest API client. + * + * @return self instance for chaining. + */ + default T usePreinstalledWda() { + return amend(USE_PREINSTALLED_WDA_OPTION, true); + } + + /** + * Whether to launch a preinstalled WebDriverAgentRunner application using a custom XCTest API client. + * Defaults to false. + * + * @param value Either true or false. + * @return self instance for chaining. + */ + default T setUsePreinstalledWda(boolean value) { + return amend(USE_PREINSTALLED_WDA_OPTION, value); + } + + /** + * Get whether to launch a preinstalled WebDriverAgentRunner application using a custom XCTest API client. + * + * @return True or false. + */ + default Optional doesUsePreinstalledWda() { + return Optional.ofNullable(toSafeBoolean(getCapability(USE_PREINSTALLED_WDA_OPTION))); + } +} From 209aaf472e9b21c3c399571b35716cd9f93d1d37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 17:31:54 +0300 Subject: [PATCH 442/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.13.1 to 5.13.2 (#2307) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1c3a87f8e..77fa118de 100644 --- a/build.gradle +++ b/build.gradle @@ -196,7 +196,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.13.1' + implementation 'org.junit.jupiter:junit-jupiter:5.13.2' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From a939776381539840f720d5c3a8ec297d2d40be3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 18:53:55 +0300 Subject: [PATCH 443/501] build(deps): Bump com.gradleup.shadow from 8.3.6 to 8.3.7 (#2306) --- updated-dependencies: - dependency-name: com.gradleup.shadow dependency-version: 8.3.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 77fa118de..0686b5c72 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '12.1.3' - id 'com.gradleup.shadow' version '8.3.6' + id 'com.gradleup.shadow' version '8.3.7' } repositories { From 9d2b859058073c6a762fc824c7f14967badc4502 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Mon, 30 Jun 2025 21:55:42 +0300 Subject: [PATCH 444/501] chore: Bump minimum Selenium version to `4.34.0` (#2305) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4f5bf63fa..a59f910bb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.26.0 +selenium.version=4.34.0 # Please increment the value in a release appiumClient.version=9.4.0 From 6b19c316979d37716a7c569c04f09d06e23ec24c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 30 Jun 2025 22:31:28 +0200 Subject: [PATCH 445/501] ci: Temporarily use latest released selenium version to run tests (#2310) --- .github/workflows/ci.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 591678f6d..33ac2e644 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,10 +78,30 @@ jobs: uses: gradle/actions/setup-gradle@v4 - name: Build with Gradle + # FIXME: Sonatype returns 401 for the snapshots repository + # latest_snapshot=$(curl -sf https://oss.sonatype.org/content/repositories/snapshots/org/seleniumhq/selenium/selenium-api/ | \ + # python -c "import sys,re; print(re.findall(r'\d+\.\d+\.\d+-SNAPSHOT', sys.stdin.read())[-1])") + # echo ">>> $latest_snapshot" + # echo "latest_snapshot=$latest_snapshot" >> "$GITHUB_ENV" + # ./gradlew clean build -PisCI -Pselenium.version=$latest_snapshot run: | - latest_snapshot=$(curl -sf https://oss.sonatype.org/content/repositories/snapshots/org/seleniumhq/selenium/selenium-api/ | \ - python -c "import sys,re; print(re.findall(r'\d+\.\d+\.\d+-SNAPSHOT', sys.stdin.read())[-1])") - echo ">>> $latest_snapshot" + GROUP_ID="org.seleniumhq.selenium" + ARTIFACT_ID="selenium-api" + REPO_URL="https://repo1.maven.org/maven2" + GROUP_PATH="${GROUP_ID//.//}" + METADATA_URL="${REPO_URL}/${GROUP_PATH}/${ARTIFACT_ID}/maven-metadata.xml" + + metadata=$(curl -s "$METADATA_URL") + latest_snapshot=$(python3 -c " + import sys, xml.etree.ElementTree as ET + root = ET.fromstring(sys.stdin.read()) + print(root.findtext('./versioning/latest')) + " <<< "$metadata") + if [ -z "$latest_snapshot" ]; then + echo "❌ Failed to extract latest released version of ${ARTIFACT_ID} from $metadata" + exit 1 + fi + echo "✅ Latest released version of ${ARTIFACT_ID} is: $latest_snapshot" echo "latest_snapshot=$latest_snapshot" >> "$GITHUB_ENV" ./gradlew clean build -PisCI -Pselenium.version=$latest_snapshot From 6cfef355cfee57cf44b2e17c544bbdacff7eef16 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Tue, 1 Jul 2025 08:42:38 +0300 Subject: [PATCH 446/501] release: v9.5.0 (#2308) --- CHANGELOG.md | 14 ++++++++++++++ README.md | 2 +- gradle.properties | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afce5b183..1e20c7874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_9.5.0_ +- **[ENHANCEMENTS]** + - Allow extension capability keys to contain dot characters [#2271](https://github.com/appium/java-client/pull/2271) + - Add a client for Appium server storage plugin [#2275](https://github.com/appium/java-client/pull/2275) + - Swap check for `Widget` and `WebElement` [#2277](https://github.com/appium/java-client/pull/2277) + - Add compatibility with Selenium `4.34.0` [#2298](https://github.com/appium/java-client/pull/2298) + - Add new option classes for `prebuiltWDAPath` and `usePreinstalledWDA` XCUITest capabilities [#2304](https://github.com/appium/java-client/pull/2304) +- **[REFACTOR]** + - Migrate from JSR 305 to [JSpecify](https://jspecify.dev/)'s nullability annotations [#2281](https://github.com/appium/java-client/pull/2281) +- **[DEPENDENCY UPDATES]** + - Bump minimum supported Selenium version from `4.26.0` to `4.34.0` [#2305](https://github.com/appium/java-client/pull/2305) + - Bump Gson from `2.11.0` to `2.13.1` [#2267](https://github.com/appium/java-client/pull/2267), [#2286](https://github.com/appium/java-client/pull/2286), [#2290](https://github.com/appium/java-client/pull/2290) + - Bump SLF4J from `2.0.16` to `2.0.17` [#2274](https://github.com/appium/java-client/pull/2274) + _9.4.0_ - **[ENHANCEMENTS]** - Implement `HasBiDi` interface support in `AppiumDriver` [#2250](https://github.com/appium/java-client/pull/2250), [#2254](https://github.com/appium/java-client/pull/2254), [#2256](https://github.com/appium/java-client/pull/2256) diff --git a/README.md b/README.md index 8ded039d1..ed0b8a888 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ----------------------------------------------------------------------------------------------------|----------------------------- -`next` | `4.34.0` +`9.5.0` | `4.34.0` `9.4.0` | `4.26.0`, `4.27.0`, `4.28.0`, `4.28.1`, `4.29.0`, `4.30.0`, `4.31.0`, `4.32.0`, `4.33.0` `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0`, `4.23.1`, `4.24.0`, `4.25.0`, `4.26.0`, `4.27.0` `9.1.0`, `9.2.0` | `4.17.0`, `4.18.0`, `4.18.1` diff --git a/gradle.properties b/gradle.properties index a59f910bb..f53e0d155 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.34.0 # Please increment the value in a release -appiumClient.version=9.4.0 +appiumClient.version=9.5.0 From 09b7ac266ced3f54518ab16f088d42bdc11d58a3 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Thu, 3 Jul 2025 13:47:30 +0530 Subject: [PATCH 447/501] feat: Proxy commands issues via RemoteWebElement (#2311) --- docs/The-event_firing.md | 57 ++++++++++ .../proxy/ElementAwareWebDriverListener.java | 107 ++++++++++++++++++ .../io/appium/java_client/proxy/Helpers.java | 6 + .../java_client/proxy/ProxyAwareListener.java | 41 +++++++ .../java_client/proxy/ProxyHelpersTest.java | 80 +++++++++++++ 5 files changed, 291 insertions(+) create mode 100644 src/main/java/io/appium/java_client/proxy/ElementAwareWebDriverListener.java create mode 100644 src/main/java/io/appium/java_client/proxy/ProxyAwareListener.java diff --git a/docs/The-event_firing.md b/docs/The-event_firing.md index 527fddeb8..ff77c1247 100644 --- a/docs/The-event_firing.md +++ b/docs/The-event_firing.md @@ -154,3 +154,60 @@ This proxy is not tied to WebDriver descendants and could be used to any classes change/replace the original methods behavior. It is important to know that callbacks are **not** invoked for methods derived from the standard `Object` class, like `toString` or `equals`. Check [unit tests](../src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java) for more examples. + +#### ElementAwareWebDriverListener + +A specialized MethodCallListener that listens to all method calls on a WebDriver instance and automatically wraps any returned RemoteWebElement (or list of elements) with a proxy. This enables your listener to intercept and react to method calls on both: + +- The driver itself (e.g., findElement, getTitle) + +- Any elements returned by the driver (e.g., click, isSelected on a WebElement) + +```java +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; +import io.appium.java_client.proxy.ElementAwareWebDriverListener; +import io.appium.java_client.proxy.Helpers; +import io.appium.java_client.proxy.MethodCallListener; + + +// ... + +final StringBuilder acc = new StringBuilder(); + +var listener = new ElementAwareWebDriverListener() { + @Override + public void beforeCall(Object target, Method method, Object[] args) { + acc.append("beforeCall ").append(method.getName()).append("\n"); + } +}; + +IOSDriver decoratedDriver = createProxy( + IOSDriver.class, + new Object[]{new URL("http://localhost:4723/"), new XCUITestOptions()}, + new Class[]{URL.class, Capabilities.class}, + listener +); + +WebElement element = decoratedDriver.findElement(By.id("button")); +element::click; + +List elements = decoratedDriver.findElements(By.id("button")); +elements.get(1).isSelected(); + +assertThat(acc.toString().trim()).isEqualTo( + String.join("\n", + "beforeCall findElement", + "beforeCall click", + "beforeCall getSessionId", + "beforeCall getCapabilities", + "beforeCall getCapabilities", + "beforeCall findElements", + "beforeCall isSelected", + "beforeCall getSessionId", + "beforeCall getCapabilities", + "beforeCall getCapabilities" + ) +); + +``` diff --git a/src/main/java/io/appium/java_client/proxy/ElementAwareWebDriverListener.java b/src/main/java/io/appium/java_client/proxy/ElementAwareWebDriverListener.java new file mode 100644 index 000000000..3540b5e7d --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/ElementAwareWebDriverListener.java @@ -0,0 +1,107 @@ +/* + * 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.proxy; + +import net.bytebuddy.matcher.ElementMatchers; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.RemoteWebElement; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; + +import static io.appium.java_client.proxy.Helpers.OBJECT_METHOD_NAMES; +import static io.appium.java_client.proxy.Helpers.createProxy; +import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; + +public class ElementAwareWebDriverListener implements MethodCallListener, ProxyAwareListener { + private WebDriver parent; + + /** + * Attaches the WebDriver proxy instance to this listener. + *

    + * The listener stores the WebDriver instance to associate it as parent to RemoteWebElement proxies. + * + * @param proxy A proxy instance of {@link WebDriver}. + */ + @Override + public void attachProxyInstance(Object proxy) { + if (proxy instanceof WebDriver) { + this.parent = (WebDriver) proxy; + } + } + + /** + * Intercepts method calls on a proxied WebDriver. + *

    + * If the result of the method call is a {@link RemoteWebElement}, + * it is wrapped with a proxy to allow further interception of RemoteWebElement method calls. + * If the result is a list, each item is checked, and all RemoteWebElements are + * individually proxied. All other return types are passed through unmodified. + * Avoid overriding this method, it will alter the behaviour of the listener. + * + * @param obj The object on which the method was invoked. + * @param method The method being invoked. + * @param args The arguments passed to the method. + * @param original A {@link Callable} that represents the original method execution. + * @return The (possibly wrapped) result of the method call. + * @throws Throwable if the original method or any wrapping logic throws an exception. + */ + @Override + public Object call(Object obj, Method method, Object[] args, Callable original) throws Throwable { + Object result = original.call(); + + if (result instanceof RemoteWebElement) { + return wrapElement((RemoteWebElement) result); + } + + if (result instanceof List) { + return ((List) result).stream() + .map(item -> item instanceof RemoteWebElement ? wrapElement( + (RemoteWebElement) item) : item) + .collect(Collectors.toList()); + } + + return result; + } + + private RemoteWebElement wrapElement( + RemoteWebElement original + ) { + RemoteWebElement proxy = createProxy( + RemoteWebElement.class, + new Object[]{}, + new Class[]{}, + Collections.singletonList(this), + ElementMatchers.not( + namedOneOf( + OBJECT_METHOD_NAMES.toArray(new String[0])) + .or(ElementMatchers.named("setId").or(ElementMatchers.named("setParent"))) + ) + ); + + proxy.setId(original.getId()); + + proxy.setParent((RemoteWebDriver) parent); + + return proxy; + } + +} diff --git a/src/main/java/io/appium/java_client/proxy/Helpers.java b/src/main/java/io/appium/java_client/proxy/Helpers.java index f9fae7768..e420d494e 100644 --- a/src/main/java/io/appium/java_client/proxy/Helpers.java +++ b/src/main/java/io/appium/java_client/proxy/Helpers.java @@ -145,6 +145,12 @@ public static T createProxy( try { T result = cls.cast(proxyClass.getConstructor(constructorArgTypes).newInstance(constructorArgs)); ((HasMethodCallListeners) result).setMethodCallListeners(listeners.toArray(MethodCallListener[]::new)); + + listeners.stream() + .filter(ProxyAwareListener.class::isInstance) + .map(ProxyAwareListener.class::cast) + .forEach(listener -> listener.attachProxyInstance(result)); + return result; } catch (SecurityException | ReflectiveOperationException e) { throw new IllegalStateException(String.format("Unable to create a proxy of %s", cls.getName()), e); diff --git a/src/main/java/io/appium/java_client/proxy/ProxyAwareListener.java b/src/main/java/io/appium/java_client/proxy/ProxyAwareListener.java new file mode 100644 index 000000000..f25c48a79 --- /dev/null +++ b/src/main/java/io/appium/java_client/proxy/ProxyAwareListener.java @@ -0,0 +1,41 @@ +/* + * 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.proxy; + +/** + * Extension of {@link MethodCallListener} that allows access to the proxy instance it depends on. + *

    + * This interface is intended for listeners that need a reference to the proxy object. + *

    + * The {@link #attachProxyInstance(Object)} method will be invoked immediately after the proxy is created, + * allowing the listener to bind to it before any method interception begins. + *

    + * Example usage: Working with elements such as + * {@code RemoteWebElement} that require runtime mutation (e.g. setting parent driver or element ID). + */ +public interface ProxyAwareListener extends MethodCallListener { + + /** + * Binds the listener to the proxy instance passed. + *

    + * This is called once, immediately after proxy creation and before the proxy is returned to the caller. + * + * @param proxy the proxy instance created via {@code createProxy} that this listener is attached to. + */ + void attachProxyInstance(Object proxy); +} + diff --git a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java index a8767629d..af0ca78d9 100644 --- a/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java +++ b/src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java @@ -19,14 +19,20 @@ import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.options.XCUITestOptions; import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.NoSuchSessionException; +import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.RemoteWebElement; import org.openqa.selenium.remote.UnreachableBrowserException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.concurrent.Callable; import static io.appium.java_client.proxy.Helpers.createProxy; @@ -45,6 +51,31 @@ public FakeIOSDriver(URL url, Capabilities caps) { @Override protected void startSession(Capabilities capabilities) { } + + @Override + public WebElement findElement(By locator) { + RemoteWebElement webElement = new RemoteWebElement(); + webElement.setId(locator.toString()); + webElement.setParent(this); + return webElement; + } + + @Override + public List findElements(By locator) { + List webElements = new ArrayList<>(); + + RemoteWebElement webElement1 = new RemoteWebElement(); + webElement1.setId("1234"); + webElement1.setParent(this); + webElements.add(webElement1); + + RemoteWebElement webElement2 = new RemoteWebElement(); + webElement2.setId("5678"); + webElement2.setParent(this); + webElements.add(webElement2); + + return webElements; + } } @Test @@ -133,4 +164,53 @@ public Object onError(Object obj, Method method, Object[] args, Throwable e) thr "onError get") ))); } + + + @Test + void shouldFireEventsForAllWebDriverCommands() throws MalformedURLException { + final StringBuilder acc = new StringBuilder(); + + var remoteWebElementListener = new ElementAwareWebDriverListener() { + @Override + public void beforeCall(Object target, Method method, Object[] args) { + acc.append("beforeCall ").append(method.getName()).append("\n"); + } + }; + + FakeIOSDriver driver = createProxy( + FakeIOSDriver.class, + new Object[] {new URL("http://localhost:4723/"), new XCUITestOptions()}, + new Class[] {URL.class, Capabilities.class}, + remoteWebElementListener + ); + + WebElement element = driver.findElement(By.id("button")); + + assertThrows( + NoSuchSessionException.class, + element::click + ); + + List elements = driver.findElements(By.id("button")); + + assertThrows( + NoSuchSessionException.class, + () -> elements.get(1).isSelected() + ); + + assertThat(acc.toString().trim(), is(equalTo( + String.join("\n", + "beforeCall findElement", + "beforeCall click", + "beforeCall getSessionId", + "beforeCall getCapabilities", + "beforeCall getCapabilities", + "beforeCall findElements", + "beforeCall isSelected", + "beforeCall getSessionId", + "beforeCall getCapabilities", + "beforeCall getCapabilities" + ) + ))); + } } From b946db4f6b062ea8e27bae127c46f1ef034d4077 Mon Sep 17 00:00:00 2001 From: Srinivasan Sekar Date: Mon, 7 Jul 2025 13:13:44 +0530 Subject: [PATCH 448/501] ci: Automated Release to Maven Central Repository using JReleaser (#2313) --- .github/workflows/publish.yml | 13 ++++++---- .gitignore | 1 + build.gradle | 48 ++++++++++++++++++++--------------- docs/release.md | 32 ++++++++++------------- 4 files changed, 51 insertions(+), 43 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6b2a253c2..6392f5692 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,8 +18,11 @@ jobs: - name: Publish package env: - MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} - PGP_SECRET: ${{ secrets.SIGNING_KEY }} - PGP_PASSPHRASE: ${{ secrets.SIGNING_PASSWORD }} - run: ./gradlew publish + JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.SIGNING_PUBLIC_KEY }} + JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_SIGNING_KEY }} + JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_SIGNING_PASSWORD }} + JRELEASER_MAVENCENTRAL_SONATYPE_USERNAME: ${{ secrets.OSSRH_USERNAME }} + JRELEASER_MAVENCENTRAL_SONATYPE_PASSWORD: ${{ secrets.OSSRH_TOKEN }} + run: | + ./gradlew publish + ./gradlew jreleaserDeploy diff --git a/.gitignore b/.gitignore index dea3a9d88..da44d7acb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ classes/ /.settings .classpath .project +.vscode diff --git a/build.gradle b/build.gradle index 0686b5c72..48cd82353 100644 --- a/build.gradle +++ b/build.gradle @@ -9,14 +9,24 @@ plugins { id 'signing' id 'org.owasp.dependencycheck' version '12.1.3' id 'com.gradleup.shadow' version '8.3.7' + id 'org.jreleaser' version '1.19.0' } +ext { + seleniumVersion = project.property('selenium.version') + appiumClientVersion = project.property('appiumClient.version') + slf4jVersion = '2.0.17' +} + +group = 'io.appium' +version = appiumClientVersion + repositories { mavenCentral() if (project.hasProperty("isCI")) { maven { - url uri('https://oss.sonatype.org/content/repositories/snapshots/') + url uri('https://central.sonatype.com/api/v1/publisher') mavenContent { snapshotsOnly() } @@ -31,12 +41,6 @@ java { withSourcesJar() } -ext { - seleniumVersion = project.property('selenium.version') - appiumClientVersion = project.property('appiumClient.version') - slf4jVersion = '2.0.17' -} - dependencies { compileOnly 'org.projectlombok:lombok:1.18.38' annotationProcessor 'org.projectlombok:lombok:1.18.38' @@ -160,23 +164,27 @@ publishing { } repositories { maven { - credentials { - username = System.getenv("MAVEN_USERNAME") - password = System.getenv("MAVEN_PASSWORD") - } - def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/'" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + url = layout.buildDirectory.dir('staging-deploy') } } } -signing { - required { !'true'.equalsIgnoreCase(project.findProperty('signingDisabled')) } - def signingKey = System.getenv("PGP_SECRET") - def signingPassword = System.getenv("PGP_PASSPHRASE") - useInMemoryPgpKeys(signingKey, signingPassword) - sign publishing.publications.mavenJava +jreleaser { + signing { + active = 'ALWAYS' + armored = true + } + deploy { + maven { + mavenCentral { + sonatype { + active = 'ALWAYS' + url = 'https://central.sonatype.com/api/v1/publisher' + stagingRepository('build/staging-deploy') + } + } + } + } } wrapper { diff --git a/docs/release.md b/docs/release.md index f2a6c1ae6..9a84ee016 100644 --- a/docs/release.md +++ b/docs/release.md @@ -9,21 +9,17 @@ Its target auditory is project maintainers. 1. Bump the `appiumClient.version` number in [gradle.properties](../gradle.properties). 1. Create a pull request to approve the changelog and version bump. 1. Merge the pull request after it is approved. -1. Create and push a new repository tag. The tag name should look like - `v..`. -1. Create a new [Release](https://github.com/appium/java-client/releases/new) in GitHub. - Paste the above changelist into the release notes. Make sure the name of the new release - matches to the name of the above tag. -1. Open [Sonatype](https://oss.sonatype.org/#welcome) in your browser. -1. Login to Nexus using 1Password credentials. Ask Appium maintainers - if you need access to the team's 1Password vault. -1. Navigate to `Staging Repositories`. -1. Select the corresponding release and click `Close`. Note that it may take - some minutes until Sonatype picks up the GitHub release. -1. Wait until checks are completed. -1. Click `Release`. -1. After the new release is published, it becomes available in - [Maven Central](https://repo1.maven.org/maven2/io/appium/java-client/) - within 30 minutes. Once artifacts are in Maven Central, it normally - takes 1-2 hours before they appear in - [search results](https://central.sonatype.com/artifact/io.appium/java-client). +1. Create and push a new repository tag. The tag name should look like + `v..`. +1. Create a new [Release](https://github.com/appium/java-client/releases/new) in GitHub. + Paste the above changelist into the release notes. Make sure the name of the new release + matches to the name of the above tag. +1. Open [Maven Central Repository](https://central.sonatype.com/) in your browser. +1. Log in to the `Maven Central Repository` using the credentials stored in 1Password. If you need access to the team's 1Password vault, contact the Appium maintainers. +1. Navigate to the `Publish` section. +1. Under `Deployments`, you will see the latest deployment being published. Note: Sometimes the status may remain in the `publishing` state for an extended period, but it will eventually complete. +1. After the new release is published, it becomes available in + [Maven Central](https://repo1.maven.org/maven2/io/appium/java-client/) + within 30 minutes. Once artifacts are in Maven Central, it normally + takes 1-2 hours before they appear in + [search results](https://central.sonatype.com/artifact/io.appium/java-client). From d610428d23fd47fbca44188eba0a863ee5473682 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:59:31 +0300 Subject: [PATCH 449/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.13.2 to 5.13.3 (#2314) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.13.2 to 5.13.3. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.2...r5.13.3) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 48cd82353..0fb6cdbb2 100644 --- a/build.gradle +++ b/build.gradle @@ -204,7 +204,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.13.2' + implementation 'org.junit.jupiter:junit-jupiter:5.13.3' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 10097a584e1e7267fe680a9314a890a1418625b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 18:37:19 +0300 Subject: [PATCH 450/501] build(deps): Bump com.gradleup.shadow from 8.3.7 to 8.3.8 (#2315) Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 8.3.7 to 8.3.8. - [Release notes](https://github.com/GradleUp/shadow/releases) - [Commits](https://github.com/GradleUp/shadow/compare/8.3.7...8.3.8) --- updated-dependencies: - dependency-name: com.gradleup.shadow dependency-version: 8.3.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0fb6cdbb2..24e7aadaf 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '12.1.3' - id 'com.gradleup.shadow' version '8.3.7' + id 'com.gradleup.shadow' version '8.3.8' id 'org.jreleaser' version '1.19.0' } From 4567ecaca0f3b7438cad2868b00d4bcb21893a3e Mon Sep 17 00:00:00 2001 From: itkhanz <62521743+itkhanz@users.noreply.github.com> Date: Thu, 10 Jul 2025 07:56:16 +0200 Subject: [PATCH 451/501] docs: updated CI badge to use ci.yml workflow (#2317) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed0b8a888..5c233031d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client) [![Javadocs](https://www.javadoc.io/badge/io.appium/java-client.svg)](https://www.javadoc.io/doc/io.appium/java-client) -[![Appium Java Client CI](https://github.com/appium/java-client/actions/workflows/gradle.yml/badge.svg)](https://github.com/appium/java-client/actions/workflows/gradle.yml) +[![Appium Java Client CI](https://github.com/appium/java-client/actions/workflows/ci.yml/badge.svg)](https://github.com/appium/java-client/actions/workflows/ci.yml) This is the Java language bindings for writing Appium Tests that conform to [WebDriver Protocol](https://w3c.github.io/webdriver/) From 8be9a0972fc9b204456ab8a3ba3d91a186dd6b56 Mon Sep 17 00:00:00 2001 From: itkhanz <62521743+itkhanz@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:40:42 +0200 Subject: [PATCH 452/501] docs: updated maven central release badge (#2316) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c233031d..0d78b2bae 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # java-client -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.appium/java-client) +[![Maven Central Version](https://img.shields.io/maven-central/v/io.appium/java-client)](https://central.sonatype.com/artifact/io.appium/java-client) [![Javadocs](https://www.javadoc.io/badge/io.appium/java-client.svg)](https://www.javadoc.io/doc/io.appium/java-client) [![Appium Java Client CI](https://github.com/appium/java-client/actions/workflows/ci.yml/badge.svg)](https://github.com/appium/java-client/actions/workflows/ci.yml) From f4ea7234fa32627a6a41f10a5f54ac936836f82e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jul 2025 18:18:01 +0300 Subject: [PATCH 453/501] build(deps): Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 (#2320) Bumps org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 24e7aadaf..d8d775e8e 100644 --- a/build.gradle +++ b/build.gradle @@ -242,7 +242,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('org.apache.commons:commons-lang3:3.17.0') + implementation('org.apache.commons:commons-lang3:3.18.0') } targets.configureEach { From 9d3b569937caa2ecf829300ac852defaa8cae429 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:04:27 +0300 Subject: [PATCH 454/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2319) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 6.1.0 to 6.1.1. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-6.1.0...webdrivermanager-6.1.1) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-version: 6.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d8d775e8e..326f3996f 100644 --- a/build.gradle +++ b/build.gradle @@ -222,7 +222,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:6.1.0') { + implementation('io.github.bonigarcia:webdrivermanager:6.1.1') { exclude group: 'org.seleniumhq.selenium' } } @@ -266,7 +266,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:6.1.0') { + implementation('io.github.bonigarcia:webdrivermanager:6.1.1') { exclude group: 'org.seleniumhq.selenium' } } From 8f5f886907d9049485dab2f021df61c3158dc033 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 18:56:21 +0300 Subject: [PATCH 455/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2322) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 6.1.1 to 6.2.0. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-6.1.1...webdrivermanager-6.2.0) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-version: 6.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 326f3996f..3c3c380b8 100644 --- a/build.gradle +++ b/build.gradle @@ -222,7 +222,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:6.1.1') { + implementation('io.github.bonigarcia:webdrivermanager:6.2.0') { exclude group: 'org.seleniumhq.selenium' } } @@ -266,7 +266,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:6.1.1') { + implementation('io.github.bonigarcia:webdrivermanager:6.2.0') { exclude group: 'org.seleniumhq.selenium' } } From db431d80a0d50aac357a9ff70a735331fad8dd4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 22:58:14 +0300 Subject: [PATCH 456/501] build(deps): Bump org.junit.jupiter:junit-jupiter from 5.13.3 to 5.13.4 (#2321) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.13.3 to 5.13.4. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.3...r5.13.4) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3c3c380b8..be70778ff 100644 --- a/build.gradle +++ b/build.gradle @@ -204,7 +204,7 @@ testing { configureEach { useJUnitJupiter() dependencies { - implementation 'org.junit.jupiter:junit-jupiter:5.13.3' + implementation 'org.junit.jupiter:junit-jupiter:5.13.4' runtimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.hamcrest:hamcrest:3.0' runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}" From 75ee0941ae32c1976b2196b929f7a709881b2826 Mon Sep 17 00:00:00 2001 From: Alex Panchenko <440271+panchenko@users.noreply.github.com> Date: Tue, 12 Aug 2025 08:02:41 +0200 Subject: [PATCH 457/501] fix: Possible NPE in initBiDi() (#2325) --- .../remote/AppiumCommandExecutor.java | 33 ++++++++------- .../remote/AppiumCommandExecutorTest.java | 41 +++++++++++++++++++ 2 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 src/test/java/io/appium/java_client/remote/AppiumCommandExecutorTest.java diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index bf02271d3..fbbd10445 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -20,7 +20,7 @@ import io.appium.java_client.AppiumClientConfig; import io.appium.java_client.internal.ReflectionHelpers; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.WebDriverException; @@ -53,12 +53,11 @@ import static java.util.Optional.ofNullable; import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; +@NullMarked public class AppiumCommandExecutor extends HttpCommandExecutor { private final Optional serviceOptional; @Getter - private final HttpClient.Factory httpClientFactory; - @Getter private final AppiumClientConfig appiumClientConfig; /** @@ -66,32 +65,31 @@ public class AppiumCommandExecutor extends HttpCommandExecutor { * * @param additionalCommands is the map of Appium commands * @param service take a look at {@link DriverService} - * @param httpClientFactory take a look at {@link HttpClient.Factory} + * @param httpClientFactory take a look at {@link Factory} * @param appiumClientConfig take a look at {@link AppiumClientConfig} */ public AppiumCommandExecutor( - @NonNull Map additionalCommands, + Map additionalCommands, @Nullable DriverService service, @Nullable Factory httpClientFactory, - @NonNull AppiumClientConfig appiumClientConfig) { + AppiumClientConfig appiumClientConfig) { super(additionalCommands, appiumClientConfig, - ofNullable(httpClientFactory).orElseGet(AppiumCommandExecutor::getDefaultClientFactory) + ofNullable(httpClientFactory).orElseGet(HttpCommandExecutor::getDefaultClientFactory) ); serviceOptional = ofNullable(service); - this.httpClientFactory = httpClientFactory; this.appiumClientConfig = appiumClientConfig; } public AppiumCommandExecutor(Map additionalCommands, DriverService service, - HttpClient.Factory httpClientFactory) { + @Nullable Factory httpClientFactory) { this(additionalCommands, requireNonNull(service), httpClientFactory, AppiumClientConfig.defaultConfig().baseUrl(requireNonNull(service).getUrl())); } public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, - HttpClient.Factory httpClientFactory) { + @Nullable Factory httpClientFactory) { this(additionalCommands, null, httpClientFactory, AppiumClientConfig.defaultConfig().baseUrl(requireNonNull(addressOfRemoteServer))); } @@ -140,6 +138,11 @@ public Map getAdditionalCommands() { return getPrivateFieldValue(HttpCommandExecutor.class, "additionalCommands", Map.class); } + public Factory getHttpClientFactory() { + return getPrivateFieldValue(HttpCommandExecutor.class, "httpClientFactory", Factory.class); + } + + @Nullable protected CommandCodec getCommandCodec() { return this.commandCodec; } @@ -163,12 +166,8 @@ protected HttpClient getClient() { * @param serverUrl A url to override. */ protected void overrideServerUrl(URL serverUrl) { - if (this.appiumClientConfig == null) { - return; - } - setPrivateFieldValue(HttpCommandExecutor.class, "client", - ofNullable(this.httpClientFactory).orElseGet(AppiumCommandExecutor::getDefaultClientFactory) - .createClient(this.appiumClientConfig.baseUrl(serverUrl))); + HttpClient newClient = getHttpClientFactory().createClient(appiumClientConfig.baseUrl(serverUrl)); + setPrivateFieldValue(HttpCommandExecutor.class, "client", newClient); } private Response createSession(Command command) throws IOException { @@ -186,7 +185,7 @@ private Response createSession(Command command) throws IOException { refreshAdditionalCommands(); setResponseCodec(dialect.getResponseCodec()); Response response = result.createResponse(); - if (this.appiumClientConfig != null && this.appiumClientConfig.isDirectConnectEnabled()) { + if (appiumClientConfig.isDirectConnectEnabled()) { setDirectConnect(response); } diff --git a/src/test/java/io/appium/java_client/remote/AppiumCommandExecutorTest.java b/src/test/java/io/appium/java_client/remote/AppiumCommandExecutorTest.java new file mode 100644 index 000000000..38b1b6459 --- /dev/null +++ b/src/test/java/io/appium/java_client/remote/AppiumCommandExecutorTest.java @@ -0,0 +1,41 @@ +package io.appium.java_client.remote; + +import io.appium.java_client.AppiumClientConfig; +import io.appium.java_client.MobileCommand; +import org.junit.jupiter.api.Test; + +import java.net.MalformedURLException; +import java.net.URL; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class AppiumCommandExecutorTest { + private static final String APPIUM_URL = "https://appium.example.com"; + + private AppiumCommandExecutor createExecutor() { + URL baseUrl; + try { + baseUrl = new URL(APPIUM_URL); + } catch (MalformedURLException e) { + throw new AssertionError(e); + } + AppiumClientConfig clientConfig = AppiumClientConfig.defaultConfig().baseUrl(baseUrl); + return new AppiumCommandExecutor(MobileCommand.commandRepository, clientConfig); + } + + @Test + void getAdditionalCommands() { + assertNotNull(createExecutor().getAdditionalCommands()); + } + + @Test + void getHttpClientFactory() { + assertNotNull(createExecutor().getHttpClientFactory()); + } + + @Test + void overrideServerUrl() { + assertDoesNotThrow(() -> createExecutor().overrideServerUrl(new URL("https://direct.example.com"))); + } +} From b2de541b441239ebfdfef584ceeb967796d9d231 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Wed, 13 Aug 2025 20:31:02 +0300 Subject: [PATCH 458/501] feat: Upgrade to selenium 4.35.0 (#2327) BREAKING CHANGE: Removed all deprecated methods with Selenium's Location and LocationContext (these classes have been removed in Selenium 4.35.0) --- README.md | 1 + build.gradle | 2 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../io/appium/java_client/AppiumDriver.java | 5 --- .../java_client/android/AndroidDriver.java | 15 ------- .../io/appium/java_client/ios/IOSDriver.java | 15 ------- .../java_client/remote/SupportsLocation.java | 44 ++----------------- 8 files changed, 8 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 0d78b2bae..0957c49d2 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ----------------------------------------------------------------------------------------------------|----------------------------- +`10.0.0` | `4.35.0` `9.5.0` | `4.34.0` `9.4.0` | `4.26.0`, `4.27.0`, `4.28.0`, `4.28.1`, `4.29.0`, `4.30.0`, `4.31.0`, `4.32.0`, `4.33.0` `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0`, `4.23.1`, `4.24.0`, `4.25.0`, `4.26.0`, `4.27.0` diff --git a/build.gradle b/build.gradle index be70778ff..1cc9fdc6d 100644 --- a/build.gradle +++ b/build.gradle @@ -188,7 +188,7 @@ jreleaser { } wrapper { - gradleVersion = '8.14' + gradleVersion = '8.14.3' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle.properties b/gradle.properties index f53e0d155..26ac1907c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.34.0 +selenium.version=4.35.0 # Please increment the value in a release appiumClient.version=9.5.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dedd5d1e6..7705927e9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 4c641fd2b..1daf7013e 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -44,7 +44,6 @@ import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec; -import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.remote.http.HttpMethod; @@ -81,8 +80,6 @@ public class AppiumDriver extends RemoteWebDriver implements // frequently used command parameters @Getter private final URL remoteAddress; - @Deprecated(forRemoval = true) - protected final RemoteLocationContext locationContext; private final ExecuteMethod executeMethod; private final Set absentExtensionNames = new HashSet<>(); private URI biDiUri; @@ -100,7 +97,6 @@ public class AppiumDriver extends RemoteWebDriver implements public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, capabilities); this.executeMethod = new AppiumExecutionMethod(this); - locationContext = new RemoteLocationContext(executeMethod); super.setErrorHandler(ERROR_HANDLER); this.remoteAddress = executor.getAddressOfRemoteServer(); } @@ -176,7 +172,6 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa executor.setResponseCodec(new W3CHttpResponseCodec()); setCommandExecutor(executor); this.executeMethod = new AppiumExecutionMethod(this); - this.locationContext = new RemoteLocationContext(executeMethod); super.setErrorHandler(ERROR_HANDLER); this.remoteAddress = executor.getAddressOfRemoteServer(); 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 dfd9a879a..aa1d30159 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -43,7 +43,6 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; import org.openqa.selenium.remote.HttpCommandExecutor; -import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; @@ -251,20 +250,6 @@ public AndroidBatteryInfo getBatteryInfo() { return new AndroidBatteryInfo(CommandExecutionHelper.executeScript(this, "mobile: batteryInfo")); } - /** - * Provides the location context. - * - * @return instance of {@link RemoteLocationContext} - * @deprecated This method, {@link org.openqa.selenium.html5.LocationContext} and {@link RemoteLocationContext} - * interface are deprecated, use {@link #getLocation()} and - * {@link #setLocation(io.appium.java_client.Location)} instead. - */ - @Override - @Deprecated(forRemoval = true) - public RemoteLocationContext getLocationContext() { - return locationContext; - } - @Override public synchronized StringWebSocketClient getLogcatClient() { if (logcatClient == null) { 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 6cc48469e..0fd5cbf20 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -44,7 +44,6 @@ import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; -import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.ClientConfig; import org.openqa.selenium.remote.http.HttpClient; @@ -279,20 +278,6 @@ class IOSAlert implements Alert { } - /** - * Provides the location context. - * - * @return instance of {@link RemoteLocationContext} - * @deprecated This method, {@link org.openqa.selenium.html5.LocationContext} and {@link RemoteLocationContext} - * interface are deprecated, use {@link #getLocation()} and - * {@link #setLocation(io.appium.java_client.Location)} instead. - */ - @Override - @Deprecated(forRemoval = true) - public RemoteLocationContext getLocationContext() { - return locationContext; - } - @Override public synchronized StringWebSocketClient getSyslogClient() { if (syslogClient == null) { diff --git a/src/main/java/io/appium/java_client/remote/SupportsLocation.java b/src/main/java/io/appium/java_client/remote/SupportsLocation.java index 91e12f0fa..c19dcc96c 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsLocation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsLocation.java @@ -18,40 +18,16 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; +import io.appium.java_client.Location; import io.appium.java_client.MobileCommand; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.html5.Location; -import org.openqa.selenium.html5.LocationContext; -import org.openqa.selenium.remote.html5.RemoteLocationContext; import java.util.HashMap; import java.util.Map; import java.util.Optional; -public interface SupportsLocation extends WebDriver, ExecutesMethod, LocationContext { - - /** - * Provides the location context. - * - * @return instance of {@link RemoteLocationContext} - * @deprecated This method, {@link LocationContext} and {@link RemoteLocationContext} interface are deprecated, use - * {@link #getLocation()} and {@link #setLocation(io.appium.java_client.Location)} instead. - */ - @Deprecated(forRemoval = true) - RemoteLocationContext getLocationContext(); - - /** - * Gets the current device's geolocation coordinates. - * - * @return A {@link Location} containing the location information. Returns null if the location is not available - * @deprecated This method and whole {@link LocationContext} interface are deprecated, use {@link #getLocation()} - * instead. - */ - @Deprecated(forRemoval = true) - default Location location() { - return getLocationContext().location(); - } +public interface SupportsLocation extends WebDriver, ExecutesMethod { /** * Gets the current device's geolocation coordinates. @@ -59,9 +35,9 @@ default Location location() { * @return A {@link Location} containing the location information. Throws {@link WebDriverException} if the * location is not available. */ - default io.appium.java_client.Location getLocation() { + default Location getLocation() { Map result = CommandExecutionHelper.execute(this, MobileCommand.GET_LOCATION); - return new io.appium.java_client.Location( + return new Location( result.get("latitude").doubleValue(), result.get("longitude").doubleValue(), Optional.ofNullable(result.get("altitude")).map(Number::doubleValue).orElse(null) @@ -72,20 +48,8 @@ default io.appium.java_client.Location getLocation() { * Sets the current device's geolocation coordinates. * * @param location A {@link Location} containing the new location information. - * @deprecated This method and whole {@link LocationContext} interface are deprecated, use - * {@link #setLocation(io.appium.java_client.Location)} instead. */ - @Deprecated(forRemoval = true) default void setLocation(Location location) { - getLocationContext().setLocation(location); - } - - /** - * Sets the current device's geolocation coordinates. - * - * @param location A {@link Location} containing the new location information. - */ - default void setLocation(io.appium.java_client.Location location) { var locationParameters = new HashMap(); locationParameters.put("latitude", location.getLatitude()); locationParameters.put("longitude", location.getLongitude()); From 6ded147de5fc7c09f4a96e26495a41c3a5f36844 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 13 Aug 2025 22:27:43 +0200 Subject: [PATCH 459/501] docs: Document the migration guide from v9 to v10 (#2331) --- README.md | 5 +++++ docs/v9-to-v10-migration-guide.md | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 docs/v9-to-v10-migration-guide.md diff --git a/README.md b/README.md index 0957c49d2..04af41b52 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,11 @@ This is the Java language bindings for writing Appium Tests that conform to [WebDriver Protocol](https://w3c.github.io/webdriver/) + +## v9 to v10 Migration + +Follow the [v9 to v10 Migration Guide](./docs/v9-to-v10-migration-guide.md) to streamline the migration process. + ## v8 to v9 Migration Since v9 the client only supports Java 11 and above. diff --git a/docs/v9-to-v10-migration-guide.md b/docs/v9-to-v10-migration-guide.md new file mode 100644 index 000000000..40f7e89fe --- /dev/null +++ b/docs/v9-to-v10-migration-guide.md @@ -0,0 +1,17 @@ +This is the list of main changes between major versions 9 and 10 of Appium +java client. This list should help you to successfully migrate your +existing automated tests codebase. + + +## The minimum supported Selenium version is set to 4.35.0 + +- Selenium versions below 4.35.0 won't work with Appium java client 10+. +Check the [Compatibility Matrix](../README.md#compatibility-matrix) for more +details about versions compatibility. + +## Removed previously deprecated items + +- `org.openqa.selenium.remote.html5.RemoteLocationContext`, `org.openqa.selenium.html5.Location` and + `org.openqa.selenium.html5.LocationContext` imports have been removed since they don't exist + in Selenium lib anymore. Use appropriate replacements from this library instead for APIs and + interfaces that were using deprecated classes, like `io.appium.java_client.Location`. From 0b4a430f8e76f48ba166c77a35ab2bd696620741 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 13 Aug 2025 22:29:05 +0200 Subject: [PATCH 460/501] release: v10.0.0 (#2332) --- CHANGELOG.md | 19 +++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e20c7874..deb7aca9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +_10.0.0_ +- **[DOCUMENTATION]** + - Document the migration guide from v9 to v10 [#2331](https://github.com/appium/java-client/pull/2331) + - updated maven central release badge [#2316](https://github.com/appium/java-client/pull/2316) + - updated CI badge to use ci.yml workflow [#2317](https://github.com/appium/java-client/pull/2317) +- **[BREAKING CHANGE]** [#2327](https://github.com/appium/java-client/pull/2327) + - Removed all deprecated methods with Selenium's Location and LocationContext (these classes have been removed in Selenium 4.35.0) +- **[ENHANCEMENTS]** + - Proxy commands issues via RemoteWebElement [#2311](https://github.com/appium/java-client/pull/2311) + - Automated Release to Maven Central Repository using JReleaser [#2313](https://github.com/appium/java-client/pull/2313) +- **[BUG FIX]** + - Possible NPE in initBiDi() [#2325](https://github.com/appium/java-client/pull/2325) +- **[DEPENDENCY CHANGE]** + - Bump minimum Selenium version to 4.35.0 [#2327](https://github.com/appium/java-client/pull/2327) + - Bump org.junit.jupiter:junit-jupiter from 5.13.2 to 5.13.3 [#2314](https://github.com/appium/java-client/pull/2314) + - Bump io.github.bonigarcia:webdrivermanager [#2322](https://github.com/appium/java-client/pull/2322) + - Bump com.gradleup.shadow from 8.3.7 to 8.3.8 [#2315](https://github.com/appium/java-client/pull/2315) + - Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 [#2320](https://github.com/appium/java-client/pull/2320) + _9.5.0_ - **[ENHANCEMENTS]** - Allow extension capability keys to contain dot characters [#2271](https://github.com/appium/java-client/pull/2271) diff --git a/gradle.properties b/gradle.properties index 26ac1907c..6053da655 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ org.gradle.daemon=true selenium.version=4.35.0 # Please increment the value in a release -appiumClient.version=9.5.0 +appiumClient.version=10.0.0 From 374b301a0f41fc5a004919ea10f690190738cc07 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 28 Sep 2025 09:31:47 +0200 Subject: [PATCH 461/501] test: Update the security flag format for Appium3 (#2348) --- .../appium/java_client/android/BaseFlutterTest.java | 2 +- .../java/io/appium/java_client/ios/BaseIOSTest.java | 2 ++ .../io/appium/java_client/ios/IOSContextTest.java | 13 ++++++++++++- .../io/appium/java_client/ios/IOSDriverTest.java | 10 +++++----- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java index 1c502c4f4..a141f01ef 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/BaseFlutterTest.java @@ -48,7 +48,7 @@ public static void beforeClass() { // Flutter driver mocking command requires adb_shell permission to set certain permissions // to the AUT. This can be removed once the server logic is updated to use a different approach // for setting the permission - .withArgument(GeneralServerFlag.ALLOW_INSECURE, "adb_shell") + .withArgument(GeneralServerFlag.ALLOW_INSECURE, "*:adb_shell") .build(); service.start(); } diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java index 73772390f..8fa488750 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSTest.java @@ -18,6 +18,7 @@ import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; +import io.appium.java_client.service.local.flags.GeneralServerFlag; import org.junit.jupiter.api.AfterAll; import java.time.Duration; @@ -49,6 +50,7 @@ public static AppiumDriverLocalService startAppiumServer() { .withIPAddress("127.0.0.1") .usingPort(PORT) .withTimeout(SERVER_START_TIMEOUT) + .withArgument(GeneralServerFlag.ALLOW_INSECURE, "*:session_discovery") .build(); service.start(); return service; diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java index c7e0af42f..999957aaa 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java @@ -17,6 +17,8 @@ package io.appium.java_client.ios; import io.appium.java_client.NoSuchContextException; +import io.appium.java_client.TestUtils; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; @@ -32,10 +34,16 @@ public class IOSContextTest extends BaseIOSWebViewTest { } @Test public void testGetContextHandles() { - assertEquals(driver.getContextHandles().size(), 2); + // this test is not stable in the CI env due to simulator slowness + Assumptions.assumeFalse(TestUtils.isCiEnv()); + + assertEquals(2, driver.getContextHandles().size()); } @Test public void testSwitchContext() throws InterruptedException { + // this test is not stable in the CI env due to simulator slowness + Assumptions.assumeFalse(TestUtils.isCiEnv()); + driver.getContextHandles(); findAndSwitchToWebView(); assertThat(driver.getContext(), containsString("WEBVIEW")); @@ -43,6 +51,9 @@ public class IOSContextTest extends BaseIOSWebViewTest { } @Test public void testContextError() { + // this test is not stable in the CI env due to simulator slowness + Assumptions.assumeFalse(TestUtils.isCiEnv()); + assertThrows(NoSuchContextException.class, () -> driver.context("Planet of the Ape-ium")); } } diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java index 438178e36..3ad036b4d 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java @@ -50,17 +50,17 @@ public void setupEach() { @Test public void addCustomCommandTest() { - driver.addCommand(HttpMethod.GET, "/sessions", "getSessions"); + driver.addCommand(HttpMethod.GET, "/appium/sessions", "getSessions"); final Response getSessions = driver.execute("getSessions"); assertNotNull(getSessions.getSessionId()); } @Test public void addCustomCommandWithSessionIdTest() { - driver.addCommand(HttpMethod.POST, "/session/" + driver.getSessionId() + "/appium/app/strings", - "getAppStrings"); - final Response getStrings = driver.execute("getAppStrings"); - assertNotNull(getStrings.getSessionId()); + driver.addCommand(HttpMethod.GET, "/session/" + driver.getSessionId() + "/appium/settings", + "getSessionSettings"); + final Response getSessionSettings = driver.execute("getSessionSettings"); + assertNotNull(getSessionSettings.getSessionId()); } @Test From bac5b4823f75e55b96d31cfd198fd0cad597a859 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:32:42 +0200 Subject: [PATCH 462/501] build(deps): Bump actions/setup-java from 4 to 5 (#2334) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4 to 5. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33ac2e644..62e2d8e14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,7 +69,7 @@ jobs: sudo udevadm trigger --name-match=kvm - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ matrix.java }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6392f5692..1bbe85806 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,7 +8,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: '11' distribution: 'zulu' From 32e83a2f8aaba66dd9bd4dfb13ae7514983a9039 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:32:57 +0200 Subject: [PATCH 463/501] build(deps): Bump actions/setup-node from 4 to 5 (#2338) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 5. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62e2d8e14..e0f86d4d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: - name: Install Node.js if: ${{ matrix.e2e-tests }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: 'lts/*' From 16103cd9a46549e5fd4e842076d2ab57dced8a63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:33:17 +0200 Subject: [PATCH 464/501] build(deps): Bump actions/checkout from 4 to 5 (#2335) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0f86d4d1..1ecfc529a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: name: JDK ${{ matrix.java }} - ${{ matrix.platform }} ${{ matrix.e2e-tests }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Enable KVM group perms if: matrix.e2e-tests == 'android' || matrix.e2e-tests == 'flutter-android' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1bbe85806..48283ff61 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,7 +6,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Java uses: actions/setup-java@v5 with: From c1ed8a0f43656e2ae9af066c91b7063d716a3532 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:33:46 +0200 Subject: [PATCH 465/501] build(deps): Bump com.google.code.gson:gson from 2.13.1 to 2.13.2 (#2342) Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.13.1 to 2.13.2. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.13.1...gson-parent-2.13.2) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-version: 2.13.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1cc9fdc6d..1d15d3831 100644 --- a/build.gradle +++ b/build.gradle @@ -69,7 +69,7 @@ dependencies { } } } - implementation 'com.google.code.gson:gson:2.13.1' + implementation 'com.google.code.gson:gson:2.13.2' implementation "org.slf4j:slf4j-api:${slf4jVersion}" implementation 'org.jspecify:jspecify:1.0.0' } From 0835090ea6dbb54c22483fcaad015a7eb54d2b78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:34:05 +0200 Subject: [PATCH 466/501] build(deps): Bump org.projectlombok:lombok from 1.18.38 to 1.18.42 (#2345) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.38 to 1.18.42. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.38...v1.18.42) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-version: 1.18.42 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1d15d3831..bc6fc8737 100644 --- a/build.gradle +++ b/build.gradle @@ -42,8 +42,8 @@ java { } dependencies { - compileOnly 'org.projectlombok:lombok:1.18.38' - annotationProcessor 'org.projectlombok:lombok:1.18.38' + compileOnly 'org.projectlombok:lombok:1.18.42' + annotationProcessor 'org.projectlombok:lombok:1.18.42' if (project.hasProperty("isCI")) { api "org.seleniumhq.selenium:selenium-api:${seleniumVersion}" From 02163ad6df5f73cdb3fc55945f1b789010059003 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 09:34:33 +0200 Subject: [PATCH 467/501] build(deps): Bump io.github.bonigarcia:webdrivermanager (#2343) Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 6.2.0 to 6.3.2. - [Release notes](https://github.com/bonigarcia/webdrivermanager/releases) - [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md) - [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-6.2.0...webdrivermanager-6.3.2) --- updated-dependencies: - dependency-name: io.github.bonigarcia:webdrivermanager dependency-version: 6.3.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index bc6fc8737..d13cd603a 100644 --- a/build.gradle +++ b/build.gradle @@ -222,7 +222,7 @@ testing { test { dependencies { implementation "org.seleniumhq.selenium:selenium-chrome-driver:${seleniumVersion}" - implementation('io.github.bonigarcia:webdrivermanager:6.2.0') { + implementation('io.github.bonigarcia:webdrivermanager:6.3.2') { exclude group: 'org.seleniumhq.selenium' } } @@ -266,7 +266,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('io.github.bonigarcia:webdrivermanager:6.2.0') { + implementation('io.github.bonigarcia:webdrivermanager:6.3.2') { exclude group: 'org.seleniumhq.selenium' } } From 059bd48558840f513bf421f2dc256acc0c347f44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 10:09:37 +0200 Subject: [PATCH 468/501] build(deps): Bump org.owasp.dependencycheck from 12.1.3 to 12.1.5 (#2344) Bumps org.owasp.dependencycheck from 12.1.3 to 12.1.5. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-version: 12.1.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d13cd603a..4dd526207 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.1.3' + id 'org.owasp.dependencycheck' version '12.1.6' id 'com.gradleup.shadow' version '8.3.8' id 'org.jreleaser' version '1.19.0' } From 872905bc894833254d89b0934bc47df2ddd3a8e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 10:28:46 +0200 Subject: [PATCH 469/501] build(deps): Bump org.jreleaser from 1.19.0 to 1.20.0 (#2336) Bumps org.jreleaser from 1.19.0 to 1.20.0. --- updated-dependencies: - dependency-name: org.jreleaser dependency-version: 1.20.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4dd526207..5a9477ad5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id 'signing' id 'org.owasp.dependencycheck' version '12.1.6' id 'com.gradleup.shadow' version '8.3.8' - id 'org.jreleaser' version '1.19.0' + id 'org.jreleaser' version '1.20.0' } ext { From e0329917fb099d09d4fb685004fb68eef0f08f1e Mon Sep 17 00:00:00 2001 From: Noritaka Kobayashi Date: Mon, 29 Sep 2025 00:51:02 +0900 Subject: [PATCH 470/501] chore: fix typos (#2347) --- CHANGELOG.md | 6 +++--- docs/Advanced-By.md | 2 +- docs/How-to-report-an-issue.md | 8 ++++---- docs/Page-objects.md | 20 +++++++++---------- docs/environment.md | 2 +- .../appium/java_client/AppiumCommandInfo.java | 2 +- .../android/nativekey/AndroidKey.java | 2 +- .../adb/SupportsLogcatFilterSpecsOption.java | 2 +- .../imagecomparison/ComparisonResult.java | 2 +- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index deb7aca9b..1f189e2cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -686,14 +686,14 @@ _8.6.0_ *6.0.0-BETA1* - **[ENHANCEMENT]** **[REFACTOR]** **[BREAKING CHANGE]** **[MAJOR CHANGE]** Improvements of the TouchActions API [#756](https://github.com/appium/java-client/pull/756), [#760](https://github.com/appium/java-client/pull/760): - - `io.appium.java_client.touch.ActionOptions` and sublasses were added + - `io.appium.java_client.touch.ActionOptions` and subclasses were added - old methods of the `TouchActions` were marked `@Deprecated` - new methods which take new options. -- **[ENHANCEMENT]**. Appium drivr local service uses default process environment by default. [#753](https://github.com/appium/java-client/pull/753) +- **[ENHANCEMENT]**. Appium driver local service uses default process environment by default. [#753](https://github.com/appium/java-client/pull/753) - **[BUG FIX]**. Removed 'set' prefix from waitForIdleTimeout setting. [#754](https://github.com/appium/java-client/pull/754) - **[BUG FIX]**. The asking for session details was optimized. Issue report [764](https://github.com/appium/java-client/issues/764). FIX [#769](https://github.com/appium/java-client/pull/769) -- **[BUG FIX]** **[REFACTOR]**. Inconcistent MissingParameterException was removed. Improvements of MultiTouchAction. Report: [#102](https://github.com/appium/java-client/issues/102). FIX [#772](https://github.com/appium/java-client/pull/772) +- **[BUG FIX]** **[REFACTOR]**. Inconsistent MissingParameterException was removed. Improvements of MultiTouchAction. Report: [#102](https://github.com/appium/java-client/issues/102). FIX [#772](https://github.com/appium/java-client/pull/772) - **[DEPENDENCY UPDATES]** - `org.apache.commons:commons-lang3` was updated to 3.7 - `commons-io:commons-io` was updated to 2.6 diff --git a/docs/Advanced-By.md b/docs/Advanced-By.md index 4226ed9f6..96609f2a7 100644 --- a/docs/Advanced-By.md +++ b/docs/Advanced-By.md @@ -48,7 +48,7 @@ XCUIElementTypeCell[$label == 'here'$] #### Handling Quote Marks Most of the time, you can treat pairs of single quotes or double quotes -interchangably. If you're searching with a string that contains quote marks, +interchangeably. If you're searching with a string that contains quote marks, though, you [need to be careful](https://stackoverflow.com/q/14116217). ```c diff --git a/docs/How-to-report-an-issue.md b/docs/How-to-report-an-issue.md index 95be8f584..863c90187 100644 --- a/docs/How-to-report-an-issue.md +++ b/docs/How-to-report-an-issue.md @@ -1,6 +1,6 @@ # Be sure that it is not a server-side problem if you are facing something that looks like a bug -The Appium Java client is the thin client which just sends requests and receives responces generally. +The Appium Java client is the thin client which just sends requests and receives responses generally. Be sure that this bug is not reported [here](https://github.com/appium/appium/issues) and/or there is no progress on this issue. @@ -13,8 +13,8 @@ If it is the feature request then there should be the description of this featur ### Environment (bug report) -* java client build version or git revision if you use some shapshot: -* Appium server version or git revision if you use some shapshot: +* java client build version or git revision if you use some snapshot: +* Appium server version or git revision if you use some snapshot: * Desktop OS/version used to run Appium if necessary: * Node.js version (unless using Appium.app|exe) or Appium CLI or Appium.app|exe: * Mobile platform/version under test: @@ -32,7 +32,7 @@ You can git clone https://github.com/appium/appium/tree/master/sample-code or ht Also you can create a [gist](https://gist.github.com) with pasted java code sample or paste it at ussue description using markdown. About markdown please read [Mastering markdown](https://guides.github.com/features/mastering-markdown/) and [Writing on GitHub](https://help.github.com/categories/writing-on-github/) -### Ecxeption stacktraces (bug report) +### Exception stacktraces (bug report) There should be created a [gist](https://gist.github.com) with pasted stacktrace of exception thrown by java. diff --git a/docs/Page-objects.md b/docs/Page-objects.md index ce7a04f1f..f3e1c9627 100644 --- a/docs/Page-objects.md +++ b/docs/Page-objects.md @@ -16,7 +16,7 @@ WebElement someElement; List someElements; ``` -# If there is need to use convinient locators for mobile native applications then the following is available: +# If there is need to use convenient locators for mobile native applications then the following is available: ```java import io.appium.java_client.android.AndroidElement; @@ -324,13 +324,13 @@ A typical page object could look like: ```java public class RottenTomatoesScreen { - //convinient locator + //convenient locator private List titles; - //convinient locator + //convenient locator private List scores; - //convinient locator + //convenient locator private List castings; //element declaration goes on @@ -371,13 +371,13 @@ public class Movie extends Widget{ super(element); } - //convinient locator + //convenient locator private AndroidElement title; - //convinient locator + //convenient locator private AndroidElement score; - //convinient locator + //convenient locator private AndroidElement casting; public String getTitle(params){ @@ -404,7 +404,7 @@ So, now page object looks ```java public class RottenTomatoesScreen { - @AndroidFindBy(a locator which convinient to find a single movie-root - element) + @AndroidFindBy(a locator which convenient to find a single movie-root - element) private List movies; //element declaration goes on @@ -427,7 +427,7 @@ public class RottenTomatoesScreen { Then ```java //the class is annotated !!! -@AndroidFindBy(a locator which convinient to find a single movie-root - element) +@AndroidFindBy(a locator which convenient to find a single movie-root - element) public class Movie extends Widget{ ... } @@ -658,7 +658,7 @@ This use case has some restrictions; - All classes which are declared by the OverrideWidget annotation should be subclasses of the class declared by field -- All classes which are declared by the OverrideWidget should not be abstract. If a declared class is overriden partially like +- All classes which are declared by the OverrideWidget should not be abstract. If a declared class is overridden partially like ```java //above is the other field declaration diff --git a/docs/environment.md b/docs/environment.md index 1af2f306c..a08a6ea6e 100644 --- a/docs/environment.md +++ b/docs/environment.md @@ -32,4 +32,4 @@ Remember to reload the config after it has been changed by restarting the comman Also, it is possible to set variables on [per-process](https://stackoverflow.com/questions/10856129/setting-an-environment-variable-before-a-command-in-bash-not-working-for-second) basis. This might be handy if Appium is set up to start automatically with the operating system, because on early stages of system initialization it is possible that the "usual" environment has not been loaded yet. -In case the Appium process is started programatically, for example with java client's `AppiumDriverLocalService` helper class, then it might be necessary to setup the environment [in the client code](https://github.com/appium/java-client/pull/753), because prior to version 6.0 the client does not inherit it from the parent process by default. +In case the Appium process is started programmatically, for example with java client's `AppiumDriverLocalService` helper class, then it might be necessary to setup the environment [in the client code](https://github.com/appium/java-client/pull/753), because prior to version 6.0 the client does not inherit it from the parent process by default. diff --git a/src/main/java/io/appium/java_client/AppiumCommandInfo.java b/src/main/java/io/appium/java_client/AppiumCommandInfo.java index cea6016d5..e41ba3699 100644 --- a/src/main/java/io/appium/java_client/AppiumCommandInfo.java +++ b/src/main/java/io/appium/java_client/AppiumCommandInfo.java @@ -26,7 +26,7 @@ public class AppiumCommandInfo extends CommandInfo { @Getter(AccessLevel.PUBLIC) private final HttpMethod method; /** - * It conntains method and URL of the command. + * It contains method and URL of the command. * * @param url command URL * @param method is http-method diff --git a/src/main/java/io/appium/java_client/android/nativekey/AndroidKey.java b/src/main/java/io/appium/java_client/android/nativekey/AndroidKey.java index c0a809801..4138ea69f 100644 --- a/src/main/java/io/appium/java_client/android/nativekey/AndroidKey.java +++ b/src/main/java/io/appium/java_client/android/nativekey/AndroidKey.java @@ -1094,7 +1094,7 @@ public enum AndroidKey { TV_SATELLITE_SERVICE(240), /** * Key code constant: Toggle Network key. - * Toggles selecting broacast services. + * Toggles selecting broadcast services. */ TV_NETWORK(241), /** diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java index e671e4848..f58076fe6 100644 --- a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java +++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java @@ -33,7 +33,7 @@ public interface SupportsLogcatFilterSpecsOption> exten * @param format The filter specifier. Consists from series of `tag[:priority]` items, * where `tag` is a log component tag (or `*` to match any value) * and `priority`: V (Verbose), D (Debug), I (Info), W (Warn), E (Error), F (Fatal), - * S (Silent - supresses all output). `tag` without `priority` defaults to `tag:v`. + * S (Silent - suppresses all output). `tag` without `priority` defaults to `tag:v`. * If not specified, filterspec is set from ANDROID_LOG_TAGS environment variable. * If no filterspec is found, filter defaults to `*:I`, which means * to only show log lines with any tag and the log level INFO or higher. diff --git a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java index 0fba408d4..e73be71c8 100644 --- a/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java +++ b/src/main/java/io/appium/java_client/imagecomparison/ComparisonResult.java @@ -42,7 +42,7 @@ protected Map getResultAsMap() { } /** - * Verifies if the corresponding property is present in the commend result + * Verifies if the corresponding property is present in the command result * and throws an exception if not. * * @param propertyName the actual property name to be verified for presence From 9b84f90cc89843333ea9ce0d7680f5f1f5441d39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 07:58:19 +0200 Subject: [PATCH 471/501] build(deps): Bump com.gradleup.shadow from 8.3.8 to 9.1.0 (#2337) * build(deps): Bump com.gradleup.shadow from 8.3.8 to 9.1.0 Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 8.3.8 to 9.1.0. - [Release notes](https://github.com/GradleUp/shadow/releases) - [Commits](https://github.com/GradleUp/shadow/compare/8.3.8...9.1.0) --- updated-dependencies: - dependency-name: com.gradleup.shadow dependency-version: 9.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Bump java --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mykola Mokhnach --- .github/workflows/ci.yml | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ecfc529a..5919afe9c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: strategy: matrix: include: - - java: 11 + - java: 17 # Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available platform: macos-14 e2e-tests: ios diff --git a/build.gradle b/build.gradle index 5a9477ad5..d88813d35 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'jacoco' id 'signing' id 'org.owasp.dependencycheck' version '12.1.6' - id 'com.gradleup.shadow' version '8.3.8' + id 'com.gradleup.shadow' version '9.2.2' id 'org.jreleaser' version '1.20.0' } From c13f27e53ff45f82936325fdefaccb7e0a8204d3 Mon Sep 17 00:00:00 2001 From: itkhanz <62521743+itkhanz@users.noreply.github.com> Date: Mon, 29 Sep 2025 10:43:14 +0200 Subject: [PATCH 472/501] build: Bump gradle to v9.0.0 (#2324) Co-authored-by: Valery Yatsynovich --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43764 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 9 +++++---- gradlew.bat | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index d88813d35..447003a10 100644 --- a/build.gradle +++ b/build.gradle @@ -188,7 +188,7 @@ jreleaser { } wrapper { - gradleVersion = '8.14.3' + gradleVersion = '9.0.0' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baabb587c669f562ae36f953de2481846..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch delta 34964 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

    Gn4F+B~IivciU9^t0j-Mgao3 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 delta 35074 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

    9HXbnx{yu=160arMI&0;a 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 z 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7705927e9..48b43d350 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a936..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -86,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,7 +115,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -205,7 +206,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -213,7 +214,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee84..9b42019c7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 95f1913946cc5133b4d68292dd51db03b0f6b1ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 18:22:56 +0200 Subject: [PATCH 473/501] build(deps): Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 (#2350) Bumps org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.19.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 447003a10..6c2aec2d3 100644 --- a/build.gradle +++ b/build.gradle @@ -242,7 +242,7 @@ testing { dependencies { implementation project() implementation(sourceSets.test.output) - implementation('org.apache.commons:commons-lang3:3.18.0') + implementation('org.apache.commons:commons-lang3:3.19.0') } targets.configureEach { From c9ac5a2879b56c2534b36e39560f757dce52a49c Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Fri, 3 Oct 2025 11:56:26 +0300 Subject: [PATCH 474/501] fix: avoid using system default locale (#2352) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For example, if the system default locale is Turkish ("tr_TR"), then `ClipboardContentType.PLAINTEXT` argument gets converted to "plaıntext", not "plaintext". 1. Replace `toLowerCase()` -> `toLowerCase(ROOT)` 2. Replace `toUpperCase()` -> `toUpperCase(ROOT)` "ROOT" is a specific locale that at least works well for latin letters (that are used in content types, enum names etc.) --- .../android/AndroidScreenRecordTest.java | 3 ++- .../io/appium/java_client/HasBrowserCheck.java | 3 ++- .../android/AndroidMobileCommandHelper.java | 10 ++++++---- .../android/HasAndroidClipboard.java | 3 ++- .../SupportsSpecialEmulatorCommands.java | 17 +++++++++-------- .../java_client/clipboard/HasClipboard.java | 5 +++-- .../driverscripts/ScriptOptions.java | 3 ++- .../gecko/options/SupportsVerbosityOption.java | 6 ++++-- .../filters/AppiumIdempotencyFilter.java | 5 +++-- .../internal/filters/AppiumUserAgentFilter.java | 4 +++- .../ios/IOSStartScreenRecordingOptions.java | 3 ++- ...sSimulatorPasteboardAutomaticSyncOption.java | 6 ++++-- .../pagefactory/OverrideWidgetReader.java | 3 ++- .../utils/WebDriverUnpackUtility.java | 3 ++- .../java_client/remote/SupportsRotation.java | 6 ++++-- .../options/SupportsOrientationOption.java | 4 +++- .../options/SupportsPageLoadStrategyOption.java | 4 +++- .../remote/options/UnhandledPromptBehavior.java | 4 +++- .../service/local/AppiumDriverLocalService.java | 3 ++- .../service/local/AppiumServiceBuilder.java | 3 ++- 20 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidScreenRecordTest.java b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidScreenRecordTest.java index b9abd9ff6..5fef68b48 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidScreenRecordTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/AndroidScreenRecordTest.java @@ -6,6 +6,7 @@ import java.time.Duration; +import static java.util.Locale.ROOT; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; @@ -26,7 +27,7 @@ public void verifyBasicScreenRecordingWorks() throws InterruptedException { .withTimeLimit(Duration.ofSeconds(5)) ); } catch (WebDriverException e) { - if (e.getMessage().toLowerCase().contains("emulator")) { + if (e.getMessage() != null && e.getMessage().toLowerCase(ROOT).contains("emulator")) { // screen recording only works on real devices return; } diff --git a/src/main/java/io/appium/java_client/HasBrowserCheck.java b/src/main/java/io/appium/java_client/HasBrowserCheck.java index eea25072e..a75ffbfd4 100644 --- a/src/main/java/io/appium/java_client/HasBrowserCheck.java +++ b/src/main/java/io/appium/java_client/HasBrowserCheck.java @@ -7,6 +7,7 @@ import org.openqa.selenium.remote.CapabilityType; import static com.google.common.base.Strings.isNullOrEmpty; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; public interface HasBrowserCheck extends ExecutesMethod, HasCapabilities { @@ -34,7 +35,7 @@ default boolean isBrowser() { } try { var context = ((SupportsContextSwitching) this).getContext(); - return context != null && !context.toUpperCase().contains(NATIVE_CONTEXT); + return context != null && !context.toUpperCase(ROOT).contains(NATIVE_CONTEXT); } catch (WebDriverException e) { return false; } 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 8c294c4c0..cacc04137 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -21,6 +21,8 @@ import java.util.Map; +import static java.util.Locale.ROOT; + /** * This util class helps to prepare parameters of Android-specific JSONWP * commands. @@ -241,7 +243,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { String phoneNumber, GsmCallActions gsmCallActions) { return Map.entry(GSM_CALL, Map.of( "phoneNumber", phoneNumber, - "action", gsmCallActions.name().toLowerCase() + "action", gsmCallActions.name().toLowerCase(ROOT) )); } @@ -275,7 +277,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> gsmVoiceCommand( GsmVoiceState gsmVoiceState) { - return Map.entry(GSM_VOICE, Map.of("state", gsmVoiceState.name().toLowerCase())); + return Map.entry(GSM_VOICE, Map.of("state", gsmVoiceState.name().toLowerCase(ROOT))); } /** @@ -289,7 +291,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> networkSpeedCommand( NetworkSpeed networkSpeed) { - return Map.entry(NETWORK_SPEED, Map.of("netspeed", networkSpeed.name().toLowerCase())); + return Map.entry(NETWORK_SPEED, Map.of("netspeed", networkSpeed.name().toLowerCase(ROOT))); } /** @@ -317,7 +319,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { @Deprecated public static Map.Entry> powerACCommand( PowerACState powerACState) { - return Map.entry(POWER_AC_STATE, Map.of("state", powerACState.name().toLowerCase())); + return Map.entry(POWER_AC_STATE, Map.of("state", powerACState.name().toLowerCase(ROOT))); } /** diff --git a/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java b/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java index 49a657898..8b7018e76 100644 --- a/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java +++ b/src/main/java/io/appium/java_client/android/HasAndroidClipboard.java @@ -25,6 +25,7 @@ import java.util.Map; import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; public interface HasAndroidClipboard extends HasClipboard { @@ -39,7 +40,7 @@ default void setClipboard(String label, ClipboardContentType contentType, byte[] CommandExecutionHelper.execute(this, Map.entry(SET_CLIPBOARD, Map.of( "content", new String(requireNonNull(base64Content), StandardCharsets.UTF_8), - "contentType", contentType.name().toLowerCase(), + "contentType", contentType.name().toLowerCase(ROOT), "label", requireNonNull(label) ) )); diff --git a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java index c60d8eaf9..bb618b8cd 100644 --- a/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java +++ b/src/main/java/io/appium/java_client/android/SupportsSpecialEmulatorCommands.java @@ -14,6 +14,7 @@ import static io.appium.java_client.MobileCommand.POWER_AC_STATE; import static io.appium.java_client.MobileCommand.POWER_CAPACITY; import static io.appium.java_client.MobileCommand.SEND_SMS; +import static java.util.Locale.ROOT; public interface SupportsSpecialEmulatorCommands extends ExecutesMethod, CanRememberExtensionPresence { @@ -53,7 +54,7 @@ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { try { CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( "phoneNumber", phoneNumber, - "action", gsmCallAction.toString().toLowerCase() + "action", gsmCallAction.toString().toLowerCase(ROOT) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback @@ -61,7 +62,7 @@ default void makeGsmCall(String phoneNumber, GsmCallActions gsmCallAction) { markExtensionAbsence(extName), Map.entry(GSM_CALL, Map.of( "phoneNumber", phoneNumber, - "action", gsmCallAction.toString().toLowerCase() + "action", gsmCallAction.toString().toLowerCase(ROOT) )) ); } @@ -99,14 +100,14 @@ default void setGsmVoice(GsmVoiceState gsmVoiceState) { final String extName = "mobile: gsmVoice"; try { CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( - "state", gsmVoiceState.toString().toLowerCase() + "state", gsmVoiceState.toString().toLowerCase(ROOT) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), Map.entry(GSM_VOICE, Map.of( - "state", gsmVoiceState.name().toLowerCase() + "state", gsmVoiceState.name().toLowerCase(ROOT) )) ); } @@ -121,14 +122,14 @@ default void setNetworkSpeed(NetworkSpeed networkSpeed) { final String extName = "mobile: networkSpeed"; try { CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( - "speed", networkSpeed.toString().toLowerCase() + "speed", networkSpeed.toString().toLowerCase(ROOT) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), Map.entry(NETWORK_SPEED, Map.of( - "netspeed", networkSpeed.name().toLowerCase() + "netspeed", networkSpeed.name().toLowerCase(ROOT) )) ); } @@ -165,14 +166,14 @@ default void setPowerAC(PowerACState powerACState) { final String extName = "mobile: powerAC"; try { CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, Map.of( - "state", powerACState.toString().toLowerCase() + "state", powerACState.toString().toLowerCase(ROOT) )); } catch (UnsupportedCommandException e) { // TODO: Remove the fallback CommandExecutionHelper.execute( markExtensionAbsence(extName), Map.entry(POWER_AC_STATE, Map.of( - "state", powerACState.name().toLowerCase() + "state", powerACState.name().toLowerCase(ROOT) )) ); } diff --git a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java index 24384da13..ae507f940 100644 --- a/src/main/java/io/appium/java_client/clipboard/HasClipboard.java +++ b/src/main/java/io/appium/java_client/clipboard/HasClipboard.java @@ -27,6 +27,7 @@ import static io.appium.java_client.MobileCommand.GET_CLIPBOARD; import static io.appium.java_client.MobileCommand.SET_CLIPBOARD; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; public interface HasClipboard extends ExecutesMethod, CanRememberExtensionPresence { @@ -40,7 +41,7 @@ default void setClipboard(ClipboardContentType contentType, byte[] base64Content final String extName = "mobile: setClipboard"; var args = Map.of( "content", new String(requireNonNull(base64Content), StandardCharsets.UTF_8), - "contentType", contentType.name().toLowerCase() + "contentType", contentType.name().toLowerCase(ROOT) ); try { CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); @@ -58,7 +59,7 @@ default void setClipboard(ClipboardContentType contentType, byte[] base64Content */ default String getClipboard(ClipboardContentType contentType) { final String extName = "mobile: getClipboard"; - var args = Map.of("contentType", contentType.name().toLowerCase()); + var args = Map.of("contentType", contentType.name().toLowerCase(ROOT)); try { return CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args); } catch (UnsupportedCommandException e) { diff --git a/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java b/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java index 41b5cd78e..7eac89083 100644 --- a/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java +++ b/src/main/java/io/appium/java_client/driverscripts/ScriptOptions.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.Map; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; @@ -59,7 +60,7 @@ public ScriptOptions withTimeout(long timeoutMs) { */ public Map build() { var map = new HashMap(); - ofNullable(scriptType).ifPresent(x -> map.put("type", x.name().toLowerCase())); + ofNullable(scriptType).ifPresent(x -> map.put("type", x.name().toLowerCase(ROOT))); ofNullable(timeoutMs).ifPresent(x -> map.put("timeout", x)); return Collections.unmodifiableMap(map); } diff --git a/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java b/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java index 60e479079..32d37f61e 100644 --- a/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java +++ b/src/main/java/io/appium/java_client/gecko/options/SupportsVerbosityOption.java @@ -22,6 +22,8 @@ import java.util.Optional; +import static java.util.Locale.ROOT; + public interface SupportsVerbosityOption> extends Capabilities, CanSetCapability { String VERBOSITY_OPTION = "verbosity"; @@ -34,7 +36,7 @@ public interface SupportsVerbosityOption> extends * @return self instance for chaining. */ default T setVerbosity(Verbosity verbosity) { - return amend(VERBOSITY_OPTION, verbosity.name().toLowerCase()); + return amend(VERBOSITY_OPTION, verbosity.name().toLowerCase(ROOT)); } /** @@ -45,7 +47,7 @@ default T setVerbosity(Verbosity verbosity) { default Optional getVerbosity() { return Optional.ofNullable(getCapability(VERBOSITY_OPTION)) .map(String::valueOf) - .map(String::toUpperCase) + .map(verbosity -> verbosity.toUpperCase(ROOT)) .map(Verbosity::valueOf); } } diff --git a/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java index 9a8f8156b..b075c9b6b 100644 --- a/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumIdempotencyFilter.java @@ -20,7 +20,8 @@ import org.openqa.selenium.remote.http.HttpHandler; import org.openqa.selenium.remote.http.HttpMethod; -import java.util.UUID; +import static java.util.Locale.ROOT; +import static java.util.UUID.randomUUID; public class AppiumIdempotencyFilter implements Filter { // https://github.com/appium/appium-base-driver/pull/400 @@ -30,7 +31,7 @@ public class AppiumIdempotencyFilter implements Filter { public HttpHandler apply(HttpHandler next) { return req -> { if (req.getMethod() == HttpMethod.POST && req.getUri().endsWith("/session")) { - req.setHeader(IDEMPOTENCY_KEY_HEADER, UUID.randomUUID().toString().toLowerCase()); + req.setHeader(IDEMPOTENCY_KEY_HEADER, randomUUID().toString().toLowerCase(ROOT)); } return next.execute(req); }; diff --git a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java index b8086e1f8..030666ab6 100644 --- a/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java +++ b/src/main/java/io/appium/java_client/internal/filters/AppiumUserAgentFilter.java @@ -24,6 +24,8 @@ import org.openqa.selenium.remote.http.HttpHandler; import org.openqa.selenium.remote.http.HttpHeader; +import static java.util.Locale.ROOT; + /** * Manage Appium Client configurations. */ @@ -54,7 +56,7 @@ private static String buildUserAgentHeaderValue(@NonNull String previousUA) { * like by this filter. */ private static boolean containsAppiumName(@Nullable String userAgent) { - return userAgent != null && userAgent.toLowerCase().contains(USER_AGENT_PREFIX.toLowerCase()); + return userAgent != null && userAgent.toLowerCase(ROOT).contains(USER_AGENT_PREFIX.toLowerCase(ROOT)); } /** diff --git a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java index a608cae0f..5c56cd9a5 100644 --- a/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java +++ b/src/main/java/io/appium/java_client/ios/IOSStartScreenRecordingOptions.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.Map; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; @@ -73,7 +74,7 @@ public enum VideoQuality { * @return self instance for chaining. */ public IOSStartScreenRecordingOptions withVideoQuality(VideoQuality videoQuality) { - this.videoQuality = requireNonNull(videoQuality).name().toLowerCase(); + this.videoQuality = requireNonNull(videoQuality).name().toLowerCase(ROOT); return this; } diff --git a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java index 665c4d368..5f3f5615b 100644 --- a/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java +++ b/src/main/java/io/appium/java_client/ios/options/simulator/SupportsSimulatorPasteboardAutomaticSyncOption.java @@ -22,6 +22,8 @@ import java.util.Optional; +import static java.util.Locale.ROOT; + public interface SupportsSimulatorPasteboardAutomaticSyncOption> extends Capabilities, CanSetCapability { String SIMULATOR_PASTEBOARD_AUTOMATIC_SYNC = "simulatorPasteboardAutomaticSync"; @@ -37,7 +39,7 @@ public interface SupportsSimulatorPasteboardAutomaticSyncOption getSimulatorPasteboardAutomaticSync() { return Optional.ofNullable(getCapability(SIMULATOR_PASTEBOARD_AUTOMATIC_SYNC)) - .map(v -> PasteboardSyncState.valueOf(String.valueOf(v).toUpperCase())); + .map(v -> PasteboardSyncState.valueOf(String.valueOf(v).toUpperCase(ROOT))); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java index e08f413dd..09984729c 100644 --- a/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java +++ b/src/main/java/io/appium/java_client/pagefactory/OverrideWidgetReader.java @@ -28,6 +28,7 @@ import static io.appium.java_client.remote.MobilePlatform.ANDROID; import static io.appium.java_client.remote.MobilePlatform.IOS; import static io.appium.java_client.remote.MobilePlatform.WINDOWS; +import static java.util.Locale.ROOT; class OverrideWidgetReader { private static final Class EMPTY = Widget.class; @@ -74,7 +75,7 @@ static Class getDefaultOrHTMLWidgetClass( static Class getMobileNativeWidgetClass(Class declaredClass, AnnotatedElement annotatedElement, String platform) { - String transformedPlatform = String.valueOf(platform).toUpperCase().trim(); + String transformedPlatform = String.valueOf(platform).toUpperCase(ROOT).trim(); if (ANDROID.equalsIgnoreCase(transformedPlatform)) { return getConvenientClass(declaredClass, annotatedElement, ANDROID_UI_AUTOMATOR); diff --git a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java index 8afc2d9cf..eeb706b09 100644 --- a/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java +++ b/src/main/java/io/appium/java_client/pagefactory/utils/WebDriverUnpackUtility.java @@ -30,6 +30,7 @@ import static io.appium.java_client.HasBrowserCheck.NATIVE_CONTEXT; import static io.appium.java_client.pagefactory.bys.ContentType.HTML_OR_DEFAULT; import static io.appium.java_client.pagefactory.bys.ContentType.NATIVE_MOBILE_SPECIFIC; +import static java.util.Locale.ROOT; public final class WebDriverUnpackUtility { private WebDriverUnpackUtility() { @@ -108,7 +109,7 @@ public static ContentType getCurrentContentType(SearchContext context) { var contextAware = unpackObjectFromSearchContext(context, SupportsContextSwitching.class); if (contextAware.map(SupportsContextSwitching::getContext) - .filter(c -> c.toUpperCase().contains(NATIVE_CONTEXT)).isPresent()) { + .filter(c -> c.toUpperCase(ROOT).contains(NATIVE_CONTEXT)).isPresent()) { return NATIVE_MOBILE_SPECIFIC; } diff --git a/src/main/java/io/appium/java_client/remote/SupportsRotation.java b/src/main/java/io/appium/java_client/remote/SupportsRotation.java index 74397a3e0..eb8a52b44 100644 --- a/src/main/java/io/appium/java_client/remote/SupportsRotation.java +++ b/src/main/java/io/appium/java_client/remote/SupportsRotation.java @@ -25,6 +25,8 @@ import java.util.Map; +import static java.util.Locale.ROOT; + public interface SupportsRotation extends WebDriver, ExecutesMethod { /** * Get device rotation. @@ -43,7 +45,7 @@ default void rotate(DeviceRotation rotation) { default void rotate(ScreenOrientation orientation) { execute(MobileCommand.SET_SCREEN_ORIENTATION, - Map.of("orientation", orientation.value().toUpperCase())); + Map.of("orientation", orientation.value().toUpperCase(ROOT))); } /** @@ -54,6 +56,6 @@ default void rotate(ScreenOrientation orientation) { default ScreenOrientation getOrientation() { Response response = execute(MobileCommand.GET_SCREEN_ORIENTATION); String orientation = String.valueOf(response.getValue()); - return ScreenOrientation.valueOf(orientation.toUpperCase()); + return ScreenOrientation.valueOf(orientation.toUpperCase(ROOT)); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java index be2dd1a5d..2f5ef1645 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsOrientationOption.java @@ -21,6 +21,8 @@ import java.util.Optional; +import static java.util.Locale.ROOT; + public interface SupportsOrientationOption> extends Capabilities, CanSetCapability { String ORIENTATION_OPTION = "orientation"; @@ -44,7 +46,7 @@ default Optional getOrientation() { return Optional.ofNullable(getCapability(ORIENTATION_OPTION)) .map(v -> v instanceof ScreenOrientation ? (ScreenOrientation) v - : ScreenOrientation.valueOf((String.valueOf(v)).toUpperCase()) + : ScreenOrientation.valueOf((String.valueOf(v)).toUpperCase(ROOT)) ); } } diff --git a/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java b/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java index 752966ef6..63511c9b0 100644 --- a/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java +++ b/src/main/java/io/appium/java_client/remote/options/SupportsPageLoadStrategyOption.java @@ -21,6 +21,8 @@ import java.util.Optional; +import static java.util.Locale.ROOT; + public interface SupportsPageLoadStrategyOption> extends Capabilities, CanSetCapability { String PAGE_LOAD_STRATEGY_OPTION = "pageLoadStrategy"; @@ -43,7 +45,7 @@ default T setPageLoadStrategy(PageLoadStrategy strategy) { default Optional getPageLoadStrategy() { return Optional.ofNullable(getCapability(PAGE_LOAD_STRATEGY_OPTION)) .map(String::valueOf) - .map(String::toUpperCase) + .map(strategy -> strategy.toUpperCase(ROOT)) .map(PageLoadStrategy::valueOf); } } diff --git a/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java b/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java index 3aa5f4add..52c2ea9d5 100644 --- a/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java +++ b/src/main/java/io/appium/java_client/remote/options/UnhandledPromptBehavior.java @@ -19,6 +19,8 @@ import java.util.Arrays; import java.util.stream.Collectors; +import static java.util.Locale.ROOT; + public enum UnhandledPromptBehavior { DISMISS, ACCEPT, DISMISS_AND_NOTIFY, ACCEPT_AND_NOTIFY, @@ -26,7 +28,7 @@ public enum UnhandledPromptBehavior { @Override public String toString() { - return name().toLowerCase().replace("_", " "); + return name().toLowerCase(ROOT).replace("_", " "); } /** diff --git a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java index 1ded306b8..70c9f024a 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumDriverLocalService.java @@ -44,6 +44,7 @@ import static com.google.common.base.Strings.isNullOrEmpty; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP6_ADDRESS; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; import static org.slf4j.event.Level.DEBUG; @@ -407,7 +408,7 @@ private static Slf4jLogMessageContext parseSlf4jContextFromLogMessage(String log String loggerName = APPIUM_SERVICE_SLF4J_LOGGER_PREFIX; Level level = INFO; if (m.find()) { - loggerName += "." + m.group(2).toLowerCase().replaceAll("\\s+", ""); + loggerName += "." + m.group(2).toLowerCase(ROOT).replaceAll("\\s+", ""); if (m.group(1) != null) { level = DEBUG; } diff --git a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java index 3a3529926..b22c93937 100644 --- a/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java +++ b/src/main/java/io/appium/java_client/service/local/AppiumServiceBuilder.java @@ -49,6 +49,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Strings.isNullOrEmpty; +import static java.util.Locale.ROOT; import static java.util.Objects.requireNonNull; import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME; @@ -143,7 +144,7 @@ private static File findNpm() { private static File findMainScript() { File npm = findNpm(); - List cmdLine = System.getProperty("os.name").toLowerCase().contains("win") + List cmdLine = System.getProperty("os.name").toLowerCase(ROOT).contains("win") // npm is a batch script, so on windows we need to use cmd.exe in order to execute it ? Arrays.asList("cmd.exe", "/c", String.format("\"%s\" root -g", npm.getAbsolutePath())) : Arrays.asList(npm.getAbsolutePath(), "root", "-g"); From f86605d1cef5384112476a1ef697afce0fb721b7 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Fri, 3 Oct 2025 15:52:44 +0300 Subject: [PATCH 475/501] build(deps): Bump Selenium from 4.35.0 to 4.36.0 (#2351) --- README.md | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 04af41b52..88c751240 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ----------------------------------------------------------------------------------------------------|----------------------------- -`10.0.0` | `4.35.0` +`10.0.0` | `4.35.0`, `4.36.0` `9.5.0` | `4.34.0` `9.4.0` | `4.26.0`, `4.27.0`, `4.28.0`, `4.28.1`, `4.29.0`, `4.30.0`, `4.31.0`, `4.32.0`, `4.33.0` `9.2.1`(known issues: appium/java-client#2145, appium/java-client#2146), `9.2.2`, `9.2.3`, `9.3.0` | `4.19.0`, `4.19.1`, `4.20.0`, `4.21.0`, `4.22.0`, `4.23.0`, `4.23.1`, `4.24.0`, `4.25.0`, `4.26.0`, `4.27.0` diff --git a/gradle.properties b/gradle.properties index 6053da655..19ebf202f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ org.gradle.daemon=true -selenium.version=4.35.0 +selenium.version=4.36.0 # Please increment the value in a release appiumClient.version=10.0.0 From 1b0c6dec8f7b77e4aeba8434ce950b0752cecb95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 15:18:14 +0300 Subject: [PATCH 476/501] build(deps): Bump gradle/actions from 4 to 5 (#2354) Bumps [gradle/actions](https://github.com/gradle/actions) from 4 to 5. - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/v4...v5) --- updated-dependencies: - dependency-name: gradle/actions dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5919afe9c..e0f64de56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,7 @@ jobs: java-version: ${{ matrix.java }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build with Gradle # FIXME: Sonatype returns 401 for the snapshots repository diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 48283ff61..efec053e3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,7 +14,7 @@ jobs: distribution: 'zulu' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Publish package env: From 958f4b18fdc3fbc7f73dcb79d9c12af43ca67ed7 Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Thu, 9 Oct 2025 00:09:45 +0300 Subject: [PATCH 477/501] refactor: Avoid using reflection to manage `AppiumCommandExecutor` state (#2356) --- README.md | 1 + .../internal/ReflectionHelpers.java | 19 ------------------- .../remote/AppiumCommandExecutor.java | 12 ++---------- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 88c751240..7f3f54480 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ dependencies { ### Compatibility Matrix Appium Java Client | Selenium client ----------------------------------------------------------------------------------------------------|----------------------------- +`next` (not released yet) | `4.36.0` `10.0.0` | `4.35.0`, `4.36.0` `9.5.0` | `4.34.0` `9.4.0` | `4.26.0`, `4.27.0`, `4.28.0`, `4.28.1`, `4.29.0`, `4.30.0`, `4.31.0`, `4.32.0`, `4.33.0` diff --git a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java index 10375e2ad..dd131fc65 100644 --- a/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java +++ b/src/main/java/io/appium/java_client/internal/ReflectionHelpers.java @@ -44,23 +44,4 @@ public static T setPrivateFieldValue(Class cls, T target, String fieldNam } return target; } - - /** - * Fetches the value of a private instance field. - * - * @param cls The target class or a superclass. - * @param target Target instance. - * @param fieldName Target field name. - * @param fieldType Field type. - * @return The retrieved field value. - */ - public static T getPrivateFieldValue(Class cls, Object target, String fieldName, Class fieldType) { - try { - final Field f = cls.getDeclaredField(fieldName); - f.setAccessible(true); - return fieldType.cast(f.get(target)); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new WebDriverException(e); - } - } } diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index fbbd10445..ad6bb36c3 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -119,13 +119,6 @@ public AppiumCommandExecutor(Map additionalCommands, this(additionalCommands, service, HttpClient.Factory.createDefault(), appiumClientConfig); } - @Deprecated - @SuppressWarnings("SameParameterValue") - protected B getPrivateFieldValue( - Class cls, String fieldName, Class fieldType) { - return ReflectionHelpers.getPrivateFieldValue(cls, this, fieldName, fieldType); - } - @Deprecated @SuppressWarnings("SameParameterValue") protected void setPrivateFieldValue( @@ -134,12 +127,11 @@ protected void setPrivateFieldValue( } public Map getAdditionalCommands() { - //noinspection unchecked - return getPrivateFieldValue(HttpCommandExecutor.class, "additionalCommands", Map.class); + return additionalCommands; } public Factory getHttpClientFactory() { - return getPrivateFieldValue(HttpCommandExecutor.class, "httpClientFactory", Factory.class); + return httpClientFactory; } @Nullable From 407247b9b8df49bb7bb7826d0b912ba61f18d071 Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Fri, 10 Oct 2025 05:13:12 +0530 Subject: [PATCH 478/501] feat: add support for descendant and ancestor flutter locators (#2357) --- .../java_client/android/CommandTest.java | 33 +++++++ .../java_client/android/FinderTests.java | 30 ++++++ .../java/io/appium/java_client/AppiumBy.java | 99 +++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java index 0f056e51a..772b316fb 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java @@ -160,4 +160,37 @@ void testCameraMocking() throws IOException { driver.findElement(AppiumBy.flutterText("PICK")).click(); assertTrue(driver.findElement(AppiumBy.flutterText("Success!")).isDisplayed()); } + + @Test + void testScrollTillVisibleForAncestor() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Nested Scroll"); + + AppiumBy.FlutterBy ancestorBy = AppiumBy.flutterAncestor( + AppiumBy.flutterText("Child 2"), + AppiumBy.flutterKey("parent_card_4") + ); + + assertEquals(0, driver.findElements(ancestorBy).size()); + driver.scrollTillVisible(new ScrollParameter(ancestorBy)); + assertEquals(1, driver.findElements(ancestorBy).size()); + } + + @Test + void testScrollTillVisibleForDescendant() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Nested Scroll"); + + AppiumBy.FlutterBy descendantBy = AppiumBy.flutterDescendant( + AppiumBy.flutterKey("parent_card_4"), + AppiumBy.flutterText("Child 2") + ); + + assertEquals(0, driver.findElements(descendantBy).size()); + driver.scrollTillVisible(new ScrollParameter(descendantBy)); + // Make sure the card is visible after scrolling + assertEquals(1, driver.findElements(descendantBy).size()); + } } diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java b/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java index e8f78e414..f00301885 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/FinderTests.java @@ -5,6 +5,7 @@ import org.openqa.selenium.WebElement; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class FinderTests extends BaseFlutterTest { @@ -51,4 +52,33 @@ void testFlutterSemanticsLabel() { assertEquals(messageField.getText(), "Hello world"); } + + @Test + void testFlutterDescendant() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Nested Scroll"); + + AppiumBy descendantBy = AppiumBy.flutterDescendant( + AppiumBy.flutterKey("parent_card_1"), + AppiumBy.flutterText("Child 2") + ); + WebElement childElement = driver.findElement(descendantBy); + assertEquals("Child 2", + childElement.getText()); + } + + @Test + void testFlutterAncestor() { + WebElement loginButton = driver.findElement(BaseFlutterTest.LOGIN_BUTTON); + loginButton.click(); + openScreen("Nested Scroll"); + + AppiumBy ancestorBy = AppiumBy.flutterAncestor( + AppiumBy.flutterText("Child 2"), + AppiumBy.flutterKey("parent_card_1") + ); + WebElement parentElement = driver.findElement(ancestorBy); + assertTrue(parentElement.isDisplayed()); + } } diff --git a/src/main/java/io/appium/java_client/AppiumBy.java b/src/main/java/io/appium/java_client/AppiumBy.java index 4314dc891..1c24b29c1 100644 --- a/src/main/java/io/appium/java_client/AppiumBy.java +++ b/src/main/java/io/appium/java_client/AppiumBy.java @@ -23,9 +23,12 @@ import org.openqa.selenium.By.Remotable; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; +import org.openqa.selenium.json.Json; import java.io.Serializable; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static com.google.common.base.Strings.isNullOrEmpty; @@ -250,6 +253,57 @@ public static FlutterBy flutterSemanticsLabel(final String semanticsLabel) { return new ByFlutterSemanticsLabel(semanticsLabel); } + /** + * This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0. + * + * @param of represents the parent widget locator + * @param matching represents the descendant widget locator to match + * @param matchRoot determines whether to include the root widget in the search + * @param skipOffstage determines whether to skip offstage widgets + * @return an instance of {@link AppiumBy.ByFlutterDescendant} + */ + public static FlutterBy flutterDescendant( + final FlutterBy of, + final FlutterBy matching, + boolean matchRoot, + boolean skipOffstage) { + return new ByFlutterDescendant(of, matching, matchRoot, skipOffstage); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0. + * + * @param of represents the parent widget locator + * @param matching represents the descendant widget locator to match + * @return an instance of {@link AppiumBy.ByFlutterDescendant} + */ + public static FlutterBy flutterDescendant(final FlutterBy of, final FlutterBy matching) { + return flutterDescendant(of, matching, false, true); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0. + * + * @param of represents the child widget locator + * @param matching represents the ancestor widget locator to match + * @param matchRoot determines whether to include the root widget in the search + * @return an instance of {@link AppiumBy.ByFlutterAncestor} + */ + public static FlutterBy flutterAncestor(final FlutterBy of, final FlutterBy matching, boolean matchRoot) { + return new ByFlutterAncestor(of, matching, matchRoot); + } + + /** + * This locator strategy is available in FlutterIntegration Driver mode since version 1.4.0. + * + * @param of represents the child widget locator + * @param matching represents the ancestor widget locator to match + * @return an instance of {@link AppiumBy.ByFlutterAncestor} + */ + public static FlutterBy flutterAncestor(final FlutterBy of, final FlutterBy matching) { + return flutterAncestor(of, matching, false); + } + public static class ByAccessibilityId extends AppiumBy implements Serializable { public ByAccessibilityId(String accessibilityId) { super("accessibility id", accessibilityId, "accessibilityId"); @@ -328,6 +382,32 @@ protected FlutterBy(String selector, String locatorString, String locatorName) { } } + public abstract static class FlutterByHierarchy extends FlutterBy { + private static final Json JSON = new Json(); + + protected FlutterByHierarchy( + String selector, + FlutterBy of, + FlutterBy matching, + Map properties, + String locatorName) { + super(selector, formatLocator(of, matching, properties), locatorName); + } + + static Map parseFlutterLocator(FlutterBy by) { + Parameters params = by.getRemoteParameters(); + return Map.of("using", params.using(), "value", params.value()); + } + + static String formatLocator(FlutterBy of, FlutterBy matching, Map properties) { + Map locator = new HashMap<>(); + locator.put("of", parseFlutterLocator(of)); + locator.put("matching", parseFlutterLocator(matching)); + locator.put("parameters", properties); + return JSON.toJson(locator); + } + } + public static class ByFlutterType extends FlutterBy implements Serializable { protected ByFlutterType(String locatorString) { super("-flutter type", locatorString, "flutterType"); @@ -358,4 +438,23 @@ protected ByFlutterTextContaining(String locatorString) { } } + public static class ByFlutterDescendant extends FlutterByHierarchy implements Serializable { + protected ByFlutterDescendant(FlutterBy of, FlutterBy matching, boolean matchRoot, boolean skipOffstage) { + super( + "-flutter descendant", + of, + matching, + Map.of("matchRoot", matchRoot, "skipOffstage", skipOffstage), "flutterDescendant"); + } + } + + public static class ByFlutterAncestor extends FlutterByHierarchy implements Serializable { + protected ByFlutterAncestor(FlutterBy of, FlutterBy matching, boolean matchRoot) { + super( + "-flutter ancestor", + of, + matching, + Map.of("matchRoot", matchRoot), "flutterAncestor"); + } + } } From 0a2589fdb2547a15fe9e3163736cc15397bea8a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:22:25 +0300 Subject: [PATCH 479/501] build(deps): Bump org.owasp.dependencycheck from 12.1.6 to 12.1.7 (#2359) Bumps org.owasp.dependencycheck from 12.1.6 to 12.1.7. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-version: 12.1.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6c2aec2d3..d9227b0ca 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'signing' - id 'org.owasp.dependencycheck' version '12.1.6' + id 'org.owasp.dependencycheck' version '12.1.7' id 'com.gradleup.shadow' version '9.2.2' id 'org.jreleaser' version '1.20.0' } From b6123dbe825bbf29038c67db6575c05d5d4bad4d Mon Sep 17 00:00:00 2001 From: itkhanz <62521743+itkhanz@users.noreply.github.com> Date: Sat, 18 Oct 2025 00:57:18 +0200 Subject: [PATCH 480/501] chore: Add Java 25 support with Gradle v9.1.0 (#2358) --- .github/workflows/ci.yml | 2 ++ build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 45457 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 11 +++++------ gradlew.bat | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0f64de56..0d37efe0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,6 +53,8 @@ jobs: e2e-tests: flutter-android - java: 21 platform: ubuntu-latest + - java: 25 + platform: ubuntu-latest fail-fast: false runs-on: ${{ matrix.platform }} diff --git a/build.gradle b/build.gradle index d9227b0ca..a057f64c8 100644 --- a/build.gradle +++ b/build.gradle @@ -188,7 +188,7 @@ jreleaser { } wrapper { - gradleVersion = '9.0.0' + gradleVersion = '9.1.0' distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..8bdaf60c75ab801e22807dde59e12a8735a34077 100644 GIT binary patch delta 37340 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 UX##k1IU5Uz9RMyC?XF1w2hzEis{jB1 delta 35347 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 48b43d350..a35649f5f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6d6..ef07e0162 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -206,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -214,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c7..5eed7ee84 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From 329daab73bfcece416f789e25c6d02eedb23416a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 19 Oct 2025 20:22:16 +0200 Subject: [PATCH 481/501] test: Fetch VodQA test app dynamically (#2360) --- .../java_client/android/TestResources.java | 2 +- .../service/local/ServerBuilderTest.java | 4 ++-- .../java_client/android/CommandTest.java | 2 +- .../io/appium/java_client/ios/AppIOSTest.java | 2 +- .../java_client/ios/BaseIOSWebViewTest.java | 11 ++++++----- .../java_client/ios/IOSContextTest.java | 2 +- .../appium/java_client/ios/IOSDriverTest.java | 2 +- .../java_client/ios/IOSWebViewTest.java | 2 +- .../local/StartingAppLocallyIosTest.java | 2 +- src/e2eIosTest/resources/vodqa.zip | Bin 3054220 -> 0 bytes .../DesktopBrowserCompatibilityTest.java | 2 +- .../java_client/plugin/StorageTest.java | 2 +- .../java_client/{ => utils}/TestUtils.java | 5 ++++- 13 files changed, 21 insertions(+), 17 deletions(-) delete mode 100644 src/e2eIosTest/resources/vodqa.zip rename src/test/java/io/appium/java_client/{ => utils}/TestUtils.java (93%) diff --git a/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java b/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java index 149a72a4a..373241fe4 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/android/TestResources.java @@ -1,6 +1,6 @@ package io.appium.java_client.android; -import io.appium.java_client.TestUtils; +import io.appium.java_client.utils.TestUtils; import java.nio.file.Path; diff --git a/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java index bf1df1fe3..a73a00dad 100644 --- a/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java +++ b/src/e2eAndroidTest/java/io/appium/java_client/service/local/ServerBuilderTest.java @@ -1,8 +1,8 @@ package io.appium.java_client.service.local; -import io.appium.java_client.TestUtils; import io.appium.java_client.android.TestResources; import io.appium.java_client.android.options.UiAutomator2Options; +import io.appium.java_client.utils.TestUtils; import io.github.bonigarcia.wdm.WebDriverManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -17,7 +17,6 @@ import java.util.List; import java.util.Map; -import static io.appium.java_client.TestUtils.getLocalIp4Address; import static io.appium.java_client.service.local.AppiumDriverLocalService.buildDefaultService; import static io.appium.java_client.service.local.AppiumServiceBuilder.APPIUM_PATH; import static io.appium.java_client.service.local.AppiumServiceBuilder.BROADCAST_IP4_ADDRESS; @@ -25,6 +24,7 @@ import static io.appium.java_client.service.local.flags.GeneralServerFlag.BASEPATH; import static io.appium.java_client.service.local.flags.GeneralServerFlag.CALLBACK_ADDRESS; import static io.appium.java_client.service.local.flags.GeneralServerFlag.SESSION_OVERRIDE; +import static io.appium.java_client.utils.TestUtils.getLocalIp4Address; import static io.github.bonigarcia.wdm.WebDriverManager.chromedriver; import static java.lang.System.getProperty; import static java.lang.System.setProperty; diff --git a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java index 772b316fb..9e7f60bda 100644 --- a/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java +++ b/src/e2eFlutterTest/java/io/appium/java_client/android/CommandTest.java @@ -1,12 +1,12 @@ package io.appium.java_client.android; import io.appium.java_client.AppiumBy; -import io.appium.java_client.TestUtils; import io.appium.java_client.flutter.commands.DoubleClickParameter; import io.appium.java_client.flutter.commands.DragAndDropParameter; import io.appium.java_client.flutter.commands.LongPressParameter; import io.appium.java_client.flutter.commands.ScrollParameter; import io.appium.java_client.flutter.commands.WaitParameter; +import io.appium.java_client.utils.TestUtils; import org.junit.jupiter.api.Test; import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java index 8de7d60e7..316b05d08 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/AppIOSTest.java @@ -1,7 +1,7 @@ package io.appium.java_client.ios; -import io.appium.java_client.TestUtils; import io.appium.java_client.ios.options.XCUITestOptions; +import io.appium.java_client.utils.TestUtils; import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.SessionNotCreatedException; diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java index 2371a7b72..8c54b30c4 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/BaseIOSWebViewTest.java @@ -16,22 +16,23 @@ package io.appium.java_client.ios; -import io.appium.java_client.TestUtils; import io.appium.java_client.ios.options.XCUITestOptions; import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.SessionNotCreatedException; +import java.io.IOException; +import java.net.URL; import java.time.Duration; import java.util.function.Supplier; -public class BaseIOSWebViewTest extends BaseIOSTest { - private static final String VODQA_ZIP = TestUtils.resourcePathToAbsolutePath("vodqa.zip").toString(); +import static io.appium.java_client.utils.TestUtils.IOS_SIM_VODQA_RELEASE_URL; +public class BaseIOSWebViewTest extends BaseIOSTest { private static final Duration WEB_VIEW_DETECT_INTERVAL = Duration.ofSeconds(2); private static final Duration WEB_VIEW_DETECT_DURATION = Duration.ofSeconds(30); @BeforeAll - public static void beforeClass() { + public static void beforeClass() throws IOException { startAppiumServer(); XCUITestOptions options = new XCUITestOptions() @@ -39,7 +40,7 @@ public static void beforeClass() { .setDeviceName(DEVICE_NAME) .setWdaLaunchTimeout(WDA_LAUNCH_TIMEOUT) .setCommandTimeouts(Duration.ofSeconds(240)) - .setApp(VODQA_ZIP); + .setApp(new URL(IOS_SIM_VODQA_RELEASE_URL)); if (PREBUILT_WDA_PATH != null) { options.usePreinstalledWda().setPrebuiltWdaPath(PREBUILT_WDA_PATH); } diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java index 999957aaa..b746edd24 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSContextTest.java @@ -17,7 +17,7 @@ package io.appium.java_client.ios; import io.appium.java_client.NoSuchContextException; -import io.appium.java_client.TestUtils; +import io.appium.java_client.utils.TestUtils; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java index 3ad036b4d..aa0a66f2a 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSDriverTest.java @@ -31,7 +31,7 @@ import java.time.Duration; import java.util.Map; -import static io.appium.java_client.TestUtils.waitUntilTrue; +import static io.appium.java_client.utils.TestUtils.waitUntilTrue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java b/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java index da68eeecb..1895e3517 100644 --- a/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/ios/IOSWebViewTest.java @@ -1,7 +1,7 @@ package io.appium.java_client.ios; import io.appium.java_client.AppiumBy; -import io.appium.java_client.TestUtils; +import io.appium.java_client.utils.TestUtils; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; diff --git a/src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java b/src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java index b262e93af..d91407509 100644 --- a/src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java +++ b/src/e2eIosTest/java/io/appium/java_client/service/local/StartingAppLocallyIosTest.java @@ -16,13 +16,13 @@ package io.appium.java_client.service.local; -import io.appium.java_client.TestUtils; import io.appium.java_client.ios.BaseIOSTest; import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.options.XCUITestOptions; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.flags.GeneralServerFlag; +import io.appium.java_client.utils.TestUtils; import org.junit.jupiter.api.Test; import org.openqa.selenium.Capabilities; import org.openqa.selenium.Platform; diff --git a/src/e2eIosTest/resources/vodqa.zip b/src/e2eIosTest/resources/vodqa.zip deleted file mode 100644 index 74b980dec5696d847b2ba1ee162b6496a5856ded..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3054220 zcmd431#l(Hk|ii+W|g?aEL|}(Gcz+YGqY4;W@ct8F>{HTnVI*!?&;atKfh%fK+6j+1ZsBn={iM7UC>RXT-&;y1sr0{G{Fehd5E788ow0&|qKSc#v#f!$g{ujj zfxSJwiaH!nL$I7?;$QX%j0PnC??RCLdk}g;cE%=37G|~v&MuB7{}d4o2ADv?S z4e$X;R)3vKck-FOl%9FT<|u z@dEmA;;c|y#&`Re$MZ$a^<&m-t6@HZg%fieV)M@u+P*zc89F|;BxA{Z$o zPfVCrIfy2gU5BgfvbVs&YjQGcRbp>;U4dGld5JzzaM~4?S3cvZuYgnwawY%Rh z=L6=FEjk(6idu%+j`9zC${|3~+){aU<$prO^Qt)$2quX=T{!S_gCNz>@@rpt^|a}> zf3Yii&BI^Y{i<;eF21)|kMq26hujn-o8FFJ7pa(ba9Ap&1BqKU?=YDdS{rg!zwXqr zLQJ?&*Q(ROQl_bOZ|7%LI>63Vf;l$oP(^x=!ZAREg8~r;IooX<9)>wc9bF5_K0qT% zFjJgR;-s)P-w!c64FQk5VZg>P0QJ4ELmt*u;sxX65b|HK5|4PAgzUjnb28ws8!@np zKo-8u!&hHd-GC+D<>8rK(P91+idJs zxM5}f*1sD%|J0r`*A@9PRJOKarbAV1Clo0!o~UTEJMV%}V+}ZMx{eXc4Ze zHrypdxmHG(9MrgkTS)aT*MBw;{!ZkCG}+tA9(Y)1m1(s|Y7z?@u1tiamM zAXN~9o~)JEM*`-Wc|cONoTW&tOw&pgF9=O(xNX4>w_1eq6dBK*tRS}M?OE6quq@B7 zWkYrR)2OdyvRuGf7Dx-a1XxZZ(%5oJ-$fz#)b+R3ae}ff-Wc=gCd|(coGNmWd^By5`s>Bc|1Gvw0+cTcvL#*NClcw;W7-5sH*lUiF{2b*XXLRE_s z3tRdKAMv=0Dl{1-%5*OEBxN;^Pr8=}3xEH-<+R)KB@sb;A}hUeX&Q2(%r15m1YJj8 zT$O{WMrEVQc~7$Yo#4ijys-4{OuR?#TE$rhQrc)KG!vp4XJb6eNj7_OaVU=-s=H5p zRXyf+&WS>|-%4c>mk1Sym@V$ zbJt<~FUK3zM9GDCt{K<_$xf>Z^ybM}7$XCf(^RL-Oe$!dt&55j`6lKl11%12=itGj zyZ!EQL{z;>ynkRmQ^?$bU<943J`NOpFJTN=N5n>^kcYXNda^ipIt}JucuWuXceSx!t#ZC`wx2t7d&(!|WYad+o{lpL5 zg8Ko%Y^dkc)zbP-N@uP29YLZ?cV{*Gr}e4g}PT z0rcObhJ=5}F1Y{RL~h{ZWa8}fUsFQVf0tzb5sCPJg7iNC{MQ`wkAO7)F+f*4V+R8| zdt0-AOE3TC>ZPZfvXaJ!8JY+<&d&n0bYNg;ke@Ogqz?)CU?fQPCnRVgv+Lo+^B|z& z@FJE!Oela8km_bDq4L2%By00SbyHqHpDtGUTwQ0b{JdQGuCt!EJhr{AkGtKjTYKC9 z-glt(I(k}iIQB=A*#1|i5bUqe`tOIvXg9dOU7rX(8qK(dIG&uocYbocdpt>DavZ(H9G*3wFSpk?Y4`N`>~lV!zCQXvaNNtuwK!qQap@j+4SIa~ z;gIJ7X=Bc$<@ofuielNPoWtQPrzevA*7=S7JKf2;^!a1kKH{@qB$nxTx-pw4d0iVa z3y{m>^#$_YexABYmpwj{Wy0l_^9iy%gtO5*p7G&(T5_|nY=>gU<7xUMe#A-Zfa{uv z!$SmC%8tNzKI~6q#f%#oJ|A17+l^PI;_D)J?=`RZb4a0+qrms+2}o&|+4T4G0nn45 zXs`XzUb%Amxw7Z@l<)1v>EidVFG#lKTDeubEI@D1Z`uzs#@fAm;&wADHW6v!H{Uyw zRkfPjS>V*w=`3Di987-HUw241-?!fwEAl=SM#j*Ky5Jg+QYsh_3!?vFU}QAfrr9(aaXGqZCGGS2 z)aoeg|5J=TupFG5jj94j4lUf!!$e3OTrX}}Z^5=~^c~ExDdxaNDOGquYwbz;`he-L z&8bLWXW&QYx5m`W0+Rj;u2UC!YZhXa+5^)r@DumbD)u}+$Ra;dA}|uqXbH21(S9D& zT->a5aZnR^g0`*kKXt>c(kfO~M)qADZsY=Gm0zn7yoi@ljcbVJe|KZU(7Pn8kj-A6 zIA2~Nm|9($-%Y{urZTPtgr9v$@*p^w-vHq-C>fvLcJvaXp!R!3^*^-7>ft-N-osB{ z(4ZJ2pq#*>m~&h~ezPJ%?XZ1@m3>M*t=C)LCrSv7d_Gf-D@YM`y(?BX!E!5X* z)^>9Z+nAN-M-us3MYf`G?yMe~Haiq}>xT3pt;t}%?b-T8y>)0}wStX!Ts*t)s^#~d z)>J+J$vefu!fxfq{&BWY1y)VFmaRjgiQt(6xKsPHy9X@p)?7bp2HHYv@_X<1(juQ* zOfLa2`#$g2OzQCJ0X{h7z*!INGjKDizr56092mum)TNEKd>XQaoXEsVP_V6j9^YM8 zQbT5-_o4y5K3NawrDuqIidrzmdi!oin>~vxP1qrLMtnd2L>`&CEsge{ptnHTD*VQg znR{Govhe{k*3`RckfkvngsqnR~*WB=~}c@N3E{;o0-W(V)AmL;U#pL>1f z`pu-}A0r72qKB$F+d7cBKuq4DK-!xxO-kq?vI+LvGvgN#i8F=yclW1vX|}bfLQ`(s zd3Vv;oq}w@20u?aT0WGRU%E#EgH?z%sfN>r>#LnBd|1^D%Qj+m;90Y4!>KH#FVtW# zMQyg51SYq0=<1oy-p|iDqwvxxVp=8c;8=v_+rxzX_5B%|9+5|IJ)iz3-F7tDv+zj4 z{fYX)yRnVYj@#FMqKcA%8@Qi|gP>p_#axD%TZDYX%&(3w%%5t^v8Xa}pa{FbHDaiX zknfrhUVQq9)g1j-kX=7XjtxThrmJGrIa_uES(J#%&pJLQR$<+e8%jd8m8I;2>9Vw} z(^Px|KQ{o^KAf$K-cpC_47VUwrH!1mYXPd8$3w|?D>T%PmMJl2t(3Vcp0VetMKxp` zWfOWRf7a5XiunKZ-$@o3V*-iYWY3jBL7RJ{k+mvjA_G-7&)xzFqIpF1XJ3Uf zt?swPG#z6_qn1~=$rDZn3usJ0V#2}T^(xWGP;foi=h+lds#SFIbrkh`;gi8UH$7C6 zs29h}_R8UGphm(Ac`~4}ZCmla1e^74WJ8@|uLI zvJg-G`T}B~=nbt=NKUvebAhV8j|e*OWuUk!Ns%Yibud8T;TxK6IpxB243^ zV!&Q;?phz`q6g9zEiDKke<$95K)l$)J!QHUEryhUBc{e<>OCo%Nig7bv#9HNDmH_x zNg_{fzim!+M9kD(voXZch(q*od+ZzOuQh&xxOmzI%k{WgQf#$v?!t3ru~87Z4;r@r z*S?R@bsRA zXhsrvl%Uw%x%?kT3s|PZC8(lqRi(_3I;|(@rmd^t;!*3J`_dMeJu zYx-*Fr%TEWdaXH+9D1+t#gQ<|>*aL%R00_>Jn)DQ+IuzWRn|SbE$CNjlYftcD7v zyx+*qAmJF$Tzo(8dKRGcH0udz6~iBr=i?^yw8veYi$jT=$(!8yxQdZlfUgU$Lr5s? z%1j@A51XbCy2_iTC2ThH0l5yR{=$DKF2Sz}2WB#snUJ5#s>LujMKxcZL+(AIw`fKg zoDssg2r?9zn6O8dkdWAexcfZ&$=G^ot{C?WfT6pHC_NLk(35KV!#Z^#M4ZuED6KBx z_#wP$Gg&}{7pVXxdwKx(o-mLp7$GzWF9NCl?50XPxnBh)o-b-?PAQK~0ahOQ8tR`! zZb=d^c?qcZxIh150&d&mj3OXXtPZ{B^X5I0Ozr9{CI3~e_ZeBlJ|GR=7i;t>%K4g< zo;K9Ea_bcnHE$bWGl?_Ks$v92l)ProlsHXwHM2s&1oS@NmT)P$h54$o2<%*X0a$4TGr{}^b9`UpGTY*komOzy1~ zK$K-lBOByc6H%@5`c~c)rE%*?Js8YZr>Tu&W4t@k)E??6G>!X*m_nMxErD&??&!+U zr8-j44<|O+ovnjfEYREOQgjY;E9o}l1G}2-{LOhLt?MdW`?TNfXNQJzcY7~&66mLz z;$h5>giowX6i^tg6sqT9T8#4@cKx1rwwuGUO>AYZAy@GY8q}zvJ&3v?Qnjv#uNmoc zR3Y8i&9vzR$5n?@mV{^4+ynesV!zdCJO8cV3(%2G;ol|T4;PBFq)~uE4>)%mZx9MV z!xmC;E>M?1ULn6szXEWDe8U`!_oxquIzuD7G&|fguj_x7{q3J!RoUd0~VHSZA>z`!(KE*eK+F`cEk{HGedp8$iM z6ZYuGMM@?@FOYi=4#}qqk$LZ1a|8d>d>AR$CGAnvo(7V;cl+*E7|Y~jr5ufgQ0BqZA~GfG;fWv_TG5ARm-K229a2AEWb-l;k4=0bx) zBZP7BVC-HTfC-1j<;wwSoZ=2^r$K-Kt){|XxG?OAHdRcDM$Kgi6P9FThm()DVr!^gZpE zn?NKB;TVQEvd@=!CWuuSDv{ZNpR$0%=1$DT{fBQazQ;?9hl+EsA^um2cB>(m*Lp(9;hhx!*7|6hPeN+U738a>7tyNMo5Lk|r@_?_ zu$&(c9*Cc&!ZU$J=UFM)2*ZA&KPv@vf~nu+*YWqXi!c{Q*qjP$r^KAH>24!9&~hrS2~tZK6G!dVMW zx4)p^zbYq{vUrY>pVn7s7531SgFBpWSRvg0dE)1`YDM)dy1&teM*U{o+JDTL$pti4Jm6-5x90B?rDiPY8*WAp2fTP~T!;X)?%h zynyrqX03KKtSS)29EPmEQnT41F9F18=C^ol;sVudOKv`IBHt_RH(C2k*!!cTLolh% zDScw|e-Om%BT0OQ%NRU;VXb==+hHexu@LLpe`HAbUX*WL&lH&rodv7#J^P+B-_qWj z{$wlcY_XM>JvgDy9Cp7^5O}y1optseF`E05PQU_;1=HyYo#pL-p7*lBUr;0k>VYN= zr4k<@bPuS3(HV2dkz_+}e?5ra1NGR0*ni$>-!kliG2B1(1J50U$@|zY;h;L3>&xem z@@$W*h%I>9z5S{Ql(V9wE#W?NEn~8H7-Z%{Q3IIR$bXDW*(vJk20#}1C<%$Bd~NNN z*pOJ)0D3k*aXH%*Bw~SMw)2mZo`|P3#!d85gL4jtR}hQvy@m@4t3Z&6&Ty2Rch>V_ zRToG<^2V)&4OS^+lj>1)+s-6q(|Mi8Fb|@tEc4C9(cG!Yf4jk;*p&<#NOuQ{yNb5Q z-qmw5cHNHV!|50JEgWUzdC8T}jv8w!L zsUQ`HX@UdLB^_&FM>tfYuaI`r(^$-0$1b>OuoYP_w6ih+9dobo0t02)-2*nq+SNT^ z^{GtYJ>pON1iW+cum*c`=L52#BoluO)pji@)>>Ox66Fu<1)7v23CS}|vED6)fB&w^ z63=ux689E}5hD9xtunR-V@i3D^m_GT7A)FMdGxiSIovcZ`1*m~26jmHIM{DgR!HLX z;Zvn``n#1k@oS0ttl|TN3|&1bC}OXC4+i#|^XC)$r)mgJ1z~vqiU+Tr6FRusBxHi8 zeOdbrHJ9^Z#%5@x2o^~o0h@_}Ep*k+?vC8uh$m;jBobCor`rAgl6N`s&q?Y|C&VvX z9O7$RHsAO3cF7CKVbjrA`_##!AWh#jH*V}@0S?y1#&qCyFBOOnn4_(!oI3*kC&3Vz z8R^a^OgS^2%$|X|_BJ~sS2pCKJpBejWdrw@t1?9;rH}42_`-J~QZ9Xgd@o-JG1)UJ zd=@RKet2#!+D5=*`Lb~I91%7jq+1aL3(*PP^LKz)rQ2@6+%y) z`O4)>Qb9okB0{mtC)`3JuHNQa+4H+t$oj1|c=-gp5>RukP2irx&$p<-qFg(D*Hn19 z>^ZTIm#7RD9`s(FXTG6pG#Rsb)3^PAnugiftd}`$RL~K$t<~;ndx-%RdX<2Z{qs}^ zdhH^#na?}B)4W=!!Ym6~12*WFS_ z;GupTm9vk>h_+6;-TvcWhgc_Jqobj#3UhgPw&wB+u=o=*AnO$qr|bFm3HFqG+pN!K zzj!}8h+q5qW^K9v0Ty4v8&&&ETWx+Hq8e1WzOry4<} zUAas9V^N#GVARrf&>=hT^=iq)cX2;N8H?8%B+rNA^RfrwTh1OtkzJG09OD~Ao8jq@ zdIYvBUQ4z_SEb@lZxQ4j6qY_-&s|`B%Tpv5L_q!P`2^Z$yhpl zXNbAoT~MRjR@h?U(sWJzcDkWrn~os*Q0fa8lp1I6?9XXVw%ja)0K`>?*pxeGEc6Ul zo}l_$xCAdn?ls2@N+^{MtVf+8wkbbILiz@EV=?>)94IUaLYPOr&`lMyPW9<1>Lx0R z?_5&+dE90%{w+I&Ft)}G40ab80=Z@2Kyo7^Nzm1N62AV<6Yyq`G?<;33nRIkTXg5b zGMN?9`}(t+-;#^EN;N9?WS=?jn2N8A$8Oy`y;#X=HR%Y9xb@VwY0@U%xed~`bVFOB zDoUAc{uTZZUU~A_?ndp0&3d(o(fi)>Ey^ciois|!aXo)y0!CXdThd0G+kP~1B&c#Hc5 zbT$y@YVGCk~}bv)$Gj zw71LUCOl6uFeSc1eJ?}zs2_|lV-F7F?p$s>XZg(6%>n2ec`+?*VwZA^-73LT4-Q|A zzH!E0&6cqR?^R$m(K}jBAiH>)x?B?8bIoL}Vf`v7#uQ~fpAnm&Up9KTsK2HB&sPwE zcIFhpzIg^BPvO2ERv?>}$zb*u5!^iO&v%WUP)@_xtncR8aZVpj!L`%HMBf<=P>PzR zn8zg!6h&(Q%mOh4mG3m-;dcl-=C#WXhjvP%T74647paU|mZ}onW9-tb9 zNeU&w+nvfr8C1PfE3nMkGbV{LgQh~ASXxdlJ=cV#L$^O4zr2}FJh`&Lb|;;Ck_%Zq zoLTy!?@MIO+)k!x2sk}#KKvls+m!(IkAhUdG;KCDbQYvd8Zc#cnH|GmDRkJMU;ZH7 zl+<8@O8TLE9G~a`3rnJ5#SWIZtPs0)iK39sCz~A*j(B(yyrOSC#Qg9A&P|idRVm%( zLsX@w$oT}OPQ4|~_l)P$M8RWB6RH_2DDWdi86iqgfW}1uc5Cg*k zcyNhwoOv0~Aua91xs&kStk5AkuJje#En6_vR55@McF`;CIR(4PgQJD`TFbt{p|ity zRw)slff%Y=YQ&1;g)s^5@;3LO(1=?h-@=Q=momG}0qTfEKj0+EU>Vn2D!_kM#b$5z zhW8<^KS=pgH6k`-tK@No5NT{^7C}b#6?Jw*YZumIJDB278g1MEjt70Xv9@{n{0z2vbGShQHny;GT|!zX}Df z)3=>B*aCyI}bro(c=_4huBgW-rVwM_zT=AVE3T!JkseM6xP3>p4Fjr+X zi%9)y57I_|_(P^VS9;f=A9Qq{^5h0(gsn6E`M99h<(`Z4LBK3I**Q3h%dmm#%U@0D z{;y}=X#l}4XO((Bz54>po(@K^+MA|Ew9F|nuw1L@E?hiYS}0nUOAezw?=VhMf^QZ3 z4XjnoyD7<^!h5ANE2o)TDGXo48C@S?ji!q2Eu;sGEuI->gjz5Iq0nBInx?|!y7h~0 zbaJz1KjUgoK7nE=c$ICqsAfNkr!o2X`6JHV5pPEJ@VsYLB#>9@GEpW{w7S>FQ`uJ5 zIG3Sw=ot4KK6LU6j?Q})QmJjC@ zWBPR6_xM@fZA>|?Cd#_h{{r#Rfx+I8#^RicEEcnBG{PZGgbW*0?FxG1+~OHFqy!q$ z^W)4b^G^I~g>mHk1_bb0Mh<(l(g44LPuW$`aL;BlPA74SMzd;0HxD7OQ}NuHH}%Ik zxZy;wi>bFn-n=R7(~1Y*rdg}qqw@QLs!Eb|SLut+moHT(>v~~<8eQd9LoYlnPP;Et;_j*S;@#wcVsV1UVGdFAtK(kex*2T zvdxHUWgSBkMud2g_mo{=@hpj5wp^AdUEK$TYJ)^mdDxSb+W6?0OKT|FXVJtmLuvEg6}3UXEFib_vt;jI_^8qEN83N7v1EmFn?|FN6Ck4` z2<`xq15)iY!nG)YSthX{N~EzCb$UiRp7f=pCdIzSZ`?2S$H7xV$-MJAFr}xKO1IA|3AYxmC|;r=|*be$n5&?i^N&o*4U8KNjtE zgfwz4^T#V$xiL}^5(i`bbRBI6KwEdt5XO097`g+SZ@x+GHTzdjo%GH~( zQw7wOkTkCSEjD8;(}TKqjg%BEg(8(@WD##{?3r~qL|Staw5hQG2g3( z+mI>|;!7KpyR3%*G32b>9iV+KML5H8?6}jW9iDFg9)w@%#cQmI7;L~1aXaUcWiXZa zA}J}yXR3S^R-5#O`Px1yO$vVAQk|?%r<=9vHoG@}?+OPUIf{OJvmDks3b<4mOn;$> zR3n8I>R!<@$5J|6le`mjfRC*--11VOx@>Cchb5?F7%yW?OmGV2VaAhG<)5(3ZfF-_ zbec7R#5jA#o2{Nq6yW99N?I+H!wzFYzlI4G;~uOu%a{Q2t=XF*C`2ZYP2) z8c7L#pJ~QHjiJb(T!RGe9>-yFyABoSg)7Vdb#Dcb5@SSYfj>N6gat97rsqF^Q}ccF z#1*K1)#O)XSd?BI;qtS>Tcf&Dh0;2WcCOoR1lViI`sBG&YWGXlL}!k2(Jvo+bCaz8 zwsk1RO(`qRx1eDu(jls`oYN#tyUeH$$UnxgXJlQ#-70xiJbCLfvySPogU8<1$v1-1 zB8jcPLrXEsft0gy3;6ns;MEZ436RD@)-_S)M(Du%-PSJR$jEFq&S=UGb)+jI`FP%HEHduE-%P*pc7Zt7CJq~ zH<|l!j_GXROitogPb@X43WIGaxlugVT!}Gw2sy5w8)d(>VW6Ez=FMQB$~u`G7yPhBUX{+sTkX=~?OcPrV`Y+A z<8*Kc`}B*ckIi=!Y;{7JLIzIk2`XY#w-6QfY3~9cM7jijnFxa6P%CD0z%OmaBLIv@ zAVr19_u7-!v6hP7vy41|_)0G|Bu%2;S*=`4_z~>_+Z3WUOqm1!yTGir!Ns?Id|**G z{V{A*_9FPC+KN=tn_BLjeS5R}K0tJ>D27uc6JZrN{l&tjzFOtlCU7iD6sorNCiZZj zJh6gsXYzgf;2tp=u1(2S`V<>AULUE_-bN|FtI07{Pn|-hMH@Cgx``Gfv!~Cm_9T=r zAv-#%31f-?G0q$PYk22!vOG(H(Q}64!A(wL(XG+Ox$);|SVX17R#Zy*hSxr^pr!TO z#5I5XR7Xj{2(G~qEcUKqe)_VIOON(W0TYegT?ppwJX1BHb`H!aDUW<2UXz+cf*aiS z?=O$ES6^Rwck0Wf=Qgv?pM8Rwu|uU6nvjAL^92QHU;sL8uzKHJPGIl$UrE2WT6^hV zjKhr-s+9^xAt{Jd<^=uyq!muj#Thi4ifOfAChk;sC{cRF`_R#Hzg>1=Ly}!O0$HB< zW;H|hT`tmcpnx~D0n~b?dSQA5ClM)>8hlGRe@0OE@{q#$jPG3wKhSX+f<*;D!y>`# zL_TVSo7L9S`dmZS>p`!r1r2r9B7L?EqNLd}P5h}r=vEMx66rHK&5HE&-9l6-$yD%1FN#r%w5<|QP)qg|znAG?wKEZqliZl1ny5%* z)GQw7aA^-Wm8e1(Lk8A|>228r3ueU%YQN`W#+Q7)C#Z2Lc_-$ootkUJIcN9r;O-LQ zQD|&qI;BLcVO8;=(5zrJ3v0rk1|i==wWr4hqxe!Gapqc+J;2PZj!I}n6>Nl|(uGOb z^15kyer>(iInyyZg*wHH`LN=W1D#-enayP*u79Cd3TLExn&{5D>3nymiK@HOEKHw` zJ?{JwDUivXI)C2u0&cGD3PtHhyTyLExf!wY1FpgY@`o+UD?n13qhCehUR0i+mxv7U79!n3<8OZd~nF;O@x#QcDAsr(u`(9)LlxI>9dbxhFNe4h5`Dp zI{MTnYRT7^iIB#MGh3{L9hxwqDw=c>sM(SMl%j+O2@V zsF9ufiX!4otjMt%>94)&ND$jT$%XBQ*h(n{s+7L{L)QQ@$K{L=RBEmLlhbwnLqJ?+ zNAc0bQA>-+nSovo%>y@ZSCve+{)+x%#VtnvZ+FBt3~8ljvb2yrZG>-Y{SIap&M(Ty zj8gYhKh}PbV@xDiRL`ZIOe-66_(M$SaN`7t*)SP+8!wrkg2#L=KN%(1d;Ooqc7=Cp z2jz1ecsu#5{VBN+r>DbnR8F*^KI~_Gp8R3S%5M*4uR?K`k%24Hx4Ob^joFn2z+LmG zkHmvlR!~;jY-&wCeulg!pOyMGFMWr?;+|CTT`@_&tE@UGZ6H{%Y-JcoNU$fVDwY&7 zmauYzC{>`iuoIRo(QVU5V_2uQ6;FocVunqar$g^Hn@Fm>M|83CcsNxT?-~+>dNSSG zcAmVyv#<En@+2+n>nW z#SdA=%eiXq9pj+;*}ETvuL?hnE7xdWC}UO6v(zhc4$ZS%GMCSOWv6R5K;<@cj&s(c zf=sJO&GL}TM8_k+*#n=FPY2-g?S(;TK*+=2$N{Ya)IFSK2bt0N7|gi_nP@_u-woUn zJEdGRgQl`6zgVf71p~ft;{MnQrg3 zO%D9pI#8IKWr|)^^lRrz%p1d95NiMANPvIBAwHXDdXYL0EBdTrtFz*(qa=paP&2FE zn_sCZsz(m_8ACB5pufJ{I~}-@qH&%?19&YKEH(p?RxCb>MZ5SDc8}y8{lex3I<*B> zl{vZj!KXC3XKDwtN{&|eU_|wf`aclHR*p$gzTzx zqRA1H?W<7X*KR9;O!5MV6ns-J@rl zKV$I_Nd*Uk-o$7WeU?9Y7f$0h;c=-r`702*4Q=5UaqEv6_7wJ?GYh19uf-sGHqbK> z4ae!}$Xt8l#JU?(yt3|S9R;q?9K~Np;)HmM1RYalx>;L8X)ns_*rRX-V%?2<3ZS0) zzD;u+%z!QO)iEwUV<2V)E!}x;zMN1Nx@I@hjQ9RRCO~#bh{`8Zfhk4dSfFYmJpROZ zTud+74C2-opYF&vbW5w>=ZM1ZO&o^9(F07s&sx5$Prr|C#FoVPZ;-!BtXp!M^mJ)} zfZ7@VM}>4qY)x$cQw8ki|9>bq7 z{NNC=YFzkn3cbLe7;(4*~2%V0S;VA_N+IV0>NZrZmT>bP3-nVwoiG!ccKAQNa$tO&mVBW&)gfqkG3Y;ULch_%cj|8=pmrTlvZa%#loM5q)zI^?Dvu_WuI4E&LxgQ7AkpTSZ&D5I z89Fh5fq;_)Zl&XQehW&N(^j|1lAyo|%Km)(& zgv5RF??mH{7bp2~nLF!2AX`{Z)Dmz7I z&*%jMD{gnR%GIDsh&ejjo_iwF?hJ{VCNBT@eaAf>o$n7uVCx_-RxMu$o9$0`XfcDX zPc+_LQMla^{jTQ+Zxo>y2X>+~?0f!l zZj>najQZW=bEzRG_>99a>Q}z{Xde?<&XA{`b-u5qf644JW_^nSp0Qr9OS$!%rJmYQqN zZPet_ zi+rh$s&VFRlBd+OZ*U+5{9TirE~i<;-m_RB9^9>;0ON4K{df%&Q4CN_ZmNOnq$cmS zD`A#hNcDOXTR8H7XE?(9Xq;kcrXkL!y+2g>HQRbPhSzeiVMNZ2`8d^XWl!r9W746& z<1t~xW`>2~vp4H)ZqCT{GAmUolnRQdbysYbt9d(rD9`X~Dh=1?Y;Xd!Vg}ZJ*dJ4;@F>%YYUdHq6*-7or7LCSL3f_Po9%$TJk2n2!k*!zmd`2#p$>@7%HJPu8OI{$d zzH8Dsgt>)tAU*60ZE*79ReoW!{$<}HhI1s+WorDXwMu6i_g3$#@NpMGWb9M**yStD zc_?Z!%GX_xSFH57XtF8v*aSlqJMc1$%NvD>dh7PFdz;e1ldLmi)E5uuixlr2JkU%W zltYsBQ;PHG{zt^Ub5WG$S``iPjN?Oxr)R_N zRS*Fv!Q_YEMPl#EB(W=jWf93&6xCz1xU(kIB-c!qT{XSBx&7eOb+n{vf9^3J28bCA!{Y~=hi%GPLXzuFpW2C--NSEqc{B>SAw8U(t=hL&zq&b z(v4mpDojTV57ZYH9G@BuQd{|>-ax?q^=NBGSoQRnErx+liMV6LBA z4HQKJi>zKMK92g%;rrRE)EPx6Ca{Ny8hGt%`)LfXgC#2=zSz$!vB8Xt{(Znl!GzWH zN|oAw___ZdYbc?dW>!fMAfUhP|Nag_&_9S>3IDxxD`?|5h(+48Qux`heQ#C;%8xc#0GDNjUSZ{Niq-bFLoIvGex0eiz|>RouYx%hV`Cv zf=^$-Gn34B!qs;&ncu{LZ)rQ9`Poe0h92{$8x`@Kv?KmhQR-~|ZZUJZmaK&*xXf`* zK6C32QTXCj&5Us##CuE%Jm2{FL8-iZz!Y3n;b*%VC7veYb%sIH?;EAHZOPMo|9Rtd z+o+awVZ(UVsI(f%7Ja+aC>xd{>_NC|I0{`KrAY_8lCdpUb(ujPZ22D%h2ZeG;b$39 zTsNl6X4om4maZ#544gp2v<=gHY^UJ%FMXRMR$|XxbTYw==&q_{-WOH++M==>fr}G& zdPHHld?!K?WJ7FMiSb7l=4{qAfIgr<}IwZ#!rE7$!#&XPhP=bve{)H1tyE zy-3szM6&MdS~o$k0sk=LiH(c=6;*$A;F�gft;)c&19AgabzbFA8V&X(=^nFY$+P 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%0AIZhc;TSbLGE4e;5lg}#4zQ(C* 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

    ;C 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

    -dru@QIB^Svv|Bp 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%0AR;4vBFP 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 pM2E`!3b* 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®KzGq~fcHYen_5#Qwe3$$PTBUy

    {rh^e`PARKdp}+$RMk7ahU>^ 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�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≪PBEZ<4=Zg@>uzDiX$9;uZTEpZSj6sF@?^5 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

    p~=fCc=JO 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

    R4uUT zwGxRI=BCLG9di&m^zQA@p_@DZA3IcgQ4bkThdH8CYgyWdhw;7>>*me&b=)e068X&0 z?ba^G!`q=#p=#yIY}u*a7+C~6l^^>b-4304Vz$<)3DCe~1$t@E?8bW)d&1G|eexsY zfVs1E8c&Bm;>?<@?@kkR=Xvsx9#H4DX~*lLnCIC)r6W|?qT=!?WjuIhwkYGK zTtA0zYHt z+@}NlJ?8h~3D=Bc4oJ*{-7pi<=Ndt}h$CfLH?Yj(?`i$h(%7oIUoutUG(W4QG$6qwgU1NyAvUo)vsy+6jo|o41h4 zGxwg^s>*YY$jrU}od7Ll>lm5Z<`a1gV2MhsK-l|bAx5{IEtH?AGHd&?I11ESl=~%u zwkiTy`pyhdx;vJJ07U2-WKu595QSE3!E+MP@-3yFOFpYZvR5K8BNDzX*8+ykGXx12 zE#jLW20CyOz8UB3b#B(#Z&2?nkt9hZakF(w-0`AZ(dsSoqFI7O^(3Go-8DYQ1z0*u zEK~JZf`}4c_yJisoEQE+*t_8&Q=W?8NYoS7WRc}

    g%(v<7{|YdP`~VR24*56(TE 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≠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%0A$Gk8>7Ld>nv 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 z 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

    HL@7gR*5zqz-63;lE&b>p2Hboz6@ZSr>M3h<4 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⪙JScszA^5tn zx^qDkL=wW!(3TgtFcRo~ZH}hCyhEx%?OI#m`t>5Wkzj>UTa_C(JnX}Y>5St-zG_d; z%u`WLJag5K=cxV!ar?|!~s zIfu#$pQYEm$09wxn__zmx!>zLyW4qG93ua?Rv#iG8mF{YA8kiqpMEPUwd`#TTF(n< zTA($n*^Yd7`)e@Em>AbRp|QIa|GAdgLwt3{E^Cw2bgG%i+tD_d<%Zpkz%KFZxdS(rDTtJ*~=<@VGh@%`=LGSVbwho=YVMO z+46`BEe{TwrCK#N1H~UE3jS5CUEa zX!35ZVSoKscRKNZMIX@t;@2iB4vcgwI#bsAQCbxhxr5hCr;H=#R$@QDT->yXxc5W+ zFj@Q|zbRwB-#dv#KF{RWSIz=QX&m&D&_6Z>!!)9cBTj_&c7H8(5!9{VPs7ML`z52zcDD z+)s_gF7q~Nx3@;ujB-TtM7jy?DN6S)Tjl=1(i&N>b7)@U75!1kcJJk-QTfL-_@XHB zsbe_<)*jT>ATkE{Pf)$^@IwZ4gCRZY}o{#UoX?NRI3 zihmd`6;n6$;**KJ%#(`b^y>zN)Ux4IlUowKTk~&y_s;D3lwT+@2pH-)1W%$*3m$x$ zf)_?#V_KgL{VX`^L{t2Np5K|S$ceVdiN0u>rf8b3XqvWYn!ZT=Wz~dAp+l9Fny*Qt zie!+DQS%#fwd1Uyt13miZ4>j4ZZq+VpIT)#I$U{ud+ATU%W0qRC$|?>KX2Wz&lxoy zGx+}UI$hK~VUIS22T%Zo0SJftwK#J=@1M6??$jg|e`e}=yUa{XXHa!bdcnmn*d9x(*d_%Gq2jt|M>(XBHUhT~Kad^Y>yJt??%}zyaX{sFVj=?4BFTEQMv+kx(@2R)ZRIMWib(O|V ztp{TUc69&dfA%mtO0U>_6k{eQjmhn&r)(Z0LqeSfN9IrBY0CP~iOrX$RU2 z59tYrVEK#ti&KroyIEBWHnvUpA6HI(93twDe$)|u)cyHUckrX`_($F0kGhi|0U_H^ znx>yC6A*(P_B%QFXqp*`7U9HWhJY*0w{iCSN5NB^er*r^e<)n`=ie_;ajT8z-eqMj ztuGqBdv#`aTTrMq+ikXH5T&D@Nn)g8>9S0|yTKXsr9MnF$f-X4ri_U{hW9gaVqqHg z=xs&UUi(h^pZ24*DjnU>7q{PMoIEk|7S!*t&D7Q5RBKM2b8v|6pC8`*^tOEJJH%w+O@v0Ac_+ppI9Oa{ z!n^deEE6ji{yK}sC`U3aUAgFLO6M)rAEQ~)_0XG)uG;Ea=d7cbcr)0$>x;%!)!r%H zeRU%JhL4!Twvko6T(WWa?1{1FRW+qGzsft1Y4*_!Em7~!ugd=jrO8W-^1j`9C{~GZ) z_CtZgT>a)Cqvh9^?0&+}9$r6oTmA8CvZQpZ@=(iotmSGQlBHyv@Xh6*_SD^mOGISl zS7E!_l;r(em^ELORB1a&Ppbm+#TWMjHgaFirCy)oP#w{}osS)$a+vz-XiMaR!@^BGrc;TF=W}4EV#b6bM z-}LnOqnXD?CV@{&Iv)(SZi>x_seWyyo@Q*jcP04(y{eY&A@p&0H^izmrbuG&?fcu$ z)Gkr0hTei1=lioG_Hv)^pt7bXra&P?WPlG>}uZDb?Rf~Oiwb1Db9b{>ByH&<2g~3}HH@D#G^X@qH zW)|j zF;jk~V5ey9gg@GtTI{Xs?>B48@qB!pa+TMUzxqzClFanIABNY=kq@JfeIV0;=YAU2 zv)0IWo2aM}vnMN&ZYp)_^&(nbdfr@}{rgta5MGn6otC~9->;+PfxeCilboT+!hBn< z5(dt51Dn?5zedaf_pIVx4@_>#Yho`uw=O{~?mu9@JaVd?1}|wyuDU5_Xy`PX{xs!R z2C^maU$}Yk=ND|h=W-`j=Zh~(^AF_RY6>@QW-6_s&Ee)L3Jv`fV^Xd45D`>!{dYje z@x;$Zr9Oyj!%rlCyA*#FTrl&o{PMEZw)b(xx3cleraob}F5h=nUNV3FPoVialLUKM zzrT~r47E!l=IJO&s*t&YNu`P!~HtlJHi5iPym4DFj?*HUP-T5+5x+hE>@W^fqV`Ti+rPF}@?vPR`=+JDKxSuD2+r9~g_&mI{`{@2P_?(J8I zy|B<>zKzUs3<;w}`F-9H+VU-l_K^8nT&x+p{v&vEE9i;v4~LPfHCIL;)hel3X+eE9 zE%wphZSOeAn2;2EUI%2m>*_ekiuwEB!ntx5|aEp4iR&@yLdy%HI6`i+Yuy zKel~K|mg%qr!cun7=-b=8mne;vWvbag|+RwbKLc_Ty?!!O#LIm4y zT4y$7zNsXrSXSIu@-ww(FS)z6@$b~=8fWg|uIWSh*e2d>E{P(8*j4pE*%-y+JFRaT zO8$HZU;pkGxqbKk*0j;W;GYo}0kAS-5^kRtghua4qjziXF4AB|BFSmTReQ$0xJR;7#RMK2$MtK` z_wB&a&+T-nsi(45VyjvS7cT46zvAWgF>~1uhhI&N=wU1QaU+CBeOL2QxRI)RS}5;JB-G?I45y! zUgPQa*l#aC1(qq&Rq;*Qgi?+3-`sq-ZxQ~=-h47e%cJq?;}_=R8dVEcyB(N;gZuL0 z7B+Wnex|!W$mV>A7YTZ1-D1V*4O1Nwe8F&mrb8nMtFJCqbvM*fJmXvH6Q?M?O`+So zn;CKJ-H%a9}wPS&eerf)vnmQ%!hyW`$nPst zr@DmUCf3ZxYHu)4_+HD9Y}a_b>{N%Y!q2c`WqL7P@u`fS&(9J(*~7$dhq}6qUyX5o zqOj5}Xm5F6$ggREx508D?&bhm==&2>?qnNp|F4y?9$a0TE6oZO#^ae9T zrO=cX=j_Lo4H#;FLt*g)?{Ypufq4& zvOVnSW>SNhHy=E`u}wS|v*eCI}=^NOhxkD(;#Hp1q@_T#TD+#PF8zhYwt zzcRhM*dcu7Cp}96L!ZG-)`3utBFc&@kvm4o9VO!-?#MeMFnM_^u?z+J%if+^b^gt_ z;D@SA3##?IwU3;3=9JHlX4bM0tS&7wH(g|&-K?vrsA5??db>kZ%4=ZZ;lSna1x_%@ z7d7^?U30o5W7po9iBz22^e+zjwO#hBk=2axug2F2!FT>O!ba1}j8yiMKZXIl!$qHW zKdYr|7XGkuH7FBC=iXRjMvicDKu3>{w$CrzTBbJQmK$_ZufEHGcKgX)O&2FFTXu^`2?E%&7vC-RS zWz=a>v|nt#NcnG2o9H}p!ro#VE!yh*?!EGx;SM%a$nV~h-xn1+D7{b84ZWs}=bMvM zt?SRbAZ*if7)RoFDPY(IZz zF{X8t%R#H7Z1Ci-&)UVdZg)%7xcd!CSw>;C`j0pIh7yE?3;Z~CtI9`{3P)A8))}ge zxL7KJ)Z@O~&oyQFmHbhPPc8E`J#bLLyMHs@6!!1epK1rvVPvNt=Gd&wT(f`SLb>|m z)00~MVUDsF1zjHo;U!jbe?y{W#kGB(bisZ$7OOpxDel3Qw}u18sWN8+bipIRDdu1Op=p_8| zEMR6&UOx=)`pOaX)>QaAiez$*Y%*OClO|9|2kvvdVx8Vw|zjy(UCa&(!tS1 zGM2Ft9oy?N7-0S7vF1{`Mb6U9^eKJMC(q82p_7mG%D5FJi5f>1vDDo@!ddsnmq9H^ z@@b3J%S7rAc%q>0uysA;|FH$&_m$K1i~&5b!a<8j0(Cghc`gCUEu4K;_Y(--eF ze1teyyf+g#F5>&8)_r_0chs)1T16J^NU8sQ_7A3z`=-|w@6^w0yb5WIQH~LIy#Y@J zW(Kq1%#p_*ez9=xY$d3_eKXs`evqT0hKm?_q~pGnoNgT9apND%stbAd*a{|e!C!-C z&c1tEZ`JTK#})p7q>n+?H>MSSKF7BfJX=F{QP0yh4DCd`ZQ#7+7EzL&lAbX8>QbHh ztAYOmT0o`0GQVH!oE4`%gTJNr_}vNhIdzo*pHo*Ake;YdQwVp2aJw>wva^vdkjBzXGGz{v*Dp)={yAKu_O#!`^ z@GiL`>I66|+v^kIaFtKeR#pczkCin6%_BoHH<>XDOqZ4CX7{xlg~?X2$)-f^2WKD4 zcSLa9&WFj@m9+u+y0SJPU-ydmZ&RDdsb&u>E&5~Wc&ssNY`P1|$JtyeZJz1&XsLbe zrJb^3E<=xr-!cmXS&rIUnnJi^@z~t7*mo>?C|R+R%+lkZM#FI`RC+W7WX7uUfXtXT zyi;?7Z7rOg2mf+a)P9)YS5=e;1izxfKlse!uB!yaf~q)19?kTN-L$gXE7nJrgiK-c zHn0F`W0@l;lj>rrJgiyy&9X-Lt1H9Hy9&uMTOR&|miwbs=Np+8#iT;@hAM(OcNMkHpl~74 zSOipklhI&QoWia<;UYP61FcxiC|n47+_O2=@L4yT$&B-zC>zqI2TQ6(`BD)h6_!=v}DXU zJt}i;b=@#6c{D$MmIuY+sL|dUo97yJtFRnLbtLEhhU=-T(7gf9yiv<2^#KL1zA`wD ztp~D-BtP_!!Fk41Tuvwg;%N|~HVypj;*L(L@*8wk)dkECRn^J)A!SqSgcj~O zxU|gNeIRS-nh=7=`=P`4WKxx1m0TS#K#=pM$KYFSh2L^mKrGkR6zU>TwNFs5>*Xz$ zmlkFll$$-XjX936b#x{(VsB~;mEeG@qV{*y!%=nQewa=8(EIxluL|$KhJx zkV>O2pSh7!BeRF^u6#XD%x5rn3U}rv`|=6&ff9PmmT`vRARQ2OXG=VGT|6a@M;bXz z?2$D#Jw@a45Sp5!GTi?&++1dT#&qd%n{m0!@EuAT6LIpc;l{<$Y~hArJvMcTh@#l+ zJnwN2;a&$iLHKTz9DDk?FKjM!g^ca`g-(pj$Yw7@l_(6GFHU<;;>O`=;pl&(hk#>8g=$q;@z8gj zXYh0tz42@F@!o~)snkMQV|a#6Zs~6G@hYnq?gF+xKpZ*nxJg|75HS~qKmGvElcGs+2L!D^h5)_-Z8JPtQHTEn`8C{pD-{{!I;~o}q>2V{^J+w!&Ipep#rL0HA z?QDR&>_z-6${PW*wx-nEfr6&I{@u77OCAL=GUg)w5F^3>cT6$ky^WOd?1r(&U^s3> zjEQu4B%xD|g3%u_PBoc9$_~%=+^o^VjT@a4r$dF!n{R|`$2%rHK_Qt`QR6!YSyL6X zrK8$EqLbpdNaG-{K{TIKFb?9SQn^BE8#g>9bA_y6%T`&jeqp>98PkW%f?|}KY@^sZ zJT$v+dOVZO%~4F`yi|pp5BvXF$U;qJ*9T2y*Vp^Ucs?1wHLt6|oM)D;fC8~dkr(3* zYig%45$(|vjmAN&VudnSI4K)515l_b+6`yqqH_81xZs|$4E!Sb28H9BLVZmk3z))6 zeWzxN@XvhAUBdK!ID>{d4`XI2ms7K4>#VLsgNgSX=>M zOzJB&S47_C$WSE3rI8rC8<(Rg-&$XNB3ur&;9nl_$yMe4pPXPPBCsII7gPe$zS+g|egDYOJNK6}`&mYH#i=0o+t$VX^Kxf+mWoQ- zpSCV4?tD~xSQg}G7q!C4t)g;BRma+zzihAAUY1XXh&m z7BW}qj`^_Rcu|P@<6I4^J~nTUt4ldNFKwBJ`>KxBewb>uK48B^eeEyX$aUV(aIp-Ml)q#keY(GIkqo z5q0N`m^Jf$QM@dhPm8TMS#(zOVlXc{V(g)LTd>b&BI3 z!J@jjg+LE0Y`z_z4HOf%o;V(x4|W#`B;I(G*Jc!n-9iQpl(VL5eWS=7sWKxtgC39t zT%xwbcbQtr?rCJ~oz0`tkgx7Gri|!l47M>dmCx$oZ8#I!CFGqSTw-ZOBkLz4%AfJL z4=+UVb<7l$$F1-K@r;Tm*p|3&o3DWul}*I^a&yz6!XclODC#1w%?K$SaTE#Pa7MH8 z+Wx8HF#$c;(LOPmW&CUs7wrTKy9$o`>+zqMSMkj~7>oOuW%a^@hqv9qL3v?jfPGV> z(On9CN}x+j&6LJA7BQvNW2BIrXDYncVwIHRaU^YKRe#r{iMVhlnu+p6yKBbGX2ZLZ zC|YQKLUrO{oKo5w zr@caHlKboIFJw5AP!$Lo?cNkD>lje`NU6)ZJ|fPQT^}*Ab2nSuDPy~I7`I%zfQ!59 zJ}(hqC(7Qo`Ao4$jGS0X>CM`ErG{nuxeVwUGslhAQ4vehxIM1mD^L2UR@{yw{BzS@ z201;N5p9{}kEt)E%qx-Pi7A$C3Il;<% zUV6?MO~paS;UcN6Y&)=0!@l!Cal%o(D|x_{rCdkZmAHx-$Dv&Mg{s045UXzR%InRk ze9|2aS>rJbm!*igrA}yJTshTDZ7Bicehgd=m4riAqZ6ob~NM0I1~qA|Ba zX*m!Uw}%-Ham9lUH5!Rh*fegpORG!_k*n(h1VSxh2F=G*$m5>jJ(*Nl?t6~8JYchP zWqFM=mIn1qzi!T?SXH_^Z-%M<%{mX=MI&z->u6U0%bi9+r}u2f=8DS)oVgpOW#8Gu z%AiA4m9_Q9;$$}5Z2+&;%54Vej&QA&EOJ14W3qAVLjJduiKwP~HE z=KApj`))t^-k010o;7qs%V%vfbmjvW44Y%)W}kQ$ad9fMPzvz|&*Jvv)j+6y78;Kz z$rGUFP16&M3Qei6B8ZGk6jpo9s}x1E7qL1Vg)P6v+$C!vIkO>jg_ymE;%Jr%T1KN# zcwEBKMJm+hE-6oU%sXL&T=A2U@#ApVQ`4t~G0e;r-6lS#CJd|x;2gq9Z!NLG!FU6W zPj@;$*42g?+MX>iO&rZT;ZY z>>=fJDQmp`*cwgb<_+lLEigU4NYC<70k@N#LE=ugBSHE1_$RE*)}3yc%}%ge$_+2a z=gx7i465G8bmLeh{m(kTQctSJA)~5CJbx+Ds6{&N7kRF(QSgD8(AK=VQp0mV-S)3o zHqKKsrkZlo3se7nvUw`Jc9d;P8sjn#CyMn=3q{lFn%e3%*#+m5s3NP_-Y$}Tjq2gp z@V={{P_Hc1W%&`kx@tdDSAGmBD*Gp4g?&4UH9;5N)RrIT^1YXj^+8?J`kKIuV_bn_ zoZqn>HgaSEcgMZf-#paLrs{yj->T~BVfitss>b&uXl>AyDe`3FF#M_YJ9t^u5OA?u zRYRR44GMn9X_Zb0X-8pUR9x{v(^$-kku1$2EmvF6Tcj(;iwa30u+<$ zF_t{U&$b+|`fkkn$QmyTgcD8j9(J2_mgAD3&M2BtW5;UY`NqNup|gTe*1MIuqFvk+ z)HayL5W^UHxRN-L>UX^4D=+tp=MwC4R96qjMyR}86R?4&x~8^h5XCg3Xg`hFJvF%Q z!Y9}MjqBfAoaV83jJp6RtjM zxud~&il)nYbr{XQ@s6j%4_gRrGb|ngVN$TBI$#E%rn=sqLpe|B3coWl24!M+S0q`r z2*~yG!ni($Q79iWHI_zvdT#%hZw_(BlkHtYdH+Fmak+pVo2*EbZ#Uwq5JC2ih%=5& z%R;!QsC*c}9rfWQFY^VMpki)*Y}DMI z7EL6U*sEKS{mk0HJ@`E)cU-mG8}2CY?0mzW_3JX%l?T+tb>;Pb)`Bi4tgEPS4jjcP zk(u$Vn8_|=!6xJ6zBT$69pLie+q0*M-M*Ri)T0T;^7&fBg6DjycZTm!xhO$LZ=LVeJ+OP}U zqVwNWIH>HZia7)+)N|IugO(+)sSD#g$&j;VfnRgm)VXHfhyTA-4z}}<^;LFgvZS?{=(vHZ_YVc5ahc$AM7vZo*wp>O=seRD3kI6 zxuVW?sM1AT&gr&!=s*S6q0?n0j34rzk?o~$v= zo>P}4LwN0Hy;xsCPQA%n&Wd*uROzC98|TcszwAIXYp$2NC+q`5)aqxmNa)}rI`U!@ zsCc@gIhxKPvaDS#vy)*EW7V zB6ZZu?LEf!C3VY^ds}E2Tii<=M%3C}Z0$=I^6r@|F*=JU&2fLI4T9ytkGqxE9*?K~ zS8A6By?ato&WBHgr!(W(e3mz0Di`n1i)NC>bvpg-OR61KT>Eew=K3IB5;eH*(qeahRG}<2)=Sw8)b@`fpk@u zuEP!flJ+d`Hjh}F|9xfT9dol%bM!&v9Py@_YaYqVMYk~K3|Y6obfd4 zdhx=RWiw|*k}*Gg{O%n8MlQGa(Gancv*#g?d?D^QjmLb=jUlHY!uY&KU(%C8-=jUc zB$dyJYlfAduG0dd`nTH)NGzml$#gy^FSlWqby%^ssCpQLa>172-2s{zO(RuJ zedSD=%Nb=er^mOMPm=3)eYxXYSvskyIY!IJoyP+FL?qY)>Jdg(TXtPf$$T;{4j;Da zLr!6jU_=TtXi~#?-O09d&tbvn`$gr^m1+KBNOlSaITkPEW=~_zmdY41J6S#%-jzPb zu~#jmFOw=Ns{OiA#omMU@S~8wzKH9*?mSq?dCio!5C$YDO&Q)}Zf(Kw%?6G;sr)|3<3cJg(PFnzg|OqB zGrcdL3gMzLf6Wvbmc>X`6!v^V7gO08$6ZdtxBrG*K^4N=H|nOXievCI+?clLd*$KN z)_K=f%`sXI7x19ddgTqn%3EGVH6X#zmQ)l;G>FK(7FEX?j!G8%`BCoNL%Bs)JqtudW$RfK!g!*Fspa^`VB*n!EdQ!>Maq9QKEo zE*@R5;dt)VBb(bc0|~(Ooc?6|Ha#<;aI>p&Of(WLye?**R-D@=uFW+rGC2-6x}xdh zu-y?&9*6DD#qqR$Jif=1y#vQ+Ukq36*YpKk=;aW!4R0J~);xv7z&cUtVZ(Vpk3$5d zR1Bo$(NkrX%v;*~${(kb=3_tN2DFGZ$0U|Wty?4lEy)RIB{+^7J6x8H>asJc+9_B` z#QXG|+^!*Ny@um(z&%cNI24V=TH;Y21D2DJg;!I&gq?>g{N&^cneqNbu$=YgwU2<~ zaylQuaETU_OvN*X$A&_8c#DcSr!ZXw$}u{3nR^Z4okF&EMqP!>KA9c((Q;Z_nJ{%# z6g}p`W3zk+RX$(VV!z42VJjy#sCv7n=hWje&dB3W>l!V$^(IBe+m(FY?_>1b+LeQNW4hyowQaHBlWqRBz4h}~PlTyt{ zy&kbdZ5-TGI>r(6vEbp_3^(!#82Hq92Ut{ChNkVja86IB#V#*1FgJNwHr^;Ty6J`c zSd|NV2b|ZmAFKUPXT}3Y;#KutfzL(LO*!NG*>>}=Z)4%;EP65i-%?lghB+7N{A0kp z7>`{z!je{_6p>tLy?sBaw&u8<3G*qn0h2ei)x-J}alx&rzetA@;;lC|V8-b^+ebE3 zoInpkeSSbn)_SL;7zehA=1X3BE?*w>430gEdVcCLI2P_$n3$dom?A9q`m{_cXFPaQ z2+o`oJrD7DUfK0n9Sl{mRt6kktEjB-`oMlkg>I6wIn&J_R=?UIVq8#rt=JUeX>565 zZm2QWZ{;4-F7q)f>pIzNSE|k99&q=exVddj>9lzQdUjgukwxo}&6OphdE_Ggl5Y|U zjiyY0UJl&#ZdY=d|hxn z2^;K>-qtrKpG+2dYQFO307$h`EF?(YK_jt;;YpXvPBC9RBDuIXb3Icg&{o2p;>G=N zW|1N`ymC-+Po{b0J7sIFERcpx`Fck1sk>t0?vs4QZ1DAvOm-M{#3j(Cwc&hBHlG#m zi0ZN7`PFG!Q%;q;tg+YcX%=WrY_#{asceOGTNP)iXuYZ2ZY_i zuI;*BA|7|{xy5Wbz&D!Iqzj5mC9V7gd6%x4i2`M9ipXbvX~>yuZW4 zrg$TLP*)5Br5Pi~E*>sW>fT}Je&C|wsdRX0v4gnCdpSkj;x^)t;Vejp38uNxndkNX zFTOP;T&%oN$pJUGk=&fJ3Ln>Ua?@eY*4lMsQoZ=@fKH7mVa_8dM&?oXrtU&lGsq8X zS;;2|N^N(1dv2=gLiuvsb3&dzM2yYd5m)8yDV!Y;3pb80m$w{;lMged3EI3+S??dX zXs`Ga?}>}&)p^Tsz_-}MdRKRM20#*|cupAssDnsA^p>P2S+TK|c+|qOjZyJjwnI#x1KtXf%6`Zv9 z^hY0x8@EOBvc%$Yp@LHvw8^us(!bc)Zh@0;!0Oq;bdNkA7Sv5Q?hTP4Wfa$klXZR8 zFdB` zUi0ZX)k}5|{0BhZmcj)z=uY$UfR4;SG|QVeVlKZ6Z#5r_-B6>S@_=rFc_W>uNuQUJybPaJ%kACC;SEdcSi&mGy!1c=adla~u4w`>hH(gIFbR)j0ua zTUFr~M^zO;kGWNxpfUxQPh9L*Rr)?_5;V%J3L0fHG);vAC7p8dgO@E2-(I*$+o0eE zjXmk@b#Z+$Z*EKI#;=xmtR{?t`C;4g9m-di2dy&5N!8(d2b+HFRCUm{#cJQyq`D$#S)n3eT>+i@X@zN_ zBE4s2wk62D=1ep@AWwP~byATHay9C%{{shFPVpeO6VYtWJR}zEY`Y>E7+TlLbCKY> zSE>UnG<7#8#5T!De0FCMcNNKki}KuDVU-;9Lpl*%($>-#&(4gB>-UARQ`&V8Q^91g zV8>y=w_F_#WyJO7WlIXca#nNYE#<)a; zw-6oQGJQ?mG5hSQo!%(7{OTCKwY<6geZ#x8b5m7o|g&bU_j#EOWbacO&i1tY&5}h#UmQWH4Z3 z1SXqcaxyswfr%#P3?@gD`8!PR?wa1a6W{-R@ADenPFGdu>guZMDo6iaB?T%W0)vZa zJk^v5Qy#{cbH`g>l`vlna8g!PaR%E>>VvNnbE%nva@xsaE{So}DRYgf0d6tW)-ds^ z%W6cCNNNDKLa*tQP{L|PA8)0?7===Xgiw9-SrSR{ zp^`xRp?%4jGaZ+Yb?EKtsNIpJAuO|MM}L3>jkFNXR>Y|^v|d8hVu#gEWejgxM_rzr z7!4`aKlEBK={y&VoZxQ4C4Hc`#c@saom~9OgeMt}3tg)5HBjSgIE|{xCcze> z`@`JX-|jfwVcrozD$^6CBBh{%97R)(r>LM2?S`+%taFma10AX=pB!3J-2$Hsr@(G; zl|OYv^V8+@rc`WCbtELvzH9 zYhGci<~?_e#SRWYz)VmYp3HVlLpG%}wJA-w?y_`3Qd0qrBajF0z^(YfGKDI>0vN=tq}R0r9sDk$MZkTbV%+PT3zihmfvd~ znY7j@+D(B;WTgQqTvll|8HB`Ie#q}VT_IGuL#m5(1&7&r{20fe@mkNDMW1yCqbE!P zF{#}FiMeU&C9!N8gs2ObX%)0gsT1n5YLrl!l&*r7KoxHZ&_{%I6&tO`s(I7HdLNkmY7^z8*5Ng z!K!n(uu@Y8NmyyB#TZw82wAlCD$0SaS3wnRnty?vR zwXC|i<^S!ONdm>ex3a`j*ZX6WcPyh_mYV-WjIMdr_8F_SJ!&_PegI7%eOrqUx)Rh>jJzNAK z{SXG~GuRNT$LJ~wr^g{hf#T?NFVG6{gfJA)bmBS}4cW}4*BylwQZ1m->M`cx4ME-h zupJBWI#syG@Y`V_5;XAj;pHX-4K7Q`RZuTL5!PXnW_PJpF^>nnrLhU1-o*fmx3y+r z9^c7i0S3r7ig3h>%2XAcD3v5Dbh>WUS-}M3qJ;)yifbgNQqZk2W?S;$<*C#C={kbR z)!^cQTQLCNsFGj>dRBu+OpGO46TY-|45JITmMf*I5Sn-cn?|mf#SFTbSKGZj8~lA6 zg^k%CbqfiRDyEY<*;d|i_FgbR|36l{&^?;m{5)~qsv;<@VOrTR;)MCwYl+{E}+%ljWc(Cbmz;c_vxq^S% zMk6t{Wy$l;F2i+&uc==4^~fAji7F`gUsXDOI6C@C3#j&7W17ny0MWt^_g$8nY!mBD zQyH6-hPvDZ9S|(}^vMr4w z^|S?g*OsLIw-c$hEJ=N2CqjdA>IqR0-2;+oDBe=Kdg9%$6vxbhUX!82M6iv-DIz(* z{7jF4d>u5i^5kDdA5gJP)wJwzaf{>XQA=TPGYgATgA891pfxyM_B$KHAT#LNIINOTeBJ2Y zQkTsZhl+UxvCO!OKmfDdXg73x(m1lYRj21%ita5d<^qrr^~f2(*nY^5h!LSE+9n)= zmU~{K&4XQ*@#`2JokDp;xTr|1ig6K*Hdr(SL&~T&R2&Kl3wTlh1hi>OLdZqr5b(0r zS+oW_i)f4HHCr*qx}2LYbi+eT&I@@)VDSvL@mpCNxQjRv4;7jiuG#fdRCf$62w& zntV9VA04N+!XAbss1E%>vuIa}%cFLp09+vF>b~I;oNq9Ykd;QID(E>CeN9zTJ;Jc|HNZ(yBhKC%ldmMyGGdrh?Cc;3FffNibwDCZ(Zc`D`QD;o zBnwGox=nI@*B5P@g(!rI$Z`{xOKFp!$k7Qea{ zmo)o+BjBy!+Y^{H4Z$#WWK2C*r!bg%>2fwM;Ze0bdb&Cy!iVTOepXS}LKe8w^d4Fe zZ;igNgH{*;-OGjyy@kychpkGrnuQNW&-cm=Zoy_VDw)oNwE4@T4P@bo)+^+i&P&Kf z+&g*0-4}AO3zsn`Lu47sC3o8#?E)h|tWq;|Z%d08I)xwpkr*pYvRZki3q=Kt@+;C> ziAa^foy8rHQ6#PLQvRa*APJ4iDNt=U?G|TJ{M`o$e z!PvJ(;kW}GpBG*-8N5R&W=narSl?dZX(K%D!cmA_8IFY;P<7Q5E^I_)x(C2-i=Nf; zc}3g^w>+*VShV4vb!xwATAg{t#;+Ub2&udP%=F~rLUSw68LHK8*gW|{G}ny)3ZH|J zz-V4ju{nqV)Z)lvGV!~5XiXkvs!elgdo|g z9gC?Kgv!yBp{0_;1FsUtP{+$PwG0SP*x!dcp7G7;_hX_2Le5MAF`2`n8gM(Qu8Qpz z7SZZB_k`L2$6zA2v*h}XY|)BDDRn4?qxyvdH%`Ef*v;xNDQ%IG3Zd|y2``Tr+n&Hk zQg;dwn}`6S#YF{HmteF zrbyp@hRyh?g{2T=_)|>4m2hp2qBq)VSpUmuHHg5p zdICb;_$zkvvvXtlLkSL2Lcj1zz#fMVyvU%EuzJjXGriX({zqH0^UOzd(aWmXkmVTB z8NL$A#O*IPGQl2`iFJhNw6WBnYBSnD5pWsSSA~7)AjG(Q&=VKsQS< zh;5>!&mtM0Xts@qfGz1UirK+>#l2$j01B<@u$qqn9MotIfd<3C zv48?9RFD69CG?$?IYi#B=Q{fPEtTaQwo@O|W2_D@FkeTI1Zs>hpRGYvWpE|@VVMyUIFt>SBA9#vRZj_j25flGw&OJ zNS#iwO9E|@q9q{D8C~+Vi?g;!L4%Pm4zXi|jw=$MMDU$QuFpgtIm4O_Y3kYT3gj_W70jE38cRr57VZv%3f52=N-8fnLnw~Yu zUv;L**%3JvEXF2G?k2-V1ARcea)~4YENpZEvH3iO6xp1fm`FGnR!E9t5m~g44Ra1Q zv@vHVlAL-J_J|o$P+jb(Ao+?rBW5wrYZ?C9rkK3tGhk}$a?9h>9_R+I2YF=-ake^B zRRl%c2Gb|*ERVDYRaeXqaBnWTke`KLJ)4r#-+25yoL;%ouaf&~mrCNlX*l=|SCYg& z6GGr9-5HFi6umT$14ECIrvMWEr`iGrv7{-`42$GzJaFjFkL^hf)4R~Q7I8=KF$mri zYH)Jz>f~Ds4WUEK`{cdhsO?#%;s9B*6!v85D$>wS=wEWr^v$tusXIo3qVN|c`Xl|w ziI(VA9Qk6P`+@74#{%<9ENnAr^yF>-vr*uERZN=&41ZBa(SbxPVDwEi(?loa8mG8l zSW?t!=oK~BG@4ZlBJwzDkYe!&po>s$*=r!}ifCwEx6%?_1g98-Z1so7)I|#-jv@bX?I6l28=~PU z&`lUSLXj298|=7E6*It6H9*^}gxQg*OLpUB=+1*fYOw&$c_jvLVh@HRyRv6fVT3RYel!#PzcBE=|7#O(Wf?z z+NzGddaWIZ37STkCNHcoP0Mq;!A#7d)Qp8ZeE(oyq)>~sV>qGaoUlVa55U<+^p}%g zL=Kjfr+7G)_suY!w9-BK%wkZYj z5K|dJe=$RhzfljYs!1g|3FbszOH6MQhu;e^?{1P#qs zRPbP(QUL6cM5?=-wGraItK1i zolxnPkX&fF^8oOY!1c{DbQNl}g+m(TRrjjOgHdusw?^2b8%{$4))GUhqc(P>ajPcK zG@Kq)-E_s&LaeSVf=L6d$03S~Gcn~0$V36;$*hXYUFnUu*8pVjtKI-4&>?jcKMMejFA9{_xUu36#lo)p@SZZV2(=-A5L+tZw= zB*7Jlx{wt{-2tF%g~OKu1$YxV1BD-P*HV2k5_*+dE%4Gkf|eyi za``~+$Vr3MSyFV}N#p}*ctr!Qv^;Q}MMbs44v<+fiwmKW3+|{b15yG>cpyC2Zco_158Ld(5Iih<9y(>g@Bi3u+tRtO@ zW_phOi0Lycfh)_fXEYYo0#3j9)gF>Hu@5bIHszNDwVsj)Dv}vZ>{sZARw;OvX!BN49OlB zIG(O6`AZFN@Rk4q7nHHQq2y$Uc2dxInpi`M$I8`m$PjOi;KbL0x=8XRQMW_9mt^Yc zX0YOG8dR)K`C*#jK|4`10?Z zSorQ5rV=u41Pc`J&xuze(NuO(aRw$M-6$@(XtRV&G}?MNFk z0;a<-PB0f!pd`cx8Kf}dV;8f_>A1^RFuws_#-MTeOBjmBw!#o$Mi8mo#PLzdyB!>r znCum7Bdd@AobU~Vx5`7QX9MN@pvj^2?c|Mhhngtu1&f#ekSYiV#z&^1RljC(<$L5ZHai_L>jk!gP{+rx<+J6 zFYzDI`-PiLG-q4}!SW?B(O-z>xUqw8Yb#R|BqA4r28vEzT{-Ugsxz~L+Aww$rHffO z&N!Dv<+83tYAE8O1GN-~3=f^xj4%B#n{4#Nq; zsc{rqiZ#DLMN$Kj0ybtURl>#`|9DJd72_sG&#DQc`v>HBSt{`ecf9E*PQ!1HtGsA6 z2FQaL&lM^VPL*HI*P39syfJ_Wo<5!pS7FnCadRl8+PHFsldKj)W{4MoMjSJ1M?kks zwuHpWeDc&&|ch>)(=qGnQ%WkI7 zB0!wP$s#_60DD|g98N&KkGOlvLn2Fyyr02wU+@8got5T#zjz8_9CT-fW)}iaUM74k zbe`|HPolPW>FTJr{Tq-{aPy=4dSwrP4)ZKiRGk@Cof3-e<@0+u{@{IoFY#*8XTBm2P0E1tj`Bge)P9!=+Czz09@h0@QH{PYZ!sNN)C!fB3JaO_Y}78%Hh%?F#u z)8oUPXmIjLskf|Jl$9#mR21z zO%oy@P9d6rtk?-L8WeY$h98_zgAtLcN$52qQ!VU54HWoZ7?LLm#nwrtB0R&1`s25h zYLb(2P|Wm~h$5cw6yy?;5{_0HNF|a;CqmsWnA(trI@=B zcq|eCi+Lm`=7aIHg1UJaP|B^N0?OY}kq$K|GmISp&|wg$#;Mr7Gdm%&T#q!Yl1fa7 zgj^?}48Ijs;Z7_pszsHg<>9y`gn@8my`t?Z3G!o3OYt%8qjE8Wyx0jO%SGmnQK=-D zF`7(z!mX8rG=RzSYTmGnYXMbF0wF1VasuiQ<*bw6n6jiWuvrpPDJET&qSF={#G)G? z7;4VrzCj3@P$QqGdM1;R=%}C<{)!`h^CiH3{$B7R;KOioCah}6gjK^xlQ?M?>S1;P z%>?GWz*8-zOLG9=NH@t0^G9kHTQou$J(AR04etsPuGcS))TCK0dZ!Z)DS~P9<|XL$ z>wb0wgYZY{V;5cvBlM_>eiBRWvXBwUorC7-8eEjVpn*1c;&ZH#)QN=x;WF>$68Ri) z0}GVIEtCkj%xdA(5MBg)nvsC}CAcwSns_nhIy}b0p!PWB9=20PA99k76Vx&A ziX+YDKrq@$da~MiwHC(>ul3ZLMxUjc!!&t8$}GJJQN&IS(==z zli}uOad=?D!~E)*O)c2SEM^R#RMVXe1C`Z<(h>7v>T&wI`muPxHo4(D2qw7bo?tGr&RsyCJ2qQha@C-F%@y=vZGMRecLh;mt;ChY{o&2x#1rsVay8 zd3h?h!Qw|E!fk{I&Tfflgp$6&wM3=mICva2$-r5{$C{kX201F&sQx?jO5XgJOo>(7 zO+Hzn_AZqIG~B6F0^k8|OHe}^WyFh&lN_LnBsg-{T&?D(c~ZsmWBHZ296+&cQ|l`t zF}=2+U~dB)2p6Iu3gJ#mxpCZS5kHu_(=c8{cSjcChIMy$9VfQCgT@W;?yP%m2y|Ko zgnADEa03au0-7M`yW6g~$nO*m2>sf_JA8hz9R9ffo{<7A_FPh4)JN z1z?1Dr)6wBc&`9L0_H>zHQrf!qR{akWzigog2)F-`H|$E6P+JUK2#{AE(k2|t_>)< zywh!Nh761@WO}!&!tnGCfG|dVuw1xa#nI}Wu8Km^yUhdR);mm07`)!EL)?KOP8fT? zgck)oz|utB9uh~jcaMJ2xx|le?~W!n$i1tufkN54SLt{dQOtYyzySl_Qy@6{z0((A z2>d`fCl0>T3^gtozQ=p`5%Fp9AU`a=C!X1&b5jr?-)S5#N`9b-A1dD!S=e~_&dvve z<~!XL_Ea1`KUgmA6F-o?b2`}KX!^lZO-x<$l#Bu?hQw9rM#3&%QHLXS1z-g7rfn3g z4!s$^4HLsb1W<4fkJTSiJBJSxLnltV7$g^fwaJYL-J%Qoj$MYsx{EdgH3S_b5wG0Akh?{g1`W8(CBucMw21j_&@^zamR$mQ#zE`AAg=XxagMVdg=&PWA<1S5endBNVha^=|rxWpir~?ed)S zi@N#LNCLCYo#VpHB*m@MtZo|e!^_FRg9@9Nxpce;1gI?Q`&*_fN&|%#NNC$fD?1FT;#-@EQeA>msg0_L&j9`s%p_47e9CH1HI#+u-@$x zz!y7YCZTR7MNbftNoY`0<>JvXNo;5wX~S=;&oceD3nk;qnINEMr-5b{b)a%$%|o?1 z8^2OKQL<#@TpcBnne%xX`PFF}qhk=~bD?YlU3O>F$8mHeSCxn)*BxkXDuB7cvH`DJ zXFVmxfhg7B3Mg7iMG9C;Z*yJA*WOy)hBq1dUTtIk1d^7JnV69G0K3%D0R0VBgdKNG9wv{ET6Te7B z;)5tIFiTv+>Wa2O_kdI2ylU@J%mI~NOmQetf5NN8Tx>ifrQ&@g0G5$T04&34k-tql z`sv@q`=gQU5b{o!a)RETmRkG}#d%FW%Lzq6H2E~y_*RZ2Q!6 zb(V$mhLbUg3@mW|$&!%^o)Tk?UItBZBermx1H3#)rD}ll3;U-!H+bxaB4Dn-?Btaq zx~z#1{pcR5KCGcD9l82vY5EBNx(JF~#0Ou*p3S(`+kaGc zN$?5O6?2+_V>#eRTylgo9czxzxkvIBlMGq|_}MCgpqVvFqBGk-OEf@(G>F)NXk7J@ z)|<<7BhrNsE$hjo@Tv?c>3|L~mviVAMIzC%7*Gv?8OoWWqtkn18eaS@0x&tKLB)!JC>VtX5vkCy zuk`%%-waNf&Qw}IhM|G_uYe2B>NX+98V)?ozqVI>UZWUveb zuIp{_^{P?BZ=fXT2N3y89sxKP3?1uCaKz7CM}I%6j8}H=~;ApbN z+lPPlVE=t`(Zc6GPCJ=#Q%IG9H3?5hobu5zGdw@-w+Im~JwxaZx}5!Jw$YI4(3Fi=TBk2(iFR%Ec+vJt3agAB$UL1ROCV zMR`>pu=%|xm`1Lcb#spSx1dhb=u@4<<9_Ti8c#PE%fa~)_N{TjqDf(#?@_O#U|Aqp ziw_-4)Z%<4v3wc8Ui>uz=|=Tsfa{%t+GtmZ(_Fm>tub64!5;F13$x7&L>{KCZ0{yd za<`{rUYE-ebqmRYYm=AQY9vrVzy+$Mv5D(8HH+Tp@fn$r2It(pVYG=xh)h+=R5GD6 zTTp>&cL(cmw3+3y&{BqA=y`0Fpka2v0!vfw22@vygCv9eSJMYIa)unDs+M;mL-{ z=dUy*#bB*>$i$1q;@X0itId)vnd{Yas@Xj@)Mw;{#HjVX)2Bvwa35%XceirHERw-_ zl9qKXQd3zCT(A<=H88_zb=x}NT!8}3riT4!ud4(sd0YggPTO+Gd#_x?ust7v*dA31 zH=Yayxh_DlF3ZJpM7EKd?{CzU0o|}PtHrX4(eOn;7vv~Nbs^6E7(6J90+LZkY!7BE zWj8*BR!22krG^sno)F}~lvgmRWw@~X95`aolCt55$uN0wxS-q&IYLNzniK29|BGo_ zfKKw#sYnbA-?#*<*ZApUjk;mc*tO{L0b&f=VN!9{?C_l|kCDQF5|GFz^b+so6``@jjDjDXb(|zhLgfQ5P{#tE zd67aIb5qT^Nm_X@p%w|q6dZFuuQ2qwFj~mGB#Z)N^Qxj33!;IbCO#o;*9PcX{lXBS zWe)_En!G>|-_Tl!BR=TAKAq6(xTJhl6SV)tRTG+J+_cKlaAahxYCy!Qu8?S?vlqzR z(ZGCkYWtnspEQUc8HW*I!EvArvyE+y%X%{o4h@fybHr9kok6z8J-|Uxb_n=b2bE$OH;Cr=@R>$W z8Zi-@03S^A7zDHf=}F!bQrksju}EPsM;@B(er>=tM7vS;Yx#&)(JH8V4oT_Vc~vd& zfpDz*A=QNuP{MJH9W7@|NdGCIStPnVs}4Jm;hYJ9sZXa%!I;pwJ+a!#szqKp;_jGMsl{Wgrd1yRGj3SaCVcrp3`5U%SiyhC_v>w6-6{NuK>tT zdLn`;DLrwBf}_{~TjIfp8{+CmWZFRku23$cnmyVO8YoBey}6T*mnx#nU|e!Oe8@*v z4CFNi+i`+rRt)_>u1p~aNrz$DF_fI1#nKAf0D4;jngTC%3#*LlcaQXWgr zpbuR&XxhvP);y7E2<-BARY-sdT%k6y`=J;%spr zpj6uat7j4Mz5qn2)X^6errsY5K}3kG+JSoLJaVh`?!B_`Qj1Y0nI&%>V%0n0zZp04 zCXW~`Yh^npt&cHf8 zLg7}DBJP(;0S8kmB|4a#20NmjFW(ShooIu|1A$P79LFZXULPMt8IG8O^6aGOnYRpE zRhCMNcu^`1Eg5=PF58v~R}+*rI7QFWW!ka|k))8S03?M}Ma432S*5ULl~Btne}R?> zH#y{onyM0sIG$&oNP4D5VdAXK`h^NRNrHkW z7f#l&38Pw#LNc9>Lm&y9qXQ+=4++BUGy(w(7oHRes&%E#qC3p=tIUWr zMsa{z;+IKyh3q7PBCf6t#!w&TPKK!|`KHl=qT{{h>=qoL!3x~}89PIen)80KSI?vU z+OA^0pqOLhp`?3%V-$8f(Hs}mDh_nC3|95t@EFqN36Ob+@k*XFiLfqRP1OIT^66&*Hp;VGvbq& zqh6K{JM@#zVPt+0>lq1TC((p+$Q>l0LGdS!lcS>9G=^NB9O0z^F5-6hh({t5iAqLH zB3xT&aMILKo2en7Lz6_2QaDurzF*0T%86EsXb4qzki?y=teAM!l_IN&qhJ!Lk&+Xy zx<(j@A9A*H^feQzIwdr!#m4KMaMcN6IN1brBc(R1iB+8xUelpRIVtB+j!>L&1XrJD z1&#=Gv-73@a9-(gPz$A19uK~pHU(IHSk)q|-c4aY2_pfLqQf9w3NW(VB`S6-8@%l7 zzJ%;1ZsVk|cYBOQnMC3ju2pKlwAc1Mpt!6hI~HkL*MUJsMn zDwty2x~`+*%Otf(iliLVA^FiJsaYbj0fI6N;Fo9;u*=-N)zL55&%(-viX=~PGgk89 z&*Vf>fg3kbKk$*@1?l)!(Hy&|*_KpQy+S;wHl<|YHlU@5AVKwTqP%SmMWIvKxAJ4R3LL{P;&5PSmY{0EmI$@U=KT8UWSVJ{>II zv$F{X=xJ$g1_7qGz~yt>T02bx&4)eKs#$Pr7ion$6A1>x@Yra2ziOIlt`{{9tH$$c z)2OZLj-duZv|4bw7@SJRkMPF6eY=HhIaP)Dqdbz_paM`f zS5$KwkRfX;1GI4!C+$RdG9#MT{2zK_Z_} z?^SM7!*DWwcg-=NQcVKJra)$nIWAxXN>LDn&>n#}>G-~=6%0hcn^ zlmm+yzw!_aNFArbT41V$C~}Pi1`t0L;hv^e3(gElvL55j#vQi+kW@qBUUUe$?p8ua zD8)SpLtt`^fnLHSYPgLVRA`SawO$=mhBYsI4cnR-45(n|JDkKF=yDiFs%uH$R@gLS=8HLL+JrJozq@i(3 z^T#dxeizzQKA2Qvpp!HqI7-o`s>dlR@og^G;T-OjGLUjjf}YEWkGdJ*y4+B{vd~gZ zs{t%%iJA)jJ`Dx*VeUYp+#VSQ7|7fK0!9*efUp7HCIRhBOKPrG3PW_&lB-O3qmdc~ z|9!knU7_dlu?WnTkgJ4Uvr-f9p7U~*1WscK1imCDSCc?Wl0c5!UgWB42qMYV!(L2E zTIL>JX}uC3ccpa{xSGoMeWHzNhRKw|2Y9!qQaAzkUL!$3FAnvoW=DSjTe|!099+3t zJuQ|rubSm+NPAlxW5xD?ze!*lH_#0Z8%X4P?8Ze(8p9Do%f?pO4s3vKx^k|ZoYmPjLFs)iwFeQKikCfPjMsp~( z=*=b$iau^KgW3Rsx7)GhSI-$Eu1`}(zn?MF$$=D1qbW^arq6CFQJRF8=FTWzcJ!H5 z@{3hQx$7@i-9(-u|6;8yOH~T}*Cie%bI|~+aH_Iea_#bSVpd3=1mnwwnW}<%TqVm$ zfrOR*4$k1$QE1FUE{c=1*eiXQ67WW2L@x=URqeM+Lg+&0qclcAb3$x&XBEWf zhE+5MUi=W?$}2}iYAzsoJDrl16HSA}F2oT~XNNjbQ8NJoQXPOIi=@-gVnSEV?!1;$ z%^fyZa`TH8YEiqFi<*{n8kXj>@+$E?wlrc=9fNp4x(1Rv18va-ZGcuNLhsbF3siH? zpsMEm{scY-Uhz}{Qnx%MDc>#VDQ$)Kl-6xXr%7Vtxht&SFtci>A62eg7Fw!lRlq8& zs3Pso%x!QY>G?4jsW}AAheRcyrcR!Cneg==6xJzOVi(GU0r1km8AYS?)RQ0M@~A`& z>{j)h6WUrww=KhOsmw$|k|2E|D_;c=4jlHEE3p=lPO=*43lTl$wI(VunYylqR?Sv3 znY^LohRNqtxsuCeH0%VN88nOq8KsD>cxql%EVW=5`OcY%#E_C5L_`(DRPq!loyjO> zHjincsmTVBIx$kw8g$5~Vjzt|CxuMZ5KV3-uPhp)H(1rQBDHr`Q5buOprn&N@%HXI z(^STsmEyb&L#(jaM@_?>RSraFB1IZvp+;m;Tjmo|6{#R8=S>o&XsI?$c9Bt7s)=+M zI!e7Wks!ZmvuIuE%3xiM8p*n#m~Pu?T8B_2$sib91+AefSVISXje_$O+v3r|Rrqj% zF{iU2{6Nh zRc&fFV(9unXJm=G3m_R;qUc)EZ_iF}muZ+;_Ubvqd3r+<;bk;yrl#jQ`WtY9y2#RF z_DebWO>)`My^_KSgcXvmanQ(x02u6MX1{eOGmDx!yDKx!i4@xKq>)a#p$v9&f*VKs znh=v9?oUKtsoUu40aJ5FI#n4%upXaFF~f$4q5q%HEY$YynKRqEGyRH1*(N>!baZ>g zX{@ALm#k)pX)YmY8Z}`WR%7Tmk{qTAh6oK3(@{F96hkV?=wk`Fw8G1Q&_Wvr%|CwV ziR0G<&jxtqhfZQ<@STmX`Bi8!AY!O(gO-3$INX z>r=b&Y0{afCe+E%;?&^^6-hi=-So^sJaHhek|d>QwECQ5A*T-UzE@gVMRzcoH8r2> zLS=ZvCNf=`do6LMrKtP;$YuJSBxTN>A({U=*zQ!Y0wu78Tv4ko))5!K%f;MODIEziHzwD;t;8nAD zoUO^5WQpaT4sb?+h2qVg)UMzxJxTV;;iYUNI0MKIJZJoP&0;I$o?=vHBKk%r zjd?~#q5%D#aO4U9OBfP+2u^X+jz%+%VudHwaJog2^OqM^jOMO1%F zi?BRmDoB>h8+}S%h~nh$;+N5Pi~O==LR^-D$|}WWR5>pw1KLsn^q~?cs}hfLGMN^Q zB`T{BPlg^s>LH*BVMbC1TZncKqY|n zpMdJC5iYLM2LsrG!l@EZQ7-3mG9~1U05=sbFjNNh8Q`?l zV!RYUGgT?xbEz8f>68Xei!^X@RaA)QyP`&X%2d>d`(6o*XC=`0${L|$fy%_&tg2kR zhN=?c@vKUTPv5GPcs#4p;$x}`*jrVVz`;>o4u~G*;&Z!nHk=Ud)N#sT;+>xmOPJ%7 z6``XZ;I;|z3P}Jv#|hjY-*1M)3Rii_W1mWhcVQ|aoR^a80eULlvT5;r0E@j6*jvy9 z1B);zW)C5`Bf3B+b71fhYtV{bI2Nm5CQaQhbp@Wq`<*1VlFI5*ZW=WJRS)F*5?iA>e|X6e|?m z6bk}8K;#tPkWd*Ua*ErT0z`>a@PLUjX<&X*fC3-|%v}oDUrtgzfp{rq5I94exC|JV zYDi=i_dQ(>@G*ebr^N~*;Cz_0>sA>s^njpUC0=v@52^u9<#K>^f%-4;76w%!!0jUm zOc%(y07)PTu-{Y)*itEAdshJ44LEvIz%iHtZbB)b4{1Q)Pbb9e3t0YTX+Wc!P62qJ zv;k~IKypY|0%cV|eN_M+z-rQfjwTJvQ5u+|igIADi?tyD`xVQ?z#UdRalm*0oVNxL z+<+b@#KMcXTjT37V3-iMU92z#C)a-S>2Lk~#$puQEDXtAILoUqWP0upwC$(+OigtiGFQvhd6Qmok;7o&mH zCt`(hsROaB;mZH893Qhq= zj+A)*N?u)Qu{u+HUQ0=N6J+L)jvR0o0E~5|?>wnJIa%xq!DSLeLfl zE=b_K1lT96oQKX}KvD#5tSP{SDFw`J3eZhX=D7~AEnqPNd_Ms!t^{OJ0j?mhffl;< z1Cs_=F<_%8WceBIA}O5{0&a`raHa+BTose8`-iUIVul7xC1`AfJl8;;3@!h0`j!Br z4Bp&<5la9=2Heg|<`b1-MHu8T1He}kGdg>Zl>$QU^54#z8M+5J`HIC@2nb)@W+OstiC* z?JEwn;WX(3YJIW4Uo|0U8~xp2=>6J&6O*+x(l|v?f8H2juxLa!9K~mdknKiT=%2Do z)<6YWZcSaPRm|IEnPD91M_8(wronWnx1~F4s;Z77z?WtGd|;@d3?cG02ozkKQRr@? zXl7OXaFV8{*Yp82XsD`o`j%1xdf16%)l(9dsamQzOanlaRu9JLG0>#is8hJYVBi%A zI(bDOC~^jl3#_Z7wi~L8|LJy?t@uz^P$;ni*NTo?HXnkeQdsjJF z760f|>_K+$1Q?_>{YqBtFg4L~=%n%Wnq1;#Zp1wr6jK5m{kMla&y9m5k%%O~hK6XI zHVD)ij<|};GJQqcHuQM7tU(rlV#mOdh|fhc2FmE~w^VlJVAiBqYIhMGIu55oKO1Pg z8Wz@pliSxWaXI(^LKw_rpf=hE(l|IOWwx|x3Z^!MHgL}%j*?Vb<8TPJVhJ^&P0*&= zrj{jPd>W+@NkDqF6QSdPx;hDJhN!eOTGAu}i4EnEvPIKGzexH&QyQyZ%d20Pqvo_6#Z||F*^N8uRb3jUQ79cTujwjHZ84$E7a}vh z?PnJCR>LS@WYhtU`~oeHL8F+@%~108oIw>y`B@clKMNlPrjaj^O3Q$bV^$XXEF3yo zx1D~-&*GqBHLB!lkn0&AZ$K2B>`I7)(V!G;)Bs?C`XA zcbaMr3(KmMs9fhTW><){aWqs!0OqkxH7eSQFb#tJvoZuclg!qD!?)80|G2rm$e3 z!_8C*1-!&9wk(QIBs5^=1782(e4@|_nC3vqUF+=S8Ocy zwo;7|SLH$noTeaF@phKItAuKHR9Se8(Ur$ZdMAgWM71$;Xm+f^%md{rrv!}=X$R%d z3-pf|U7%lE7XPdDX?ZNfl8Z{o&BP+FB$hg=*;r8`35|CgmP2MJR!c6gGW>~;hE8lp z>Y#dz(kUpqM%RNiLm5_^34)SC2+7r8t4wb1Y%9Msd2Qo@#u{zIxUcd zlGWs}6>~rh;!Adv!K*Lg8E4m}pv4rtOGQT+*5gQ4>LK=awMxQUJqDwYf`GdhXpB6~ zfwt(OCYA+xivz1;jk#H()W!@2ZJKU$ZxU!D!^nN;&VnzY&05LB7DSaCxajOQ`J&Qz z(1pSoZ^yA(pL!LEJ1XJC5(G>#w$y@yCbXroNdgJ+RgwTCs!){LL#C?OZ5mn-`ar!i z)>fUxzgGiIuJc5B+2z_+BRK+UAF3OxL|Pp7ErF;GX?90p}x;THKadc*JACHFV~B zk~cPfH0hXK#`Re8I*%_0SuLOE7>y%v1++VH#<7?ia0Dx7s1{-qR4DCjX~B%aEEYJH zAB;+sE2`ORW04qfV^Zy~W)v;7(zus(0HxW;B6gMwN!d=0LpeH5SEYcn#t>fQ?oHil z)fRZ#0x1F_bG(&_RtQY$9ZE*OZfU&u8e)2S(f65-z7_ zWIPnQN9-TDp$3f=L+6jV2ga@T?7H}juD+@Xvp8f zjXd!)TL79+LZFt-njQt9rjur=Ij^wNG8aP~&E|`_QZS0Th5yQRA*L-fKZQF$;K?Vs zDlh`-GS{_8>M2dl?u7*tGxz`Z1JP>9mlaqlPzr^hi!7_7#QheGVeS(2qm zsu~@Mu;?z`spR~;5HJS4JfdGT8y!z$%bgRfwCr|qV^@cP_Kjsr!;>0lgW^Dk+$qOC zz+?&;#aI-D7z@#lj-rjK;V52(9S$JHjw_P7+{wn*5Rel@SBcj$kl{qJES$#CUtqGs zKyjs@-SsFjW?4mV8q#bZqfYlKiyv=wRLOd{R(o@UtgzDJWQG z!$O!VP?Ume1e2e)I8DYa@+=@p#8->nyx$+;vxUcAPVfs8H5}`e>W)kJlgQt1vJ%fT`p&;^j%9F zCfb8t)QJm*#S@O?4!I$Lp@u}hlR+ShWnWPclc>XEh7oN#Q+7 z>pG(dUP(lO@Sx;6qN9T0LQXAYX2?a`(&#+X;wsj{@FX)SJ_&f&wlF9WCTE3bNd_j=M=%!>JTY#uCC zFAKUE0QW9QGN3sv$5UGh$B}HhLDSHUqU9LjJzp=e2ci_ZGZr#yPl61yv%N0M9zhO* z$a_4%A*69d&Y`_64c;3R&!PbXi65eJ(=0cU8~K*&R}LVBY}JqYaT~5ag{Xo-Fc*G(6WM zIi#Yb@>PMOHRgcz2|Q^ypw93)K4cOIR{x+CJNmH%MEo!vU4<3hrk_ixROecJS@2*jRBJ)}SenEJY(5oYsz>uO0TRwL z%VqH;!6$Lb=pPPl4hKBCw}&4Z3Np9i5G8%(dBN4uw8#e0b3lYmbv?g=CD zsyBca6+Q)O6c{N+u_A|DDqa>lykYCAv?c|n=cs%pi(Eh*B)qIhH;Q9~k3k$%ta?=? zUNT6iFS%Y#A6B`x{}?a1L-FWc5rUpQs;9{7j2>6ZM@#3nbT))Pk%tn*wb7)qR=BuPQHQXH0B^-8`=>sCmF& zGA*bx!Nxe|ME`;5tfGSbuuzGw9?Q9Jz^Df(s)QWfwP;7?F`LX|bF6|EsM(G0-cp!! zDO#mt1{)vH;XC?HJM^0e66!quj7U?@`3C&v12+OA;EPLL*2e0RMuh;Og^29{x!|u@ z=s<1$o8JciYDZNnj(1DQg$0{OiMk7W!a59}^q{uPLMsRlO~~=Zb#^J4RzKD#l4u^( z87FWd_xsWB_n2EA=;s367}49%1~$hWNAa>D*I}Gf7Qh?|J)N(0pQd1^+OhEC_*&E+ zVsNT03%IBIZsp^m6kHhs$8|i4ZY^c5;Xn#FNZi$(_yK{+*iU@8@ahl0W}dFvWC`a8 z6bRr5Q~*TQ*$hz#?Ad_*60w5^R!7n8DXLKbU2r_f9nrj78CHGs9ljglm00T<2x}1w z*K-;ff;@c?>_aBk_}HFt;)%s9TRgN>m99=8Oou-;I1=A;MGJ zP5RU0@_pi}}sEbmYgIy!Lk`5CTli|#sCYaRL(Eo4PKDyVg$dCqDDBzI!I z8R-I5sgBvregwaXo=O9VbccwHD?gDFRxj43AhZ8cUnu-3}x&mE?9s_ zH!0<4^u11_4x;NTwSm_wCgR2>k{8IoAWZ1aF+_we#ObpO&?f0{Uw8~;`o<8qugm8R zq7d`GG@}cF|7(UeFgOR5n{A4@0DpDV>-7w>Q!u-YEyBuX&KL4>%d2j9h(&b1MPVY1 zGV(dJAuwJh@9;nT30-io*ynx2JH_3c?Tq(jS(f@>#z4^>9R#ATl8s2N(N)3>%4~mU zih+290_O$h9$Y#R7?w;UeGN}}qL>m7j3wqoQ}VjcAru8+i8L2=BE~{g7#NmJz#Uph zhJo=Ic*L_ML#5q--wL`ASxzAmf&A|dpOqpJ=39JtPX!$m34(R=0AgFgr5bF`yw+r@ zy&K!OOf`@0K+{EIszVS~ zW5yue2!N#0Q4kXyLc?kY1DK2gTB_}gO1}>l8fpTDW*v_*qTas%|kv zkkJUVrqR*Z=B9l2%IbGcnbLOKlqpkIm_q+=8v5UIQ>LuH-IOV7qCeMPFy&YH^B;af zu;}~mzMrz(at`Q}6Vd<*WPYXNA2ZXp7!%+t6f?7_%}aZzvup&n~Ux_ z^$qn;SKm{9&+7y07;|=9ao0_Ed1kGKn;(7t{qv4}>bMhLJ7mV!7ybJA4{!bVo(q0n z{^p$zo%MF@6?c^%+O+TcjaRq6S9SQ$vsQlVl;x-2w)v?K{;BiZKke6Bwfm(X)LgUa z&)49y|v=ZL-uVMes9;S4}7Kk)=d|lca-(O19v?1(qy z&_ky^mAm+zKW?`Brs~SqefsnbBZr>$!{V#A?f+q)nfeMfx&Q1|{_x>XZ+XsY#pPf6 z+dp&fK)B_0P~hdGP5UPkMIf zj_am=d*aLQKDXn?YaO`D#~Y8XsEzdAefv)5?03t@_QA)#wcnbz-m~*H`yaZ(4OcvW z`Na=Dwnl#2_s(8-%Wb|%ENNS%y6TqKb05^-UAxhq$0)sq?>Et(QLedSlaHht7NViJ^-hyX=$Cr;gPB@t)JCZMyFX(|=AM z(6_j2mA?#hcicU%{fku#yMNnJ|6|YXPk!;MGfz8i;mSKbviA)yzw*NN=ApN5ck}hy zsk=SAYkJmo5B0tGMnh}+a>qV?`XM*|_TB3@s{Zc&n@`+io%av>+cxJ;+kWhC>(|d; zzU73L`)3+6_g!ttK2P?oH*)145{KS;P3qEHmiusnub#T6<)|kw+2oP`zIFPq7Tmev zrAOSj+>|@-u+J#}bo%PgJ$%){7ybLwwU-;%^pr&(P22LJN7n!6#+wg)ctIu40$L!{BZu7x4Cv~l9o%ZbCk9qgL zvvyNgJb88HvwIKUV#YpqzW46WyYBzWwS&97y4P`2uRia>#cQ9o=G~`#{J)P^ylnLF z_8DiNv+cIY{l1=e{Ti!0vfK|p4-dS2<*gUb`{2y=H@(_^wt30_{<8f^_S&mW|Kybu zpP9D%sxO}N;*0;v{n+#1F*Vi(zdwG}ir410HE#XR&wo6w{-#e)n6<_+FK@Z#rDLl- zcHT>ep4`6IyQ|)?@#cH)wB!9hztcYbSp9<=H{9}XmtE6){n4MUTe$wi8*lyf%xj;# zwDI=e-8^>P6V;iwt~+V&0lzCIp56A`nu}iBqyL)?wrl#&v)kUa@is?{d^j)BckdNz z{%+U1x|V)@L-px*Z}-k2FJAx7*)M62U)y)&R z=BazFz0z5kQ*Ucu{k0jV*FSh(|6Vs$FTalY@@-q4^xPH?{Q1H|@7ex0^?RRx!{QYO zUa3r8xm=U+(~^^iw;Ec0$?|vguQ@pXhv(OS^`+|$x$n`t539cZgKMt3eX~^ekC(1g zb5HMfYd(6=&%eL-fw`-nxLCQebLk5gcO*A>cj4@dXT7-cp@U1l+jNg}j(zN3tG0Z0 z+MY%G;M=xZ<^9wp+a7i7I{AOh-tCT^e>msUp`CyCM$7zZSA8&l?)6uFd(gRmxGDYh z@a-%7_sYZnw@T%a|5(o0`o_b*Iq-n}>aKdD@2|UGwapIAn_gtk?OlF@r7LVY?Um;~ zDJ(zr*zD#XtbI^%_SB94^h))tm$$y{y7Y60zpWJx`ps>RuXFLrBZuyK`_rxF&NI5d z-JoZk)4tHpUZ<~b-lY7es;?N&pmlWQ^SsL_inKHrPsdm)D>edUi3Qe9RkvE}tA7vt^)G{?EA{;$_4l(rp1NvN@917feX!HQM>jd;(79WmzI6J^J6-g^ z4o~P>S>x%qew41-vF|Kny>G6#f9|%QZ))~^3bV=pYht;9k;3N zOa67j4!`;K)IC=DaoU0>YHmFIp|0dE`4^6O@Xg~MeE+=kKX=*mh`|?^|LVW5{ki$` zmma(Bpt`%?9^K~A6CZhPqtQd2e&dL%|9Ibrug*!FzwUV#y#3sg;+;)z+OxL#%dw*k zCocER&FkE>$sK=vdHpGecYZeT<4X5*^mk_Gyl~^|gS%C~Q=OSJc*9%U@3!)z8?JrJ zH&>ih@zdV_n)=ScEn7Xa>EE7z=-uUh{&B@KA6)s3d&j06Q1!*(Z`MtF^`1FLAF*fh zp$~R#JYdG&7cJhr>Flj8*nhPnH_)$o^~9%}H=q4{;}5&N|Lhy(J6!i!YDeSfvtMst ze_?U`CFfkQQOg!v95v;TcQ?Fs##P51v%)`eM+}^K=@rW2>i^v~Lv6|3aM7dBtn#IDF0?$4%E>sJ0#v1#2GwN(#4 zCA;>v1No88{SSQQuc@+~r?0;DpPJ`iQ!#qk=pC&eZ+F?Zdd+$_ZTS5DS8tZuwfU~6 z-~PJ!xTSON$-RE#RSO4qyyLz5zx!{+?1T3m-2H+xA2~k%erDSD`#!V#jH@bF{M&W= z{QCHXudTTJ)WvmIzp$Y7)W?4H=q4+FyCl{0NcSoYdp*1V@EXHS)i+nZzGB0|TMyb| z(Zg51dEQ~4KXBJh+i8m$);?*`{5PMwBl3sUW%TX&e zKDxmNAMEtmP%{1Yk>9Md%e7TU-*&4$|JWV&+xM)c+rIGJTYtIiraR3=b@yB~f9x+C z{pZ->HxK^xhkw24^{3DN=IE!7-tFbrSGsR>`k{+YJo)A2R^MjHhmY^F__~*N-cykT9+3;O|htiSeyrnRsA`}LoFyW!+_&TQGKZ}(~ceq@ak zUR>!GdxL44ZTanE=1WT7vxhx*M*8NuXS*&wsq<=U{?a$5zB@-fsBML@o!?z9SG~n@ z*BrUeZ8sh`>ye$Sb~(|S{>YvS>({(<#gY1lU;X^17e8)&;oSKht1kIrtvzr3bc@69 z-*A%!&;54Epe)x_{pCti9(e5Axu1S}MPJ`3_DzY!=Y8IMYsc4zJpD|r^5{g< zCa0@EUv~S$ucn&kOn=en`g-4w&-r~*)4y+d>%gt%p8MUtRoEvvK_4ehKJ7B}#T|0QpjM*0)zxx(Hyms;zPyTe&u|MAX`GL3W zv#@RXcYd$jS97(#?#ol=E;#3~miI3?dhEy@@4NquGq+P$JR-Hi{B3`HsBzO*hAW;~ z^xgxfe|puI#%6EdeaIR=pVL}>f5%39t$AVj1&1E`#3rwvF#W7AZ~M&#mv4G*;(({- zW>@?Bo@+i`xZ#ec{!zK+7vJCZ-sOM4>dR#7SC8zl(iW?({+GGuukp^h^Sl21?e7;q zka+jx*MDDCam=Yp_q*!fm(D2L<@<*(xhT8vitE;@I$-r{&h9yKzuGO2ee=Pex1Igm zew(j(#!9)D%0GDeR~`1bXCK=9^H)1A*yPQl-dXuKefJ%+#%?brl%L+-aoY>8|K#EG z51M!3*EKsneCJz-op!`2H+(;Ty~nyQJ$c9afn9#L#`e!V*wDGr`Ijx(|%*{mCcq zzhe8@+wS>%oAtrQ&s==VW{ry%>c_md@=BlFe%)(Y@4B@upT4<@z52aR?t6dN77Mmo z(v+$>6-{+3Pt!sUL z@a`MFu-@QlQ@;7{@t@we^$z!RueKUw+6;jO>_cD>Cun(@|w$2@S% zOV2*?bIX;pyIz0f-$&eQPSZC2-REb0_4%9)wz}y~rFXAKhwfLt_|vx2F8I$Mzuv3t zgIWLG?30(z-tDeiru=l*zTbWGW9KW+?sDw&|M~ix^^RLBz47YXT)XbHe&ew}eD~Dl zGap@j#>_w6clQo&b{%`%DsyI>^7ctvT`_IVR~s|)k9qWl6+V9}yZ;(fHhH9D>Dw>g z`SB(1UpBkv*L%FM?kC6S_r7x0PJjP$USi3He=Xeg^A_L!cJX@phYP*biJIy@5x3T-5ht$oyKfT@J{`77S zb|3T2XJ>!9R&Jk$x`7pbxc&A|-@5U;J7=x2|LnW_uU@IjIUU_2cUADV(#)^9{8dVc- zEZyX$E6e`(%BeT+blAGDJ=(cs%CEn;>dtT8IPBoXyUzT+YV-7S`tJJDH&^I5dFOf6 z&)xO#{mpk@zW${Omi=9vxVIaE~umJAVH?zdZ2E7p|E$Z|#?^+wr%? zXNSz6@>EOb?fI%xSNLr9&BMp9xZ2{%|F6Bb431+<+6L8PW(Hf#&|;P>W@cFo7K0^O z%nTMYGcz-@WHB>Z7Bl0@bMMS|XJU5W-9P*7M%;|3=*sNOs_d-Hr}CWWILF<@@z>n& zt<=YDj*56xL%do0Ru`DxEI%06wenNkuswuHM4@%`6(!%Km96P)JA$+!XamLw zf`~7#ON3Fc%QMdwEq=?Bfv7bEOC+p!MB}m(s__kF?j9*g3pJ;pel6EG9#6Sr1jFBJ zZprs8P%Tk9J}p7NWp9&s2BzHL@rWqC|Lfq|whsOn!e;;@;ki}w#K+-r_AB8!Zfh78Q z)w!SHp$LlxBWBf7aJ9X_5YNC4L!JG_mN?a2iEnSHoes>C~OR^6eF;JA<9 z>MjsQwq?-ge*DOr~>msWlDGkRRV;`RYNnNngj2b%m%v?Qwql*K=wH2&^yuiFh zm({_6X_{ocrh<7o@0_8=_7!YOt%e!&Uaht}>a56;7)4vS8dFKHYacUVHcY>j&1pv? zge81mMMMJxC<$f*2S8pRLxvV@Q`Uz)V8N|olev)ESgX!kiAuege1=o_I$7qRj7iy_ zl$$2bKXaU`w2U)}c@lI%5TEqfVzu5rw|s4<%eBfq-mReY0y0r|4sJ|!jDq}O^J`yV znX2Mm^RO(ABPQ%IgysDMHT0UI^;qqCoJQ5*&n6rP$? z!|?A=I~uCn?WUio2{Cm^8ISRH2O>0tSuycsAu^a)a6e=d>x353r`O=Z3e^AXEe(0D z6yrpvEBbCRkb5=8unpDclrCPS5`i`x(aI!>anN4AK0uMmlqtv*zR;_!pxbgJQ~zuO za1@xu87BJ5MrQlLs`0|G3$Am{D414mwsS@K-~$`De8AV!GS=jL%uF>6mMjt(is>3pKd#Ji<2(Ke4 zF_(#votrEv`-Fgpz&VyC5r#Tl$=%PQIQfd3oa;2GjDC!Yj3c|i*=m${;vXqF6gSol z?5w;j+u129ZUOG9&du`i93rfDE2UTTWTV)C691lh$Uk zy(XB%NpR;29iiTnYJ==$0hPU-31)aBrJ#Fure{A2!zBC-eo%C+GveFFc0@RW0A`4% zHI5d8Re=KR(MtJ-u4yrT?S!_$D7u0i4`81U8 zB+_#Fil}+Jzm>T+)nxqKz`~WH5;}VVuN5R{Z`~YzV{xce3Y}iE#o6{v_n*oFlecr& z&Bn9n0r4`3%-=t`E>V`j+~k86BgiBeVAz^LCwhXGsxzCklfor9?P8O z_C}Kw&Qup!=DOf5lx`5R87~FHFdrbNr9aP1{3J98ab15Pw|-Jgl>m8A-OOBNWCLxhle@U+P@y z5}lE-T1f01i+GK3&!JE#g*h!ZjuCW22x`Jw8%ARb#iID(C|2}1fOs!uD5dh0=OHMS zZAYPBavNhL?YFlN><$@fLle0S#ct>!u1nLpg!Q0p5@-_z&7r8m67qWA_1xUTIWE0< z;7}D=C(>=|e3D$?F8UGHDRV2POF2o3iV9p%*0Lx4kz_>C6IpCTOi$426G5#}L^*e@ z&-~Fe_Su7&P7S+e9O|n`$=>>eFS)-4wMU|>nUJM=<=+kxL035g4BeOj1A$_)d;%yh z7p6V1Z^;OPE;SvYpJ=Qx_ptlfHY3a%+|^&?9ieQnRP@cn(wB*PS1H&fsd>-JZQZ{0 zS#(GF)V2(mbsj|`@s7r_5tl()CkXJof&R#>QhKx1O1+OrikIkKtJX+F1%+`iEcG&} z{`qykYMz*c$BBaOP13Bm%jeoq4WBxwo#~N@1!>t=I1Vr2 ze8}1B(17c#IsC*KI)Qj+E?vEAn`hGIZuYDdVcF zWbLY=Hoj6X-S{q#-5QuGyA(pI2|Gv)3LNm6r4fa7ruij&AWa4h?P<|Sp|?Q2IMaaD zyd-BNk!l6c?sn-J_&p$`cZ8qj0Y5JG&uTik;x_;O3!2F|-j7WVV&eA+h(!-b(`d++c>xl8H~&E_hSI zD44(!>RL&M*|ec)UQVNYs@Els=AwTI4j>OJ#L*rL3WnkXGF-?S0#1ux13fSp{fCCD zRld__2nR3{?@*R!)ivPtH6Vb7Gk`%0*$dEEHstkk!*i)@uH**dkAK0**GCep4=d2c zeXQr2m6EZ*U+P|?FtZHn&+ESEOs$HpZ#SU&FWH z(n_0F>0%%`VZ*O{WBgiACysNsCwlN~gxU3o3-;*UV_1QfAZ<$P@OkPHeGX?I6iTk> z5vBgDlt?U(Ox?P^FD=(>;~l3umdfdEBVwv#BAxNikcq#ee%Rk7&F4YoN!_XGsBT3f1 zPXVfEEnuV0Rp4pGK#X@xd~XGr?xsS7rDd4eZ8{hL!7Pb?IqCv9$GX}oIp5wb*@Fw6>B$)2 z(4=Z*IjpjhD+f)u1rL$I#X2K{M=g)#lKBvR%GVPTQc%?IZt*DX=bl?S;1lN{SLp#GLSC-r=2UHyv6Tw=N1JfNt zQ$%rLF^^x5=8rPj@~Y~AU;U8XY~T;}MCLJg4W6bGKP+m6VX@Y<=cs;Q3vxM`2mQ=c zOLGu{G*AkY*{vmw%7O3nO*`RM_xrfONU>9fTSsQq!OEBPz-D%Ed#{yR$EDVo$u*_# zwVU7iDVYj>^~pu(;3rww5N~M@@_bbm*fU&qK~B@D&wolL_%31(K@^*p(Gs!Mx)5J4 zEi71ar8`VfLkXH_ZsA)7PY1JHAG)GT)fA@3@qnZR2rzgpUiCY6_D_uE&d0>RN9M&w z{UF24iuf}Om!q0f{^Vn9+qg%Be<19_Q&8Gr%;zx5Lbs)nqNFgItHJLUNV-Dd%zjON z#SysVAM+%Bo(IvmETB(VRF?$q(py)z8PS>B#V1fR^PsUpAUt$y34$5{I9#K?jH2DqfEhJJ<$(NNbLa1JZ(WWNx$LIqAW}=D)lzv2544vL?p|?SF=x z#C^t;`%WnoWwzXO>paB}$5Ory@x)0U`^?vd{!Ilv55kYY>=` z>*>a2X=|@Bi=JFMwK>5A_Z;+L8)X?QN8HpdMI%xSds*26Zz;WZd4dRkBHjY@suE>G ziXbz*qN&G3mX-sb`9^ijbT=oYy+SW|=1L)G73}Qh3nvkn-H5uhFWf2Q0y%4g*zzO4 z=dn_WWcbXU7qN*^F>t88Srywt0$oihKC&Wo748 zWc`RZZreZ7r4}?Jpc68`=M)_)gqSs?X2PF)lp)JBiXX-t*M2lw|Mc@mb+)6@OcU-> zZt^Mw=8*I@Bs+XKwFi5L6(nv88FG4^PrGJ8 z;)Gqmwa?UiFSzP6xSPoQM5w_D9olrC)_=ibomvcdClZzS03L`h6y+?0WpN6g%xaE^ zY}!!}E*8JcXre1uylwPhM<;rAlkS_>a^LPHGD#5!8+;(VyGNH}yoeA(=n^Ge(Nz*I zxU=i8H*nPhhpr1M{^nG;_oLCX`_r#aBIcrQDnybnYTR2BW9)FxAYiAHXwx&e3*^EB z!yKeZ1eY&9xwq~8Z9D}?S#aTpOLW8NQD#nc#iI`TG;tN*dS5bwe)Qyhtui*Q$K$uh zwqc2r7dL(iz;wv9ymDY*QdpoH3h7$_e_9RzZJ~R47+|slS9nf&!dW`2R6E}H`r#qjD-3G=On9bN=Yd%fJ6O%KQn>OMy>*z=xk+@_ zKGWayMs5^0%jNmfuBBvE2Y4nLvy*rzE+lFdm(;PqRhBMMzSz|jklJebOnZ`w`)ev8 zuL9n?AES)@2?CXLV%|C*(Wj#vsC|qtrlzZx36iq)?Bjw<+MWHX!Y>%$TKWW*!c`x$ z6t5rWeda2Ug-B1Lr23%dL~e4P2XfF*Y8%yfq!ky`AN34LlM=Brm-6_6dooqruE&sL zI7}l9+9~7Py{U~?zxo}8e@>yR$zy2Ay=yTVWp6c_AIN#dR=*P%i5k|FM_{>(sea6IW1gC7Detb5L}EA88sr+}z?L6nTYT z$`!>mpR~g%ob4BwDa&97A{goQI3H|RT(S65iuLpAPn7gg!Vs(Cw!}d?#QlBCFdp8r zi`C~cPHxNwWlfP;!C&2@*d;(!X!?1_Nze^!WvXgnE>YrQDMcGUupl1e%cj&%ppT8O zr+V>HTXh=gU^crQLjKd33rzhrS+|sViiI_w+!x6DsYjoKLKw>2W7~B$QH7cmaj3 zv8InA?x?j;vZ_&zETGFcBPf)gFuh67U)LU1cD$$#u7EyYz}!ncl+Bl)Fc_*#>vbE& z7QD1BsSYf)eYq(J2nu181)I`b=?v-#`1TYaaf_6-o}90!?q8POnIl}w$|krC(c(`o zoGf*@;OjFw&NM&qQ;G*bR1>>%zgm(* z)04e~WppqWhlEcAv|Kavfi8mkVx=I>*ajz;XXFXJ=}b6-ZU#d9T!-rK>13Otx3U)_ z7izr!nlAH}g++51R}aS7w^lmCYO2^ePQX>(<&3EF6FI?pn&U0^W2p=mGks#a1=Vq( zCa6E0e(939vtlNE!!5Z4-zhzn){50tlW{S$lx(Q%)|r=%cv(;f1gKK-qtE&t$kB5l1m4*Fzwbw(ZTu%1DAx zgHMS~^TVgeT7n1etCcYy(XLn|+=$$`{=h>wFIt#9;wJ zFVc=RmGN7NRj0jCBjYyn&#KA66eShb;k@z8>KLrJHQh1NcMTA#`%zjc^oYMGsHJdk zf#QhZL@0Jaw5Z0@jbfoNx-+^KY8{xC6FIBah7?cHfA_t}&w~a1$kTi{e0s zg)Yx5k`2@r-TiwRjqU*S(lbe6LlT(ifK(CvFTeVig|Zy2So|pHx45Rm@p4V~yNur) z?6&tx$G=ETH723mi(6QZJjpO&wTHjL=3tRU7|aU#NIH93IMrWU$SyQZ*je0i8gaUpXiorL`rh&Q2wRfw1+gUqCp=mHU(yIif}M0 z%*c$**(6(m(Z!%rU^)+8@=-4-mrSI;#!|^1yno0ZogLvfHUZj~Oe2b~C7-eaSZIPe zo*@?btLPtgQ4R*xWTt03>Os!)F977Yq1rlD9v;xF9bT~kv$K~-tV8D&pj4d0YtqcH zC+t$2i!k6Kj5(6K3}6rIbOLmZHYf*)0)=K-BK=J5>(MMWhk{S0amiB#jkTSjPgy&V zUU9jL@{98rnwA;&6p*R(Zu~3V2`+6!iQ_)2F=Ao24&T;!@dmx28U+nbK6kWdmx}Ge zGWudfiX_3pJXgrb&*P&=VR$1II(Fym4o-8anjmG{!x@vVYt;K&(M^68C&Hrg4a{-9 zL28zxk{Vk6#u(zx#i;*fYp?IYHCEVw?EM{5#z2gSAX#aZr$_E53rz7SP~(v^1=(J7 zNaZ7Vu;4FJtcr>ADzK^|YkdK0N3CThUFFxfRU$DQO&zHgE;X>1w2MHq+5|Qv@g?54 zwKbY+VH(%`iifpY#5x=}mniOCq0L98HH2dq&OK>+*-FBZ2=`-AJ0er@-=)= zJ$Dm4^TTRVgGc+KHFAIa2en4i*_cdc6&AMq5G)s(3RJ&K$_*@YpXiD`!&(#*85wwI zF|&~tWc1E(KuNo(zXJ4WCl3gu{YpuLiFx;{$r**g@(NjWWoV`{3s{PC$LSqcn9oQf zp~hz=aF!0`Q&(ga59oc42ou!fhxICErXO&Phx@!@^?hYd2!(!Rn++}ml^5uyuEn6B zVXVw0cO8rK0F!3#<%hYCto?@Uc4y=>Zim5*2zl)Y3!QKY)VXyEOJE|g?3`oA?F)jqpb)@1MgNa161io zp(ps29Q9H<(^CCBqidJ-+b!(#%H$miUS(vLSc!#kmQt4{x^oR6E(*rJ^Ep;NskFPx z*C948_X#>XEYWWT?*f-Q#`UF)=;3H9Yc?j*R?E4PgMYUO}PkJ#`p zPdD4a_$BeSASEvtxE5yct3qd~J0XkwgQ6M&l0jBMurNX2#6nrssIi%2kee#cc|e>tBQgZW9rMoWokI;m(8+whOj-~-duw{AL#l8uegwhS+!&eq{ECBv@6O!*gcMjoLcvp|bigH2 zr9jACkZyJ&NFl(YhgvFLla|~VT7VM)y^mt#NYWuphh%|Xm`WEctaQWmm4wc0=GKp( zjb?=Xcv;)7v*#yvthwX`Rw`#8F2aq9iKs630nUfh8)$PCAIshc!6v`5B$^Vu7Aaej z1i^k!{!%M$K;EsWo4;C`t?xQE)*!)5U>!gF7XXvf9r!mZvPovtc!vj`48-gzHMDBN zgwnhU8b(SgL*yH))wzN7=6)9Bk*4Mw;zZYFf5Kwex@^KA!tyFeYmal+T{h*OW>{#D zJR&JFLdx5?tIUq9bfOhP19zFrD zP#8#*Kjm>7l8_m2pL%=Of1qc*_4wz0x(nwl)tjvIBY zSPz$4o?1pMQ7Mp9jH?8vtm{Km>>!8Cb^9pbeNF>Hl6+y^W7PYT>$O;ipJBYAOOg9a zz7c5)@oEii5i1f8YAhCovq>O~LBTfxpa|I+myzV7(TCS@Txx??K6Trz)Ud)vXhrd{ zGQ00yAi=WPsB4v(`up-Q=}d>7LBwaT}&J#nZLd3nQh!xp)9JmF96q*H$n$>6R%hf4Men zID0d=p(U}YXHC+q;8?l0!MWZ%W^VEHrVDYsl`iVcs(fNL6TN%gtlI(iskm@5A_8YB zi<1s9r-wb7MFK`7kM9kXmv)UJ2vAUe_x=W}$GjWxsj z#o)KP?Rj5KQj^iTFgwibE2*D*>Yq*Qh7F~JM4+INHWWSN9+;q_ji=08iL__=l9NB- zRr@woiU>o0M(wB6H3SiinL|*5`LtQ@l^Za?czgPSHCYmJWB9{43Lme*z_;(|ehj|uQ8&C4Cc*P8jfZKUAzzRb zBAE}S-{2ItQ`_T~PGym0NXr5{V*QJ>kMadL`(WdGv1n5UqAC_(*UQcHS}kN__VBvb zVpXdaHZbKZ>yQ_Tg6mwt`E(yi7A?T2G9d}R36&_MNlN&sy$<4A)DOgZEi#h$PDzk0 zZevKD*(dN6qEezviCPJI?NBoh%*&Vhl%qmgo0QUdf#}f!*I+3hK_#pmJSD8B(Kg&3 z3?qS?9If!tx%r>39VTbRRFIz!Vl^b=;Tk|{a!#Vd4*O)-TH}QWYU2|H2*U{<9h=p0 z$oCiV9-SCNP8I>V~hra zkzAmLHJOQ{t-BvxJfE?KF~nIovS*^ZX4df0E~7BSvf|!C(M=gOR*ZU-QsyOoxy6;s z?3QIpWa<4G9~b+CBpJpW{!`?EK9C(b7B%_#4wYez9x9AGC`}~nLNPjHtQHIMyKC+8P3TQF3raIjXJCL%`BNWe$ zEk!xG^kr*(1zD7KKckR(>GM@nkx9%kwku@SSEA17n86s?*c!5BOD zzKxE5%F((ln9gIT7qv3iaBUB<9dfM2DsM8v>py|btTW7=T5&eup0U~6Y$Z*2yJ%(`Hf5hbsvT<&%0A7~II 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�MM67zfM)6 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

    F~0=yPO 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 z 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 %0g;PWBb>SP6=HXp?Hz2+FE16!j62 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¨f;ZI+M*;h-f{g>c>y(jnZn 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

    MV>6$;fS=&-$@+m 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ᰡWB%O`+Uyv0M_Yh}H#Zi4J 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

    3MX|7KqI8Woot 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

    {+z4IA;!7f3! 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�tFIDx*=@Uz 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%0D55OqUACi9XcZYv!!tNZwi}gU3xifbg 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

    -$CY)13WsB|ueG+35-h2&AF2ChiK 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 z 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 z¥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%0AW=8$_r_Y>rUZ&aR4evhNA8!y=h;2G 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

    9|ukZ2%h} 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