Skip to content

Commit

Permalink
Add withLabel/withLabelHint and @Label/@LabelHint
Browse files Browse the repository at this point in the history
Close #316
  • Loading branch information
Toilal committed Sep 28, 2016
1 parent b4bbff6 commit 25ddf13
Show file tree
Hide file tree
Showing 21 changed files with 633 additions and 57 deletions.
Expand Up @@ -41,7 +41,7 @@ public void isAt() {
try {
findFirst(by).now();
} catch (NoSuchElementException | StaleElementReferenceException e) {
throw new AssertionError("@FindBy element not found for page " + getClass().getName());
throw new AssertionError("@FindBy element not found for page " + getClass().getName(), e);
}
}
}
Expand Down
@@ -0,0 +1,18 @@
package org.fluentlenium.core.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Define a label on a injected {@link org.fluentlenium.core.domain.FluentWebElement} or
* {@link org.fluentlenium.core.domain.FluentList}
*
* @see org.fluentlenium.core.label.FluentLabel#withLabel(String)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Label {
String value() default "";
}
@@ -0,0 +1,18 @@
package org.fluentlenium.core.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Add a label hint on a injected {@link org.fluentlenium.core.domain.FluentWebElement} or
* {@link org.fluentlenium.core.domain.FluentList}
*
* @see org.fluentlenium.core.label.FluentLabel#withLabelHint(String...)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface LabelHint {
String[] value();
}
Expand Up @@ -4,6 +4,7 @@
import org.fluentlenium.core.conditions.FluentListConditions;
import org.fluentlenium.core.filter.Filter;
import org.fluentlenium.core.hook.HookControl;
import org.fluentlenium.core.label.FluentLabel;
import org.fluentlenium.core.proxy.FluentProxyState;
import org.fluentlenium.core.search.SearchControl;
import org.fluentlenium.core.wait.FluentWaitElementList;
Expand All @@ -14,7 +15,7 @@
/**
*
*/
public interface FluentList<E extends FluentWebElement> extends List<E>, FluentActions<FluentList<E>, E>, FluentProxyState<FluentList<E>>, SearchControl<E>, HookControl<FluentList<E>> {
public interface FluentList<E extends FluentWebElement> extends List<E>, FluentActions<FluentList<E>, E>, FluentProxyState<FluentList<E>>, SearchControl<E>, HookControl<FluentList<E>>, FluentLabel<FluentList<E>> {

/**
* Retrieve the first element.
Expand Down
@@ -1,8 +1,10 @@
package org.fluentlenium.core.domain;

import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
import lombok.experimental.Delegate;
import org.fluentlenium.core.FluentControl;
import org.fluentlenium.core.action.Fill;
import org.fluentlenium.core.action.FillSelect;
Expand All @@ -16,6 +18,8 @@
import org.fluentlenium.core.hook.FluentHook;
import org.fluentlenium.core.hook.HookChainBuilder;
import org.fluentlenium.core.hook.HookDefinition;
import org.fluentlenium.core.label.FluentLabel;
import org.fluentlenium.core.label.FluentLabelImpl;
import org.fluentlenium.core.proxy.LocatorProxies;
import org.fluentlenium.core.wait.FluentWaitElementList;
import org.openqa.selenium.By;
Expand All @@ -34,11 +38,23 @@ public class FluentListImpl<E extends FluentWebElement> extends ComponentList<E>
private final List<HookDefinition<?>> hookDefinitions = new ArrayList<>();
private HookChainBuilder hookChainBuilder;

public FluentListImpl(Class<E> componentClass, List<E> list, FluentControl fluentControl, ComponentInstantiator instantiator) {
private final FluentLabelImpl<FluentListImpl<E>> label;

public FluentListImpl(Class<E> componentClass, final List<E> list, FluentControl fluentControl, ComponentInstantiator instantiator) {
super(componentClass, list, fluentControl, instantiator);
this.hookChainBuilder = new DefaultHookChainBuilder(fluentControl, instantiator);
this.label = new FluentLabelImpl<>(this, new Supplier<String>() {
@Override
public String get() {
return list.toString();
}
});
}

@Delegate
private FluentLabel<FluentListImpl<E>> getLabel() {
return label;
}

/**
* Creates a FluentList from array of Selenium {@link WebElement}
Expand Down Expand Up @@ -85,7 +101,12 @@ public E first() {
if (!LocatorProxies.isLoaded(proxy)) {
WebElement first = LocatorProxies.first(proxy);
LocatorProxies.setHooks(first, hookChainBuilder, hookDefinitions);
return instantiator.newComponent(componentClass, first);
E component = instantiator.newComponent(componentClass, first);
if (component instanceof FluentLabel) {
component.withLabel(label.getLabel());
component.withLabelHint(label.getLabelHints());
}
return component;
}
if (this.size() == 0) {
throw new NoSuchElementException("Element not found");
Expand All @@ -98,7 +119,12 @@ public E last() {
if (!LocatorProxies.isLoaded(proxy)) {
WebElement last = LocatorProxies.last(proxy);
LocatorProxies.setHooks(last, hookChainBuilder, hookDefinitions);
return instantiator.newComponent(componentClass, last);
E component = instantiator.newComponent(componentClass, last);
if (component instanceof FluentLabel) {
component.withLabel(label.getLabel());
component.withLabelHint(label.getLabelHints());
}
return component;
}
if (this.size() == 0) {
throw new NoSuchElementException("Element not found");
Expand All @@ -111,7 +137,12 @@ public E index(int index) {
if (!LocatorProxies.isLoaded(proxy)) {
WebElement indexElement = LocatorProxies.index(proxy, index);
LocatorProxies.setHooks(indexElement, hookChainBuilder, hookDefinitions);
return instantiator.newComponent(componentClass, indexElement);
E component = instantiator.newComponent(componentClass, indexElement);
if (component instanceof FluentLabel) {
component.withLabel(label.getLabel());
component.withLabelHint(label.getLabelHints());
}
return component;
}
if (this.size() <= index) {
throw new NoSuchElementException("Element not found");
Expand Down Expand Up @@ -529,7 +560,7 @@ public void clear() {

@Override
public String toString() {
return list.toString();
return label.toString();
}
}

@@ -1,5 +1,6 @@
package org.fluentlenium.core.domain;

import com.google.common.base.Supplier;
import lombok.experimental.Delegate;
import org.fluentlenium.core.FluentControl;
import org.fluentlenium.core.action.Fill;
Expand All @@ -18,6 +19,8 @@
import org.fluentlenium.core.hook.HookChainBuilder;
import org.fluentlenium.core.hook.HookControl;
import org.fluentlenium.core.hook.HookDefinition;
import org.fluentlenium.core.label.FluentLabel;
import org.fluentlenium.core.label.FluentLabelImpl;
import org.fluentlenium.core.proxy.FluentProxyState;
import org.fluentlenium.core.proxy.LocatorProxies;
import org.fluentlenium.core.search.Search;
Expand All @@ -38,7 +41,7 @@
* WebElementCustom include a Selenium WebElement. It provides a lot of shortcuts to make selenium more fluent
*/
public class FluentWebElement extends Component implements WrapsElement, FluentActions<FluentWebElement, FluentWebElement>,
FluentProxyState<FluentWebElement>, SearchControl<FluentWebElement>, HookControl<FluentWebElement> {
FluentProxyState<FluentWebElement>, SearchControl<FluentWebElement>, HookControl<FluentWebElement>, FluentLabel<FluentWebElement> {
private final Search search;
private final Axes axes;
private final MouseElementActions mouseActions;
Expand All @@ -48,6 +51,9 @@ public class FluentWebElement extends Component implements WrapsElement, FluentA
private final List<HookDefinition<?>> hookDefinitions = new ArrayList<>();
private final HookChainBuilder hookChainBuilder;

@Delegate
private FluentLabel<FluentWebElement> label;

public FluentWebElement(WebElement webElement, FluentControl fluentControl, ComponentInstantiator instantiator) {
super(webElement, fluentControl, instantiator);

Expand All @@ -58,6 +64,12 @@ public FluentWebElement(WebElement webElement, FluentControl fluentControl, Comp
this.mouseActions = new MouseElementActions(this.fluentControl.getDriver(), webElement);
this.keyboardActions = new KeyboardElementActions(this.fluentControl.getDriver(), webElement);
this.conditions = new WebElementConditions(this);
this.label = new FluentLabelImpl<>(this, new Supplier<String>() {
@Override
public String get() {
return getElement().toString();
}
});
}

@Delegate(excludes = {InputControl.class, AwaitControl.class, SearchControl.class})
Expand Down Expand Up @@ -489,11 +501,6 @@ private boolean isInputOfTypeFile() {
return "input".equalsIgnoreCase(this.tagName()) && "file".equalsIgnoreCase(this.attribute("type"));
}

@Override
public String toString() {
return this.getElement().toString();
}

@Override
public FluentWebElement noHook() {
hookDefinitions.clear();
Expand All @@ -514,4 +521,9 @@ public <O, H extends FluentHook<O>> FluentWebElement withHook(Class<H> hook, O o
LocatorProxies.setHooks(getElement(), hookChainBuilder, hookDefinitions);
return this;
}

@Override
public String toString() {
return label.toString();
}
}

This file was deleted.

Expand Up @@ -24,7 +24,6 @@
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.events.EventFiringWebDriver;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
Expand Down Expand Up @@ -198,8 +197,8 @@ private void initFluentElements(final Object container, SearchContext searchCont
if (isSupported(container, field)) {
ArrayList<HookDefinition<?>> fieldHookDefinitions = new ArrayList<>(containerContext.getHookDefinitions());
addHookDefinitions(field.getAnnotations(), fieldHookDefinitions);
ElementLocatorFactory locatorFactory = new FieldAndReturnTypeElementLocatorFactory(searchContext);
ElementLocator locator = locatorFactory.createLocator(field);
InjectionElementLocatorFactory locatorFactory = new InjectionElementLocatorFactory(searchContext);
InjectionElementLocator locator = locatorFactory.createLocator(field);
if (locator != null) {
ComponentAndProxy fieldValue = initFieldElements(locator, field);
injectComponent(fieldValue, locator, container, field, fieldHookDefinitions);
Expand Down
Expand Up @@ -10,9 +10,10 @@
import java.lang.reflect.Field;
import java.util.List;

public class FieldAndReturnTypeAnnotations extends AbstractAnnotations {
public class InjectionAnnotations extends AbstractAnnotations {
private final ClassAnnotations classAnnotations;
private final Annotations fieldAnnotations;
private final LabelAnnotations labelFieldAnnotations;

private static boolean isList(Field field) {
return List.class.isAssignableFrom(field.getType());
Expand All @@ -26,10 +27,10 @@ private static Class<?> getEffectiveClass(Field field) {
return field.getType();
}

public FieldAndReturnTypeAnnotations(Field field) {
public InjectionAnnotations(Field field) {
classAnnotations = new ClassAnnotations(getEffectiveClass(field));
fieldAnnotations = new Annotations(field);

labelFieldAnnotations = new LabelAnnotations(field);
}

@Override
Expand All @@ -44,4 +45,12 @@ public By buildBy() {
public boolean isLookupCached() {
return classAnnotations.isLookupCached() || fieldAnnotations.isLookupCached();
}

public String getLabel() {
return labelFieldAnnotations.getLabel();
}

public String[] getLabelHints() {
return labelFieldAnnotations.getLabelHints();
}
}

0 comments on commit 25ddf13

Please sign in to comment.