Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Page factory list element not initialized when parameterized by gener… #1237

Merged
merged 2 commits into from
Sep 16, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -129,6 +131,12 @@ protected boolean isDecoratableList(Field field) {
return true;
}
}

if ((listType instanceof TypeVariable)
&& Arrays.asList(((TypeVariable<?>) listType).getBounds())
.stream().anyMatch(item -> availableElementClasses.contains(item))) {
return true;
}
return false;
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,156 @@
package io.appium.java_client.pagefactory_tests;

import static org.junit.Assert.assertTrue;
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;
import java.util.function.Supplier;

public class GenericTest {

static class TempGenericPage<T> {
/**
* The Generic types are null on an unbound page.
*/
private static <T> void assertUnboundGenericsNull(T genericItem,
List<? extends T> genericItems) {
assertNull(genericItem);
assertNull(genericItems);
}

/**
* The Generic types are not null on a page bound by a WebElement (or WebElement
* sub type).
*/
private static <T extends WebElement> void assertBoundGenericsNotNull(T genericItem,
List<? extends T> genericItems) {
assertNotNull(genericItem);
assertNotNull(genericItems);
}

/**
* The Element types are never null.
*/
private static void assertElementsNotNull(WebElement elementItem,
List<? extends WebElement> elementItems) {
assertNotNull(elementItem);
assertNotNull(elementItems);
}

/**
* The Object types are always null.
*/
private static void assertObjectsNull(Object objectItem, List<? extends Object> 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<WebElement> webElementItems;
public List<MobileElement> mobileElementItems;
public List<Object> 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<T> {
public T genericItem;
public WebElement webElementItem;
public MobileElement mobileElementItem;
public Object objectItem;

public List<T> items;
public List<T> genericItems;
public List<WebElement> webElementItems;
public List<MobileElement> mobileElementItems;
public List<Object> objectItems;

public List<T> getItems() {
return items;
public void assertInit() {
assertUnboundGenericsNull(genericItem, genericItems);
assertElementsNotNull(webElementItem, webElementItems);
assertElementsNotNull(mobileElementItem, mobileElementItems);
assertObjectsNull(objectItem, objectItems);
}
}

static class MockWebDriver implements WebDriver {
/**
* A page with a WebElement bound generic type. The Object types are never
* initialized.
*/
static class TempWebBoundPage<T extends WebElement> {
public T genericItem;
public WebElement webElementItem;
public MobileElement mobileElementItem;
public Object objectItem;

public List<T> genericItems;
public List<WebElement> webElementItems;
public List<MobileElement> mobileElementItems;
public List<Object> 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<T extends MobileElement> {
public T genericItem;
public WebElement webElementItem;
public MobileElement mobileElementItem;
public Object objectItem;

public List<T> genericItems;
public List<WebElement> webElementItems;
public List<MobileElement> mobileElementItems;
public List<Object> 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) {
Expand All @@ -42,13 +168,13 @@ public String getTitle() {
}

@Override
public List<WebElement> findElements(By by) {
return null;
public <T extends WebElement> List<T> findElements(By by) {
throw new NotImplementedException("MockWebDriver did not expect to findElements");
}

@Override
public WebElement findElement(By by) {
return null;
public <T extends WebElement> T findElement(By by) {
throw new NotImplementedException("MockWebDriver did not expect to findElement");
}

@Override
Expand Down Expand Up @@ -90,16 +216,85 @@ public Navigation navigate() {
public Options manage() {
return null;
}

@Override
public Capabilities getCapabilities() {

final Map<String, Object> 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<String, Object> 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<WebElement> 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<WebElement> page = new TempWebBoundPage<>();
PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page);
page.assertInit();
}

@Test
public void genericTestCse() {
Supplier<Boolean> result = () -> {
PageFactory
.initElements(new AppiumFieldDecorator(new MockWebDriver()),
new TempGenericPage<>());
return true;
};
assertTrue(result.get());
}
}
public void webBoundMobileElementTestCase() {
TempWebBoundPage<MobileElement> 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<MobileElement> page = new TempMobileBoundPage<>();
PageFactory.initElements(new AppiumFieldDecorator(new MockWebDriver()), page);
page.assertInit();
}
}