Skip to content

Commit

Permalink
Merge pull request #556 from TikhomirovSergey/master
Browse files Browse the repository at this point in the history
#552 FIX
  • Loading branch information
TikhomirovSergey authored Jan 20, 2017
2 parents c607ff2 + d940158 commit 02b5b64
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 93 deletions.
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 @@ -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);
}

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

import static io.appium.java_client.MobileBy.AndroidUIAutomator;
import static org.junit.Assert.assertTrue;
import static org.openqa.selenium.By.className;
import static org.openqa.selenium.By.tagName;

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 org.junit.Test;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebElement;

import java.io.File;
import java.util.function.Supplier;

public class AndroidElementGeneratingTest extends BaseElementGenerationTest {

private final File app = new File(new File("src/test/java/io/appium/java_client"),
"ApiDemos-debug.apk");
private final Supplier<DesiredCapabilities> serverCapabilitiesSupplier = () -> {
DesiredCapabilities serverCapabilities = new DesiredCapabilities();
serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
serverCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
serverCapabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
return serverCapabilities;
};

@Test public void whenAndroidNativeAppIsLaunched() {
assertTrue(check(serverCapabilitiesSupplier, () -> {
DesiredCapabilities clientCapabilities = new DesiredCapabilities();
clientCapabilities.setCapability(MobileCapabilityType.FULL_RESET, true);
clientCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60);
return clientCapabilities;
}, commonPredicate, AndroidUIAutomator("new UiSelector().clickable(true)"),
AndroidElement.class));
}

@Test public void whenAndroidHybridAppIsLaunched() {
assertTrue(check(serverCapabilitiesSupplier, () -> {
DesiredCapabilities clientCapabilities = new DesiredCapabilities();
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"), RemoteWebElement.class));
}

@Test public void whenAndroidBrowserIsLaunched() {
assertTrue(check(() -> {
DesiredCapabilities serverCapabilities = new DesiredCapabilities();
serverCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
serverCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.BROWSER);
return serverCapabilities;
}, () -> {
DesiredCapabilities clientCapabilities = new DesiredCapabilities();
clientCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
return clientCapabilities;
}, (by, aClass) -> {
driver.get("https://www.google.com");
return commonPredicate.test(by, aClass);
}, className("gsfi"), RemoteWebElement.class));
}
}
Loading

0 comments on commit 02b5b64

Please sign in to comment.