Hopefully I'm not the first person to encounter this issue.
I'm writing some selenium tests in C# and have a dilemma when trying to adobt a page object model design whilst also needing to do some explicit waits with the ExpectedConditions class.
Let's say I'm storing my elements in an element map class that is simply a property that calls the .FindElement method using an XPath stored in a resources file...
public class PageObject {
public IWebElement Element
{
get { return DriverContext.Driver.FindElement(By.XPath(Resources.Element)); }
}
}
Then I would go on to use that property in various selenium methods.
The issue I have is I also need to check whether this element is visible on the page, and it will error before I can perform the checked (e.g. with WebDriverWait, passing in ExpectedConditions.ElementIsVisible(by) to the .until method).
How do I cleanly seperate out the IWebElement and By locator and allow for this explicit wait/check where needed?
TLDR - How do I maintain a Page Object Model design whilst also having the flexibility to use explicit waits based on the By locator of my elements.
Many thanks,
I use page objects all the time but I have locators at the top of the class instead of elements. I then use the locators to click buttons, etc. as needed. The advantage of this is I only access the element on the page when needed which avoids stale element exceptions, etc. See a simple example below.
class SamplePage
{
public IWebDriver Driver;
private By waitForLocator = By.Id("sampleId");
// please put the variable declarations in alphabetical order
private By sampleElementLocator = By.Id("sampleId");
public SamplePage(IWebDriver webDriver)
{
this.Driver = webDriver;
// wait for page to finish loading
new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(waitForLocator));
// see if we're on the right page
if (!Driver.Url.Contains("samplePage.jsp"))
{
throw new InvalidOperationException("This is not the Sample page. Current URL: " + Driver.Url);
}
}
public void ClickSampleElement()
{
Driver.FindElement(sampleElementLocator).Click();
}
}
I would recommend against storing locators in a separate file because it breaks one of the mantras of page object model which is everything to do with the page goes in the page object. You shouldn't have to open anything but one file to do anything with Page X, the page object class.