--
You received this message because you are subscribed to the Google Groups "Selenium Users" group.
To post to this group, send email to seleniu...@googlegroups.com.
To unsubscribe from this group, send email to selenium-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/8ICkNZS6vEUJ.
For more options, visit https://groups.google.com/groups/opt_out.
I would classify myself as one of the more experienced Selenium users and I use page factory’s all the time.
In my mind they are exactly the right way to do things, make your page factory control the pages and your test assert that everything is as expected.
Who is telling you not to use them?
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/HaX0-xHzNR0J.
On his three points:
1. Correct, but that’s true for any WebElement (You can’t create a WebElement if the locator cannot be found). You can however work around this by using the FindBy object to get a list of elements e.g.:
@FindBy(how=How.ID, using =”foo”)
List<WebElement> myElement
You can then use the size of the list to find out if the element exists (This is the same as performing a driver.findElements(by.id(“foo”));
2. Not sure what he means here to be honest as he is not exactly clear. That being said I’m not aware of a way of checking if an WebElement is a child of another WebElement off the top of my head so I don’t see how the page factory is different from using normal WebElement’s.
3. He’s wrong, you can. We use elements created in a page factory with ExpectedConditions every day.
There are also a few cheats you can do with page factories, one of my favourites is to instantiate a PageFactory using an element rather than a driver object e.g.:
This is very handy when working with things like SVG’s.
You can have a page object for a global navigation bar that returns a page object for the page you navigate to every time you click on a link e.g.:
@FindBy(how = How.ID, using = "home")
public WebElement homeLink;
@FindBy(how = How.ID, using = "contact")
public WebElement contactUsLink;
HomePage followHomePageLink() {
homeLink.click();
return new HomePage (driver);
}
ContactUsPage followContactUsLink() {
contactUsLink.click();
return new ContactUsPage (driver);
}
Page objects are extremely powerful if used properly and you can have page objects that use page objects. This means you can break out global functionality used by all pages if you want to.
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/Q6vnySadP6YJ.
HomePage followHomePageLink() {
homeLink.click();
return new HomePage (driver);
}
I mean, shouldn't you have written "...return PageFactory.initElements(driver, HomePage.class)", instead?
thanks.
In that case point 3 is not clear, I read it to mean that WebElements constructed using a page factory were not compatible with ExpectedConditions (which they are).
I agree that you can’t plug WebElements into ExpectedConditions that require a By locator. From my point of view I don’t see this as a big issue because I see the ExpectedConditions class as a template to do useful things, but I can see that for somebody new to the concept having to write your own is not ideal.
As to your second point I usually initElements in the constructor for my page factory (have a look at the link I supplied). Using the example I linked below my constructor looks like this:
public HighCharts(WebDriver driver, WebElement chart) {
PageFactory.initElements(new DefaultElementLocatorFactory(chart), this);
this.driver = driver;
this.chart = chart;
wait = new WebDriverWait(driver, waitTimeoutInSeconds, 100);
performAction = new Actions(driver);
}
Since the WebElements created by @FindBy are essentially WebElement proxies that find and re-find the associated element every time you invoke them (unless you set them to be cached), you can init them when you construct the object to cut down on line of code.
So to answer your question I did, I just use Page Objects in a slightly different way to you J
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/KAxXhO-S4moJ.
No, parent.findElement() won’t do what you rightly suggest. I believe that that’s a bug, but several Selenium developers disagree (see Issue 403 http://code.google.com/p/selenium/issues/detail?id=403). Thus WebElement.findElement(By.xpath(“//...”)) starts at the document root, even though the programmer clearly said “starting at this element”. I believe all other WebElement.findElement()s are find-within-element, as is WebElement.findElement(By.xpath(locator)) as long as the locator doesn’t start with “//”.
Ross
From: seleniu...@googlegroups.com [mailto:seleniu...@googlegroups.com] On Behalf Of Mike Riley
Sent: Friday, November 16, 2012 2:46 PM
To: seleniu...@googlegroups.com
Subject: Re: [selenium-users] Your opinion on why not to use Page Factory
I am not sure if this will do what you mean for #2, but if you do a search for an element using an element, doesn't that limit it to children of the element you are using for the search?
Instead it incorrectly finds only those nodes which are descendants of p.
Yes, but what you missed was that update #9780 (http://code.google.com/p/selenium/source/detail?r=9780) changed the behavior to treat “//” as meaning “from the top of the document” regardless of the context. In other words, as the issue’s original author wrote:
## What steps will reproduce the problem?
1. Find an element on the page
2. Do a something like my_element.find_elements(:xpath, '//p')
## What is the expected output? What do you see instead?
I expect it to find *all* p elements on the page. If I'd wanted to find
only descendants, I'd have done something like:
my_element.find_elements(:xpath, './/p')
Note the dot before //p
Instead it incorrectly finds only those nodes which are descendants of p.
Which is exactly what Selenium has done since release 2.8. I still think that’s wrong – all other WebElement.findElement() versions search in context except this one – but apparently I’m in the minority.
Ross
From: seleniu...@googlegroups.com [mailto:seleniu...@googlegroups.com] On Behalf Of Mike Riley
Sent: Friday, November 16, 2012 3:23 PM
To: seleniu...@googlegroups.com
Subject: Re: [selenium-users] Your opinion on why not to use Page Factory
As I read that bug it is doing exactly what I said. It treats that element as the start of the DOM to be searched. The poster of that issue says that is not what they expected it to do, but that is how it worked.
Just as they wrote here:
Instead it incorrectly finds only those nodes which are descendants of p.
Mike
On Friday, November 16, 2012 12:02:46 PM UTC-8, Ross wrote:
No, parent.findElement() won’t do what you rightly suggest. I believe that that’s a bug, but several Selenium developers disagree (see Issue 403 http://code.google.com/p/selenium/issues/detail?id=403). Thus WebElement.findElement(By.xpath(“//...”)) starts at the document root, even though the programmer clearly said “starting at this element”. I believe all other WebElement.findElement()s are find-within-element, as is WebElement.findElement(By.xpath(locator)) as long as the locator doesn’t start with “//”.
Ross
From: seleniu...@googlegroups.com [mailto:seleniu...@googlegroups.com] On Behalf Of Mike Riley
Sent: Friday, November 16, 2012 2:46 PM
To: seleniu...@googlegroups.com
Subject: Re: [selenium-users] Your opinion on why not to use Page Factory
I am not sure if this will do what you mean for #2, but if you do a search for an element using an element, doesn't that limit it to children of the element you are using for the search?
For example:
WebElement parent = driver.findElement(By.xpath("//table"));
WebElement child = parent.findElement(By.xpath("//th"));
That should only find a th tag that is a child of the table. Obviously you probably would use something a bit more distinguishing that just the tag name, unless the page only had the one table.
One exception is that XPath could be used to find siblings or even parents of the first element using the "../" notation for the path. Just don't do that and it won't be a problem.
Unless I misunderstood what is wanted.
Mike
--
You received this message because you are subscribed to the Google Groups "Selenium Users" group.
To post to this group, send email to seleniu...@googlegroups.com.
To unsubscribe from this group, send email to selenium-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/selenium-users/-/A3J1yb8k-KAJ.
I think what you really want is:
WebElement parent = driver.findElement(By.xpath("./descendant::table"));
WebElement child = parent.findElement(By.xpath("./descendant::th"));