FindBy with dynamic using possible?

8,739 views
Skip to first unread message

confusa

unread,
Nov 17, 2010, 5:56:58 PM11/17/10
to webdriver
Trying to migrate from Selenium where I had a method like so in a
PageObject:

public void clickContent(String something) {
StringBuilder sb = new StringBuilder();
sb.append("//a[contains(@href, '/");
sb.append(something);
sb.append("')]");
String link = sb.toString();
clickAndWait(link);
}

That worked like a charm but I am struggling with how to do this in
WebDriver with a PageFactory created PageObject. I am thinking it
needs to be something like so but I don't know how to get "something"
in the annotation:

@FindBy(how = How.XPATH, using = "//a[contains(@href, '/
something')]")
private WebElement contentLink;

Is what I am trying to do here possible or is there a better way?
Basically I am trying to construct the xpath for the element with a
variable.

Simon Stewart

unread,
Nov 18, 2010, 12:09:45 PM11/18/10
to webd...@googlegroups.com
Annotations are static. You can, however, pretty easily write a custom
ElementLocator that can build the By dynamically.

Simon

> --
> You received this message because you are subscribed to the Google Groups "webdriver" group.
> To post to this group, send email to webd...@googlegroups.com.
> To unsubscribe from this group, send email to webdriver+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/webdriver?hl=en.
>
>

Message has been deleted

confusa

unread,
Nov 18, 2010, 5:19:39 PM11/18/10
to webdriver
Ahh, that sort of makes sense. Should I implement the
ElementLocatorFactory
interface and create my custom locator that way? A little confused on
that approach as I would need a prefix, variable, and suffix to create
the xpath.

Thanks!

On Nov 18, 9:09 am, Simon Stewart <simon.m.stew...@gmail.com> wrote:
> Annotations are static. You can, however, pretty easily write a custom
> ElementLocator that can build the By dynamically.
>
> Simon
>

Simon Stewart

unread,
Nov 19, 2010, 10:31:23 AM11/19/10
to webd...@googlegroups.com
Yup. That's what you need to do. An example would be:

public class MyLocator implements ElementLocator {
private final WebDriver driver;
private final By by;
private final boolean shouldCache;
private WebElement cachedElement;

public MyLocator(WebDriver driver, Field field) {
this.driver = driver;
Annotations annotations = new Annotations(field)
shouldCache = annotations.isLookupCached();

MyFindBy findBy = field.getAnnotation(MyFindBy.class);
if (findBy != null) {
by = deriveFrom(findBy);
} else {
by = annotations.buildBy();
}
}

protected By deriveFrom(MyFindBy annotation) {
// your magic here
}

public WebElement findElement() {
if (cachedElement != null && shouldCache) {
return cachedElement;
}

WebElement element = driver.findElement(by);

if (shouldCache) {
cachedElement = element;
}

return element;
}
}

That's the hardest bit. The rest is up to you :)

Simon

On Thu, Nov 18, 2010 at 8:25 PM, confusa <materia...@gmail.com> wrote:
> Ahh, that makes sense. Should I implement the ElementLocatorFactory
> interface and create my custom locator that way? Seems like the proper
> thing to do perhaps.
>
> Thanks!
>
> Bryan


>
> On Nov 18, 9:09 am, Simon Stewart <simon.m.stew...@gmail.com> wrote:

>> Annotations are static. You can, however, pretty easily write a custom
>> ElementLocator that can build the By dynamically.
>>
>> Simon
>>

confusa

unread,
Nov 23, 2010, 1:42:51 PM11/23/10
to webdriver
Sorry, still struggling a bit here. The example you gave above is
giving me a "bound mismatch error":

Bound mismatch: The generic method getAnnotation(Class<T>) of type
AnnotatedElement is not applicable for the arguments
(Class<ConstructedFindBy>). The inferred type ConstructedFindBy is not
a valid substitute for the bounded parameter <T extends Annotation>
ConstructedElementLocator.java line 25

I am naming mine ConstructedFindBy by the way. Do I also need to
create the ConstructedFindBy class?

Thanks for your help!

Simon Stewart

unread,
Nov 24, 2010, 7:00:34 AM11/24/10
to webd...@googlegroups.com
Presumably, yes.

Simon

confusa

unread,
Nov 24, 2010, 7:11:13 PM11/24/10
to webdriver
Think I have this now, I needed to create the ConstructedFindBy as an
@interface similiar to the FindBy. Don't have it fully working yet,
but at least the compiler stopped complaining!

Thanks!

On Nov 24, 4:00 am, Simon Stewart <simon.m.stew...@gmail.com> wrote:
> Presumably, yes.
>
> Simon
>

Yanan

unread,
Jan 19, 2011, 9:16:27 PM1/19/11
to webdriver
Hi confusa,

I'm having the same problem as you did and still struggling. Could you
please share some samples?

Thank you in advance for the help!
Yanan

confusa

unread,
Feb 2, 2011, 12:33:37 AM2/2/11
to webdriver
Haven't had time to go back to this so it is not fully working. What I
came up with so far, which may be wrong:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ConstructedFindBy {
How how() default How.ID;
String using();
}

Now the class:
public class ConstructedElementLocator implements ElementLocator {

private final WebDriver driver;
private final By by;
private final boolean shouldCache;
private WebElement cachedElement;

public ConstructedElementLocator(WebDriver driver, Field field) {
this.driver = driver;
Annotations annotations = new Annotations(field);
shouldCache = annotations.isLookupCached();

ConstructedFindBy findBy =
field.getAnnotation(ConstructedFindBy.class);
if (findBy != null) {
by = deriveFrom(findBy);
} else {
by = annotations.buildBy();
}
}

protected By deriveFrom(ConstructedFindBy annotation) {
// Need stuff here
}

public WebElement findElement() {
if (cachedElement != null && shouldCache) {
return cachedElement;
}

WebElement element = driver.findElement(by);

if (shouldCache) {
cachedElement = element;
}

return element;
}

}

Anyone else want to take a crack at it?

On Jan 19, 6:16 pm, Yanan <baoj...@gmail.com> wrote:
> Hi confusa,
>
> I'm having the same problem as you did and still struggling. Could you
> please share some samples?
>
> Thank you in advance for the help!
> Yanan
>
> On Nov 24 2010, 7:11 pm, confusa <materiaconf...@gmail.com> wrote:
>
> > Think I have this now, I needed to create the ConstructedFindBy as an
> > @interface similiar to theFindBy. Don't have it fully working yet,
> > > >>    if (findBy!= null) {

pallav shah

unread,
Sep 24, 2016, 9:48:08 PM9/24/16
to webdriver
Any one has recent update on this ?
Love to have solution to this.

⇜Krishnan Mahadevan⇝

unread,
Sep 25, 2016, 9:46:08 AM9/25/16
to webdriver
Pallav,

I don't think there is much that can be done here. Annotations are compile time meta data that you feed to the JVM.
Variables are necessarily resolved as values only at runtime. So its not possible.
PageFactory created PageObject to the best of my knowledge will not fit the bill when you are dealing with dynamic elements. 

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/

--
You received this message because you are subscribed to the Google Groups "webdriver" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webdriver+unsubscribe@googlegroups.com.

To post to this group, send email to webd...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages