4

爲了解釋我的問題,我已經給了一個小場景:Selenium WebDriver PageFactory FindsBy使用jQuery Selector?

說我有一個登錄頁面。

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(); // some function which returns my driver in a wrapped event or something so I can log everything it does. 
    } 

    [Test] 
    public void Test() 
    { 
     new LoginPage(driver) 
       .Login(new Credentials 
          { Username = "username", 
          Password = "password" }) 
       .SomeHomePageFunction() 

    } 

最終,我知道頁面配置將發生變化,該ID的將主要保持不變,但事情在我的項目迅速改變。我知道xPath是另一種選擇,但由於頁面是基於特定標準生成的,因此路徑不會總是相同,這仍然會變得很痛苦。

使用上面的當前代碼,頁面被加載,並且PageFactory init通過Page Constructor來加載元素。非常棒。這是我目前使用的。

目前,如果某些事情並非總是在頁面上生成,直到某個步驟。我通常做到以下幾點:

private const string ThisIsTheUserNameFieldId = "usernamefield"; 

然後使用撞了上去webdriver的以下內容:

// Navigate to login page 

// code here 

// Enter in credentials 

driver.FindElement(By.Id(ThisIsTheUserNameFieldId)).SendKeys(cred.Username); 

沒有得到很好的結構爲PageFactory,但可以肯定的是,我現在無法繞過的要求。

我最近遇到了一些與C#.Net一起使用的jQuery Selector代碼,它擴展了RemoteWebDriver的功能,我可以使用jQuery選擇器在頁面上查找我的元素。

Selenium jQuery for C#.Net (Including Source)

// So I can do things like this: 
driver.FindElement(By.jQuery("a").Find(":contains('Home')").Next()) 

有誰知道我可以在硒的webdriver延長[FindsBy]屬性,以便它可以使用類似下面的(僞代碼)?

[FindsBy(How = How.jQuery, Using = "div[id$='txtUserName']")] 
public IWebElement UsernameField { get; set; } 
+0

請記住,XPath是非常強大的,你可以很容易地變換的div [ID $ = 'txtUserName']以// DIV [結束-用(@id, 'txtUserName') ] – Anders

+0

我可以發誓我曾試過這種方法。我做了一個快速的單元測試。 OpenQA.Selenium.InvalidSelectorException:給定的選擇器輸入// [結束-與(@id,「txtUserName」)]或者是無效或不導致WebElement。出現以下錯誤: [InvalidSelectorError]無法定位與xpath表達式//輸入的元素[結束-與(@id,「txtUserName」)]由於以下錯誤的: [異常...「的表達是不是法律表達。「代碼: 「51」 nsresult: 「0x805b0033(NS_ERROR_DOM_INVALID_EXPRESSION_ERR)」 位置:「資源:// fxdriver /模塊/原子。js Line:2394「] –

+0

很遺憾,因爲我在幾個頁面上有幾個重要的web元素,這些元素在網站使用涉及的步驟的每個過程中都被用到了ALOT。確定xPath表達式,甚至那些Selenium似乎是無效的,但我認爲這個插件已經很老了,但它仍然存在,它的混亂直到它的工作很好,但是我似乎總是用XPath來解決這個問題 –

回答

4

這不延長[FindsBy],但你是否知道,你可以使用JavaScript的返回的元素?:

var driver = new FirefoxDriver { Url = "http://www.google.com" }; 
var element = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("return document.getElementsByName('q')[0];"); 
element.SendKeys("hello world"); 

您可以輕鬆地擴展,以允許通過jQuery選擇第一注射的jquery(從JQuerify截取和修改):

const string js = 
    @"{var b=document.getElementsByTagName('body')[0]; if(typeof jQuery=='undefined'){var script=document" + 
    @".createElement('script'); script.src='http://code.jquery.com/jquery-latest.min.js';var head=document" + 
    @".getElementsByTagName('head')[0],done=false;script.onload=script.onreadystatechange=function(){if(!" + 
    @"done&&(!this.readyState||this.readyState=='loaded'||this.readyState=='complete')){done=true;script." + 
    @"onload=script.onreadystatechange=null;head.removeChild(script);}};head.appendChild(script);}}"; 
((IJavaScriptExecutor)driver).ExecuteScript(js); 

,然後運行JavaScript來SEL ECT元素你想要的:

var driver = new FirefoxDriver { Url = "http://www.google.com" }; 
var element = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(@"return $('input[name*=""q""]')[0];"); 
element.SendKeys("hello world"); 
+0

我希望我可以用這種方法,我真的這樣做。我處理ASP.Net,並且一旦進行了一些設置更改,大部分ID都會改變。如果可以的話,我試圖走向xPath解決方案,因爲所有這些jQuery添加和JavaScript執行都會對開發階段的快速移動項目維護和處理太多。 –

+0

這太糟糕了......我想你可以提交一個功能請求來升級到XPath 2.0,或者允許JQuery選擇器。 – Anders

+0

感謝您的輸入。 +1 –

相關問題