diff --git a/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/HtmlElementLoader.java b/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/HtmlElementLoader.java
index 6cacd0e5..9eb667a1 100644
--- a/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/HtmlElementLoader.java
+++ b/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/HtmlElementLoader.java
@@ -32,11 +32,11 @@ public class HtmlElementLoader {
* @see #createPageObject(Class, org.openqa.selenium.WebDriver)
*/
public static T create(Class clazz, WebDriver driver) {
- return create(clazz, new HtmlElementLocatorFactory(driver));
- }
+ return create(clazz, new HtmlElementLocatorFactory(driver));
+ }
- @SuppressWarnings("unchecked")
- public static T create(Class clazz, CustomElementLocatorFactory locatorFactory) {
+ @SuppressWarnings("unchecked")
+ public static T create(Class clazz, CustomElementLocatorFactory locatorFactory) {
if (isHtmlElement(clazz)) {
Class htmlElementClass = (Class) clazz;
return (T) createHtmlElement(htmlElementClass, locatorFactory);
@@ -44,7 +44,7 @@ public static T create(Class clazz, CustomElementLocatorFactory locatorFa
// Otherwise consider class as a page object class
return createPageObject(clazz, locatorFactory);
}
- }
+ }
/**
* Initializes {@code instance} as a block of elements it is instance of {@link HtmlElement}
@@ -90,13 +90,13 @@ public static void populate(T instance, WebDriver driver) {
* @return Initialized instance of the specified class.
*/
public static T createHtmlElement(Class clazz, WebDriver driver) {
- return createHtmlElement(clazz, new HtmlElementLocatorFactory(driver));
+ return createHtmlElement(clazz, new HtmlElementLocatorFactory(driver));
}
public static T createHtmlElement(Class clazz, CustomElementLocatorFactory locatorFactory) {
T htmlElementInstance = HtmlElementFactory.createHtmlElementInstance(clazz);
populateHtmlElement(htmlElementInstance, locatorFactory);
- return htmlElementInstance;
+ return htmlElementInstance;
}
/**
@@ -123,12 +123,12 @@ public static T createHtmlElement(Class clazz, Custom
public static T createPageObject(Class clazz, WebDriver driver) {
return createPageObject(clazz, new HtmlElementLocatorFactory(driver));
}
-
+
public static T createPageObject(Class clazz, CustomElementLocatorFactory locatorFactory) {
- T page = HtmlElementFactory.createPageObjectInstance(clazz, locatorFactory);
+ T page = HtmlElementFactory.createPageObjectInstance(clazz);
populatePageObject(page, locatorFactory);
return page;
- }
+ }
/**
* Initializes fields of the given block of elements with lazy proxies.
@@ -153,9 +153,9 @@ public static T createPageObject(Class clazz, CustomElementLocatorFactory
* @param driver The {@code WebDriver} instance that will be used to look up the elements.
*/
public static void populateHtmlElement(HtmlElement htmlElement, WebDriver driver) {
- populateHtmlElement(htmlElement, new HtmlElementLocatorFactory(driver));
+ populateHtmlElement(htmlElement, new HtmlElementLocatorFactory(driver));
}
-
+
public static void populateHtmlElement(HtmlElement htmlElement, CustomElementLocatorFactory locatorFactory) {
@SuppressWarnings("unchecked")
Class htmlElementClass = (Class) htmlElement.getClass();
@@ -168,7 +168,7 @@ public static void populateHtmlElement(HtmlElement htmlElement, CustomElementLoc
String elementName = getElementName(htmlElementClass);
htmlElement.setName(elementName);
// Initialize elements of the block
- PageFactory.initElements(new HtmlElementDecorator(elementToWrap), htmlElement);
+ PageFactory.initElements(new HtmlElementDecorator(elementToWrap), htmlElement);
}
/**
@@ -194,8 +194,8 @@ public static void populateHtmlElement(HtmlElement htmlElement, CustomElementLoc
public static void populatePageObject(Object page, WebDriver driver) {
populatePageObject(page, new HtmlElementLocatorFactory(driver));
}
-
+
public static void populatePageObject(Object page, CustomElementLocatorFactory locatorFactory) {
- PageFactory.initElements(new HtmlElementDecorator(locatorFactory), page);
+ PageFactory.initElements(new HtmlElementDecorator(locatorFactory), page);
}
}
diff --git a/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/decorator/HtmlElementFactory.java b/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/decorator/HtmlElementFactory.java
index 73e216f2..b7636bc9 100644
--- a/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/decorator/HtmlElementFactory.java
+++ b/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/loader/decorator/HtmlElementFactory.java
@@ -1,16 +1,12 @@
package ru.yandex.qatools.htmlelements.loader.decorator;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Proxy;
+import java.lang.reflect.*;
import java.util.List;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.internal.Locatable;
import org.openqa.selenium.internal.WrapsElement;
import org.openqa.selenium.support.pagefactory.ElementLocator;
-import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler;
import ru.yandex.qatools.htmlelements.element.HtmlElement;
@@ -21,6 +17,8 @@
import ru.yandex.qatools.htmlelements.loader.decorator.proxyhandlers.WebElementListNamedProxyHandler;
import ru.yandex.qatools.htmlelements.loader.decorator.proxyhandlers.WebElementNamedProxyHandler;
+import static ru.yandex.qatools.htmlelements.utils.ReflectionUtils.newInstance;
+
/**
* Contains factory methods for creating instances of blocks, typified elements, page objects
* and for creating lazy proxies.
@@ -32,19 +30,22 @@ public class HtmlElementFactory {
public static T createHtmlElementInstance(Class elementClass) {
try {
- return elementClass.newInstance();
+ return newInstance(elementClass);
+ } catch (NoSuchMethodException e) {
+ throw new HtmlElementsException(e);
} catch (InstantiationException e) {
throw new HtmlElementsException(e);
} catch (IllegalAccessException e) {
throw new HtmlElementsException(e);
+ } catch (InvocationTargetException e) {
+ throw new HtmlElementsException(e);
}
}
public static T createTypifiedElementInstance(Class elementClass,
WebElement elementToWrap) {
try {
- Constructor constructor = elementClass.getConstructor(WebElement.class);
- return constructor.newInstance(elementToWrap);
+ return newInstance(elementClass, elementToWrap);
} catch (NoSuchMethodException e) {
throw new HtmlElementsException(e);
} catch (InstantiationException e) {
@@ -56,14 +57,11 @@ public static T createTypifiedElementInstance(Class<
}
}
- public static T createPageObjectInstance(Class pageObjectClass, ElementLocatorFactory locatorFactory) {
+ public static T createPageObjectInstance(Class pageObjectClass) {
try {
- try {
- Constructor constructor = pageObjectClass.getConstructor(ElementLocatorFactory.class);
- return constructor.newInstance(locatorFactory);
- } catch (NoSuchMethodException e) {
- return pageObjectClass.newInstance();
- }
+ return newInstance(pageObjectClass);
+ } catch (NoSuchMethodException e) {
+ throw new HtmlElementsException(e);
} catch (InstantiationException e) {
throw new HtmlElementsException(e);
} catch (IllegalAccessException e) {
diff --git a/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/utils/ReflectionUtils.java b/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/utils/ReflectionUtils.java
new file mode 100644
index 00000000..d5da31a8
--- /dev/null
+++ b/htmlelements-java/src/main/java/ru/yandex/qatools/htmlelements/utils/ReflectionUtils.java
@@ -0,0 +1,26 @@
+package ru.yandex.qatools.htmlelements.utils;
+
+import com.google.common.collect.Lists;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+import static org.apache.commons.lang3.reflect.ConstructorUtils.invokeConstructor;
+
+/**
+ * User: eroshenkoam
+ * Date: 1/22/13, 5:53 PM
+ */
+public class ReflectionUtils {
+
+ public static T newInstance(Class clazz, Object... args) throws IllegalAccessException,
+ InstantiationException, NoSuchMethodException, InvocationTargetException {
+ if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
+ Class outerClass = clazz.getDeclaringClass();
+ Object outerObject = outerClass.newInstance();
+ return invokeConstructor(clazz, Lists.asList(outerObject, args).toArray());
+ } else {
+ return invokeConstructor(clazz, args);
+ }
+ }
+}
diff --git a/htmlelements-java/src/test/java/ru/yandex/qatools/htmlelements/NestedClassTest.java b/htmlelements-java/src/test/java/ru/yandex/qatools/htmlelements/NestedClassTest.java
new file mode 100644
index 00000000..7e34220e
--- /dev/null
+++ b/htmlelements-java/src/test/java/ru/yandex/qatools/htmlelements/NestedClassTest.java
@@ -0,0 +1,65 @@
+package ru.yandex.qatools.htmlelements;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import ru.yandex.qatools.htmlelements.annotations.Block;
+import ru.yandex.qatools.htmlelements.element.HtmlElement;
+import ru.yandex.qatools.htmlelements.element.Link;
+import ru.yandex.qatools.htmlelements.element.TypifiedElement;
+import ru.yandex.qatools.htmlelements.loader.HtmlElementLoader;
+
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * User: eroshenkoam
+ * Date: 1/22/13, 2:16 PM
+ */
+public class NestedClassTest {
+
+ public WebDriver driver = mock(WebDriver.class);
+ WebElement arrow = mock(WebElement.class);
+ WebElement link = mock(WebElement.class);
+
+ @Before
+ public void before() {
+ when(driver.findElement(By.className("arrow"))).thenReturn(arrow);
+ when(arrow.findElement(By.className("link"))).thenReturn(link);
+ }
+
+ @Test
+ @Ignore
+ public void test() {
+ NestedPageObject pageObject = HtmlElementLoader.create(NestedPageObject.class, driver);
+ assertThat(pageObject, notNullValue());
+ assertThat(pageObject.arrow.getName(), notNullValue());
+ assertThat(pageObject.arrow.link.getWrappedElement(), notNullValue());
+ }
+
+ public class NestedPageObject {
+ @FindBy(className = "arrow")
+ public NestedHtmlElement arrow;
+ }
+
+ public class NestedHtmlElement extends HtmlElement {
+ @FindBy(className = "link")
+ public NestedTypifiedElement link;
+
+ }
+
+
+ public class NestedTypifiedElement extends TypifiedElement {
+
+ public NestedTypifiedElement(WebElement wrappedElement) {
+ super(wrappedElement);
+ }
+
+ }
+}