Skip to content

Added You.i Engine Support #429

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
94992de
US-3382 Added three required classes and a rough testclass
pfoster-youitv Jun 3, 2016
fa2fc4d
Fixed PR comments
simongranger Jul 15, 2016
5704b91
Merge pull request #15 from simongranger/PrComments
simongranger Jul 19, 2016
57b252b
Fixed style issues
simongranger Jul 19, 2016
3b08dd2
Merge pull request #18 from simongranger/PrComments
simongranger Jul 19, 2016
643f733
Updated SanityTest.java now that backgrounding works
pfoster-youitv Jul 20, 2016
e5cecd4
Merge pull request #19 from pfoster-youitv/backgroundTest
pfoster-youitv Jul 20, 2016
c90e343
Addressed codacy-bot comments
simongranger Jul 20, 2016
e008a90
Merge pull request #20 from simongranger/PrComments
simongranger Jul 20, 2016
bbd26e3
Added frames classes to represent the app and contain interaction met…
pfoster-youitv Jul 22, 2016
64ab870
Merge pull request #22 from pfoster-youitv/newTests
pfoster-youitv Jul 28, 2016
5748bec
US-3498 Adding test code for the isDisplayed feature
HeloiseRD Jul 11, 2016
453f327
US-3415 Added Test to exercise the 'clear' function of the You.i Engi…
Jul 8, 2016
0a4ea41
Add test code for sending delete and backspace keys
jplandry Jul 20, 2016
d7be0f0
Moved test methods from SampleTest to SanityTest
pfoster-youitv Jul 28, 2016
1ec51d7
Merge pull request #24 from pfoster-youitv/develop
pfoster-youitv Jul 29, 2016
df1eefa
Moved tests for Size and Location into SanityTest
pfoster-youitv Jul 29, 2016
7a8523d
Merge pull request #25 from pfoster-youitv/sizeAndLocationTests
pfoster-youitv Jul 29, 2016
a65ba01
Adding Codacy Badge
SrinivasanTarget Jun 30, 2016
b1dcc34
Use weaker interface HasIdentity instead of class RemoteWebElement
asolntsev Jul 1, 2016
ba00475
Update README.md
TikhomirovSergey Jul 1, 2016
22a0f9e
#242 fix: API was completely designed and implemented
TikhomirovSergey Jul 3, 2016
62c733d
#242 fix: some fixes of API implementation. Preparation for the testing.
TikhomirovSergey Jul 3, 2016
24c0d66
#242 fix: The general test and bug fixes
TikhomirovSergey Jul 4, 2016
933cdb9
#242 fix: The test of compatibility with WebDriverEventListener & bug…
TikhomirovSergey Jul 5, 2016
b6f9177
#242 fix: Everything was finished
TikhomirovSergey Jul 10, 2016
379f081
#242 fix: The new WIKI chapter
TikhomirovSergey Jul 11, 2016
0282b46
#242 fix: Working out issues which were found by codecy.
TikhomirovSergey Jul 15, 2016
76e9252
#242 fix: The potential bug was fixed.
TikhomirovSergey Jul 15, 2016
84edca0
The setValue method was moved to MobileElement.
TikhomirovSergey Jul 16, 2016
d99f18c
The complete #215 fix and addition to #403
TikhomirovSergey Jul 16, 2016
7f8dd22
Update README.md
TikhomirovSergey Jul 18, 2016
6bb04b6
Update README.md
TikhomirovSergey Jul 19, 2016
7fb10f9
Mobile OS-specific command helpers. Source code refactoring
TikhomirovSergey Jul 24, 2016
ac72d01
Delete command was moved to the MobileCommand
TikhomirovSergey Jul 25, 2016
b18f15e
Javadocs were added
TikhomirovSergey Jul 26, 2016
54ebe93
Checkstyle issue were got fixed
TikhomirovSergey Jul 27, 2016
6b70603
Issues which had been detected by codecy were got fixed
TikhomirovSergey Jul 28, 2016
43702dd
Update README.md
TikhomirovSergey Jul 29, 2016
d979c08
Updated YouiEngineDriver to use CommandExecutor
pfoster-youitv Jul 29, 2016
7124711
Merge pull request #26 from pfoster-youitv/commandExecutorChanges
pfoster-youitv Aug 2, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +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)
[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/io.appium/java-client/badge.svg)](http://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)

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)

Expand Down Expand Up @@ -82,7 +83,14 @@ You can get it on [WIKI](https://github.com/appium/java-client/wiki)
- `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 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.1.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)

*4.0.0*
- all code marked `@Deprecated` was removed. Java client won't support old servers (v<1.5.0)
Expand Down
125 changes: 125 additions & 0 deletions docs/The-event_firing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
since 4.1.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](http://seleniumworks.blogspot.ru/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://projects.spring.io/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<Listener> 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

```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 {
...
}
```
14 changes: 13 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.0</version>
<version>2.53.1</version>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
Expand Down Expand Up @@ -69,6 +69,18 @@
<artifactId>cglib-nodep</artifactId>
<version>3.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
<scope>compile</scope>
</dependency>
</dependencies>
<packaging>jar</packaging>
<name>java-client</name>
Expand Down
49 changes: 7 additions & 42 deletions src/main/java/io/appium/java_client/AppiumDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,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.SET_SETTINGS;
import static io.appium.java_client.MobileCommand.prepareArguments;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
Expand All @@ -46,7 +47,6 @@
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;

import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.Dimension;
Expand All @@ -57,7 +57,6 @@
import org.openqa.selenium.WebElement;
import org.openqa.selenium.html5.Location;

import org.openqa.selenium.remote.CommandInfo;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.DriverCommand;
import org.openqa.selenium.remote.ErrorHandler;
Expand All @@ -67,7 +66,6 @@
import org.openqa.selenium.remote.Response;
import org.openqa.selenium.remote.html5.RemoteLocationContext;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpMethod;
import org.openqa.selenium.remote.internal.JsonToWebElementConverter;

import java.lang.reflect.Constructor;
Expand Down Expand Up @@ -189,39 +187,6 @@ protected static Capabilities substituteMobilePlatform(Capabilities originalCapa
return dc;
}

/**
* @param param is a parameter name.
* @param value is the parameter value.
* @return built {@link ImmutableMap}.
*/
protected static ImmutableMap<String, Object> getCommandImmutableMap(String param,
Object value) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put(param, value);
return builder.build();
}

/**
* @param params is the array with parameter names.
* @param values is the array with parameter values.
* @return built {@link ImmutableMap}.
*/
protected static ImmutableMap<String, Object> getCommandImmutableMap(String[] params,
Object[] values) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
for (int i = 0; i < params.length; i++) {
if (!StringUtils.isBlank(params[i]) && (values[i] != null)) {
builder.put(params[i], values[i]);
}
}
return builder.build();
}

@SuppressWarnings("unused")
private static CommandInfo deleteC(String url) {
return new CommandInfo(url, HttpMethod.DELETE);
}

@Override public List<T> findElements(By by) {
return super.findElements(by);
}
Expand Down Expand Up @@ -572,7 +537,7 @@ public JsonObject getSettings() {
* @param settings Map of setting keys and values.
*/
private void setSettings(ImmutableMap<?, ?> settings) {
execute(SET_SETTINGS, getCommandImmutableMap("settings", settings));
execute(SET_SETTINGS, prepareArguments("settings", settings));
}

/**
Expand All @@ -584,7 +549,7 @@ private void setSettings(ImmutableMap<?, ?> settings) {
* @param value value of the setting.
*/
protected void setSetting(AppiumSetting setting, Object value) {
setSettings(getCommandImmutableMap(setting.toString(), value));
setSettings(prepareArguments(setting.toString(), value));
}

@Override public WebDriver context(String name) {
Expand Down Expand Up @@ -654,7 +619,7 @@ protected void setSetting(AppiumSetting setting, Object value) {
* @see HasAppStrings#getAppStringMap(String).
*/
@Override public Map<String, String> getAppStringMap(String language) {
Response response = execute(GET_STRINGS, getCommandImmutableMap("language", language));
Response response = execute(GET_STRINGS, prepareArguments("language", language));
return (Map<String, String>) response.getValue();
}

Expand All @@ -667,7 +632,7 @@ protected void setSetting(AppiumSetting setting, Object value) {
@Override public Map<String, String> getAppStringMap(String language, String stringFile) {
String[] parameters = new String[] {"language", "stringFile"};
Object[] values = new Object[] {language, stringFile};
Response response = execute(GET_STRINGS, getCommandImmutableMap(parameters, values));
Response response = execute(GET_STRINGS, prepareArguments(parameters, values));
return (Map<String, String>) response.getValue();
}

Expand All @@ -689,8 +654,8 @@ public URL getRemoteAddress() {
* @return a map with values that hold session details.
*
*/
public Map<String, String> getSessionDetails() {
public Map<String, Object> getSessionDetails() {
Response response = execute(GET_SESSION);
return (Map<String, String>) response.getValue();
return (Map<String, Object>) response.getValue();
}
}
41 changes: 41 additions & 0 deletions src/main/java/io/appium/java_client/CommandExecutionHelper.java
Original file line number Diff line number Diff line change
@@ -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;

import org.openqa.selenium.remote.Response;

import java.util.Map;

public final class CommandExecutionHelper {

public static <T extends Object> T execute(MobileElement element,
Map.Entry<String, Map<String, ?>> keyValuePair) {
return handleResponse(element.execute(keyValuePair.getKey(), keyValuePair.getValue()));
}

public static <T extends Object> T execute(MobileDriver driver,
Map.Entry<String, Map<String, ?>> keyValuePair) {
return handleResponse(driver.execute(keyValuePair.getKey(), keyValuePair.getValue()));
}

private static <T extends Object> T handleResponse(Response responce) {
if (responce != null) {
return (T) responce.getValue();
}
return null;
}
}
Loading