Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ This is the Java language binding for writing Appium Tests, conforms to [Mobile
##Changelog##
*5.0.0 (under construction yet)*

**[BUG FIX]**:Issue report: [#549](https://github.com/appium/java-client/issues/549). Fix: [#551](https://github.com/appium/java-client/pull/551)
- **[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)

*5.0.0-BETA1*
- **[MAJOR ENHANCEMENT]**: Migration to Java 8. Epic: [#399](https://github.com/appium/java-client/issues/399)
Expand Down
4 changes: 2 additions & 2 deletions docs/Installing-the-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Add the following to pom.xml:
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>${version.you.require}</version>
<scope>test</test>
<scope>test</scope>
</dependency>
```

Expand All @@ -40,7 +40,7 @@ If it is necessary to change the version of Selenium then you can configure pom.
</dependency>
```

#Gardle
#Gradle

Add the following to build.gradle:

Expand Down
55 changes: 53 additions & 2 deletions src/main/java/io/appium/java_client/AppiumDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
package io.appium.java_client;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME;
import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME;
import static java.util.Optional.ofNullable;

import com.google.common.collect.ImmutableMap;

Expand Down Expand Up @@ -71,6 +74,10 @@ public class AppiumDriver<T extends WebElement>
private URL remoteAddress;
private RemoteLocationContext locationContext;
private ExecuteMethod executeMethod;
private final String platformName;
private final String automationName;
private String currentContext;


/**
* @param executor is an instance of {@link org.openqa.selenium.remote.HttpCommandExecutor}
Expand All @@ -85,7 +92,35 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) {
locationContext = new RemoteLocationContext(executeMethod);
super.setErrorHandler(errorHandler);
this.remoteAddress = executor.getAddressOfRemoteServer();
this.setElementConverter(new JsonToMobileElementConverter(this, getSessionDetails()));
final AppiumDriver<?> driver = this;

HasSessionDetails hasSessionDetails = new HasSessionDetails() {
@Override
public Response execute(String driverCommand, Map<String, ?> parameters) {
return driver.execute(driverCommand, parameters);
}

@Override
public Response execute(String driverCommand) {
return driver.execute(driverCommand);
}
};

Object capabilityPlatform1 = getCapabilities().getCapability(PLATFORM_NAME);
Object capabilityAutomation1 = getCapabilities().getCapability(AUTOMATION_NAME);

Object capabilityPlatform2 = capabilities.getCapability(PLATFORM_NAME);
Object capabilityAutomation2 = capabilities.getCapability(AUTOMATION_NAME);

platformName = ofNullable(ofNullable(hasSessionDetails.getPlatformName())
.orElse(capabilityPlatform1 != null ? String.valueOf(capabilityPlatform1) : null))
.orElse(capabilityPlatform2 != null ? String.valueOf(capabilityPlatform2) : null);
automationName = ofNullable(ofNullable(hasSessionDetails.getAutomationName())
.orElse(capabilityAutomation1 != null ? String.valueOf(capabilityAutomation1) : null))
.orElse(capabilityAutomation2 != null ? String.valueOf(capabilityAutomation2) : null);

this.setElementConverter(new JsonToMobileElementConverter(this, this));
currentContext = getContext();
}

public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities) {
Expand Down Expand Up @@ -137,7 +172,7 @@ public AppiumDriver(Capabilities desiredCapabilities) {
protected static Capabilities substituteMobilePlatform(Capabilities originalCapabilities,
String newPlatform) {
DesiredCapabilities dc = new DesiredCapabilities(originalCapabilities);
dc.setCapability(MobileCapabilityType.PLATFORM_NAME, newPlatform);
dc.setCapability(PLATFORM_NAME, newPlatform);
return dc;
}

Expand Down Expand Up @@ -317,6 +352,7 @@ public void zoom(int x, int y) {
@Override public WebDriver context(String name) {
checkNotNull(name, "Must supply a context name");
execute(DriverCommand.SWITCH_TO_CONTEXT, ImmutableMap.of("name", name));
currentContext = name;
return this;
}

Expand Down Expand Up @@ -384,4 +420,19 @@ public void zoom(int x, int y) {
public URL getRemoteAddress() {
return remoteAddress;
}

@Override public String getPlatformName() {
return platformName;
}

@Override public String getAutomationName() {
return automationName;
}

@Override public boolean isBrowser() {
if (super.isBrowser()) {
return true;
}
return !currentContext.toLowerCase().contains("NATIVE_APP".toLowerCase());
}
}
20 changes: 20 additions & 0 deletions src/main/java/io/appium/java_client/HasSessionDetails.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.appium.java_client;

import static io.appium.java_client.MobileCommand.GET_SESSION;
import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.isBlank;

import com.google.common.collect.ImmutableMap;

Expand All @@ -39,4 +41,22 @@ default Map<String, Object> getSessionDetails() {
default Object getSessionDetail(String detail) {
return getSessionDetails().get(detail);
}

default String getPlatformName() {
Object platformName = getSessionDetail("platformName");
return ofNullable(platformName != null ? String.valueOf(platformName) : null).orElse(null);
}

default String getAutomationName() {
Object automationName = getSessionDetail("automationName");
return ofNullable(automationName != null ? String.valueOf(automationName) : null).orElse(null);
}

/**
* @return is focus on browser or on native content.
*/
default boolean isBrowser() {
Object browserName = getSessionDetail("browserName");
return browserName != null && !isBlank(String.valueOf(browserName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import io.appium.java_client.HasSessionDetails;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.RemoteWebElement;
Expand All @@ -37,25 +38,17 @@
*/
public class JsonToMobileElementConverter extends JsonToWebElementConverter {

private static final String AUTOMATION_NAME_PARAMETER = "automationName";
private static final String PLATFORM_NAME_PARAMETER = "platformName";


protected final RemoteWebDriver driver;
private final String automation;
private final String platform;
private final HasSessionDetails hasSessionDetails;

/**
* @param driver an instance of {@link org.openqa.selenium.remote.RemoteWebDriver} subclass
* @param sessionParameters the map of current session parameters
* @param hasSessionDetails object that has session details
*/
public JsonToMobileElementConverter(RemoteWebDriver driver, Map<String, Object> sessionParameters) {
public JsonToMobileElementConverter(RemoteWebDriver driver, HasSessionDetails hasSessionDetails) {
super(driver);
this.driver = driver;
automation = String.valueOf(sessionParameters
.get(AUTOMATION_NAME_PARAMETER)).toLowerCase();
platform = String.valueOf(sessionParameters
.get(PLATFORM_NAME_PARAMETER)).toLowerCase();
this.hasSessionDetails = hasSessionDetails;
}

/**
Expand Down Expand Up @@ -93,8 +86,14 @@ public Object apply(Object result) {
}

protected RemoteWebElement newMobileElement() {
Class<? extends RemoteWebElement> target =
getElementClass(platform, automation);
Class<? extends RemoteWebElement> target;
if (hasSessionDetails.isBrowser()) {
target = getElementClass(null, null);
} else {
target = getElementClass(hasSessionDetails.getPlatformName(),
hasSessionDetails.getAutomationName());
}

try {
Constructor<? extends RemoteWebElement> constructor = target.getDeclaredConstructor();
constructor.setAccessible(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
* Default decorator for use with PageFactory. Will decorate 1) all of the
Expand All @@ -72,7 +73,7 @@ public class AppiumFieldDecorator implements FieldDecorator {
private final String automation;
private final TimeOutDuration timeOutDuration;

private static String extractSessionData(WebDriver driver, String parameter) {
private static String extractSessionData(WebDriver driver, Supplier<String> dataSupplier) {
if (driver == null) {
return null;
}
Expand All @@ -81,7 +82,7 @@ private static String extractSessionData(WebDriver driver, String parameter) {
return null;
}

return String.valueOf(HasSessionDetails.class.cast(driver).getSessionDetail(parameter));
return String.valueOf(dataSupplier.get());
}

public AppiumFieldDecorator(SearchContext context, long implicitlyWaitTimeOut,
Expand All @@ -99,8 +100,10 @@ public AppiumFieldDecorator(SearchContext context, long implicitlyWaitTimeOut,
*/
public AppiumFieldDecorator(SearchContext context, TimeOutDuration timeOutDuration) {
this.originalDriver = unpackWebDriverFromSearchContext(context);
platform = extractSessionData(originalDriver, "platformName");
automation = extractSessionData(originalDriver, "automationName");
platform = extractSessionData(originalDriver, () ->
HasSessionDetails.class.cast(originalDriver).getPlatformName());
automation = extractSessionData(originalDriver, () ->
HasSessionDetails.class.cast(originalDriver).getAutomationName());
this.timeOutDuration = timeOutDuration;

defaultElementFieldDecoracor = new DefaultFieldDecorator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,6 @@ public interface IOSMobileCapabilityType extends CapabilityType {
*/
String SHOW_XCODE_LOG = "showXcodeLog";

/**
* Device logger for real devices. It could be path to deviceconsole
* (installed with npm install deviceconsole, a compiled binary named
* deviceconsole will be added to ./node_modules/deviceconsole/)
* or idevicesyslog (comes with libimobiledevice). Defaults to idevicesyslog
*/
String REAL_DEVICE_LOGGER = "realDeviceLogger";

/**
* Time in milliseconds to pause between installing the application
* and starting WebDriverAgent on the device. Used particularly for larger applications.
Expand Down Expand Up @@ -255,4 +247,20 @@ public interface IOSMobileCapabilityType extends CapabilityType {
*/
String KEYCHAIN_PATH = "keychainPath";

}
/**
* Forces uninstall of any existing WebDriverAgent app on device.
* This can provide stability in some situations. Defaults to false.
*/
String USE_NEW_WDA = "useNewWDA";

/**
* Time, in ms, to wait for WebDriverAgewnt to be pingable. Defaults to 60000ms.
*/
String WDA_LAUNCH_TIMEOUT = "wdaLaunchTimeout";

/**
* Timeout, in ms, for waiting for a resonse from WebDriverAgent. Defaults to 240000ms.
*/
String WDA_CONNECTION_TIMEOUT = "wdaConnectionTimeout";

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.appium.java_client.android;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import io.appium.java_client.NoSuchContextException;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -46,6 +47,7 @@ public class AndroidContextTest extends BaseAndroidTest {

@Test(expected = NoSuchContextException.class) public void testContextError() {
driver.context("Planet of the Ape-ium");
assertTrue(driver.getContext().equals("Planet of the Ape-ium"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.appium.java_client.appium.element.generation;

import static org.junit.Assert.assertTrue;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.service.local.AppiumServiceBuilder;
import org.junit.After;
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 BaseElementGenerationTest {
protected AppiumDriver<?> driver;
protected final BiPredicate<By, Class<? extends WebElement>> commonPredicate = (by, aClass) -> {
WebElement element = driver.findElement(by);
assertTrue(element.getClass().equals(aClass));
return true;
};

@After
public void tearDown() {
if (driver != null) {
driver.quit();
}
driver = null;
}

protected boolean check(Supplier<DesiredCapabilities> serverCapabilitiesSupplier,
Supplier<Capabilities> clientCapabilitiesSupplier,
BiPredicate<By, Class<? extends WebElement>> filter,
By by, Class<? extends WebElement> clazz) {
AppiumServiceBuilder builder = new AppiumServiceBuilder()
.withCapabilities(serverCapabilitiesSupplier.get());
driver = new AppiumDriver<>(builder, clientCapabilitiesSupplier.get());
return filter.test(by, clazz);
}

}
Loading