2016-03-02 76 views
0

我使用Selenium的v2.52和WebDriver與C#。我想實現的目標應該相當簡單,但我無法找到解決方案:我想通過多個By-criteria找到一個元素。找到一個滿足多個By-criteria的Selenium Webdriver元素

比方說,我有這樣的事情:

<a href="#" class="foo">Click me!</a> 
<a href="#" class="bar">Click me!</a> 
<p class="foo">Click me!</p> 

忽略了一個事實,我可以使用By.CssSelectorBy.CssSelectorBy.XPath等。我假定它應該可以做這樣的事情:

driver.FindElement(By.TagName("a").ClassName("foo")) 
// ...or something like this... 
driver.FindElement(By.TagName("a"), By.ClassName("foo")) 

OpenQA.Selenium.Support.PageObjects.ByChained不會做的伎倆,因爲它是搜索層次。

有沒有辦法找到符合多個By-criteria的元素?

最好的問候, 卡斯滕

+0

,什麼是錯用'XPath'和'CssSelector'? – Andersson

+0

它沒有什麼不對。好的,也許XPath有點靜態。我只是想知道我是否可以像我描述的那樣找到元素。 –

+0

我想沒有這樣的方式來找到多個過濾器的元素。無論如何,'xpath'會更加靈活,因爲只有'xpath'和'cssSelector'才能找到許多'HTML'屬性。還要注意,包含空格的類名不能與By.ClassName(「foo」)方法匹配,但可以與By.XPath('// * [@ class =「foo」]匹配')'... – Andersson

回答

0

我想象這樣的事情可能是你的工作情況。

public IWebElement FindElementByMultipleCriteria(List<By> Criteria, IReadOnlyCollection<IWebElement> toFilter = null) 
{ 
    // If we've reached the end of the criteria list, return the first element: 
    if (Criteria.Count == 0 && toFilter != null) return toFilter.ElementAt(0); 

    // Take the head of the criteria list 
    By currentCriteria = Criteria[0]; 
    Criteria.RemoveAt(0); 

    // If no list of elements found exists, we get all elements from the current criteria: 
    if (toFilter == null) 
    { 
     toFilter = Driver.FindElements(currentCriteria); 
    } 
    // If a list does exist, we must filter out the ones that aren't found by the current criteria: 
    else 
    { 
     List<IWebElement> newFilter = new List<IWebElement>(); 
     foreach(IWebElement e in Driver.FindElements(currentCriteria)) 
     { 
      if (toFilter.Contains(e)) newFilter.Add(e); 
     } 
     toFilter = newFilter.AsReadOnly(); 
    } 

    // Pass in the refined criteria and list of elements found. 
    return FindElementByMultipleCriteria(Criteria, toFilter); 
} 

IWebElement example = FindElementByMultipleCriteria(new List<By>(){ By.TagName("a"), ClassName("foo") }); 

從本質上講,你正在做在通過第一By發現元素的列表你然後通過其餘的By標準並從該初始列表中移除永遠不會再次找到的元素。

這是非常低效的,我不明白你爲什麼想要這樣做,但它是存在的。

哦另外,您需要添加using System.Linq;才能與IReadOnlyCollection互動。

+0

的確,這聽起來像一個可怕的想法。 ;)如果開箱後沒有支持,那就罰款。我想知道是否有可用的東西,但顯然不是。 –

+0

我想它不存在,因爲你可以給它一個像[By.TagName(「a」),By.TagName(「input」),By.TagName(「h1」)]'和只是磚你的程序,哈哈 –

0

嗯,我想你可以嘗試這樣的事情,讓我知道,如果它的工作原理:

public IWebElement FindElementUsingNestedBy(By firstCriteria, By secondCriteria) 
    { 
     var allElements = Driver.FindElements(firstCriteria); 
     foreach (var webElement in allElements) 
     { 
      try 
      { 
       var desiredObject = webElement.FindElement(secondCriteria); 
       return desiredObject; 
      } 
      catch (NotFoundException ex) 
      { 

      } 
     } 
     return null; 
    } 
+0

如果我沒有錯,這不是我所期待的。您的'secondCriteria'正在從firstCriteria中搜索那些元素下面的元素(從DOM的角度來看)。這個功能已經被'ByChained'覆蓋。我希望所有標準都匹配一個元素。 –

相關問題