To explain my question, I gave a small script:
Say I have a login page.
public class LoginPage { [FindsBy(How = How.Id, Using = "SomeReallyLongIdBecauseOfAspNetControlsAndPanels_username"] public IWebElement UsernameField { get; set; } [FindsBy(How = How.Id, Using = "SomeReallyLongIdBecauseOfAspNetControlsAndPanels_password"] public IWebElement PasswordField { get; set; } [FindsBy(How = How.Id, Using = "submitButtonId")] public IWebElement SubmitButton { get; set; } private readonly IWebDriver driver; public LoginPage(IWebDriver driver) { this.driver = driver; if(!driver.Url.Contains("Login.aspx")) { throw new NotFoundException("This is not the login page."); } PageFactory.InitElements(driver, this); } public HomePage Login(Credentials cred) { UsernameField.sendKeys(cred.Username); PasswordField.SendKeys(cred.Password); SubmitButton.Click(); return new HomePage(driver); } } [TestFixture] public class Test : TestBase { private IWebDriver driver; [SetUp] public void SetUp() { driver = StartDriver();
In the end, I know that the page configuration will change, the identifier will basically remain the same, but in my projects everything changes quickly. I know that xPath is another alternative, but because of how the pages are created based on certain criteria, it will still be painful, since the path will not always be the same.
With the current code above, the page loads, and PageFactory initializes the elements through the page builder. Everything is great. This is what I am using at the moment.
Currently, if some things are not always created on the page before a certain step. I usually do the following:
private const string ThisIsTheUserNameFieldId = "usernamefield";
Then click the web browser using the following:
// Navigate to login page // code here // Enter in credentials driver.FindElement(By.Id(ThisIsTheUserNameFieldId)).SendKeys(cred.Username);
Not as well structured as PageFactory, but it is certainly a requirement that I cannot get around.
I recently came across jQuery Selector code for use with C # .Net, which extends the functionality of RemoteWebDriver, where I can use the jQuery selector to find my elements on the page.
Selenium jQuery for C # .Net (including source)
Does anyone know how I can extend the [FindsBy] attribute in Selenium WebDriver so that I can use something like the following (pseudocode)?
[FindsBy(How = How.jQuery, Using = "div[id$='txtUserName']")] public IWebElement UsernameField { get; set; }