2013-07-19 13 views
19

Uderzyłem głową o ścianę, próbując wybrać opcję z listy wyboru select2 select ajax z selenowym webdriverem. Udało mi się sprawić, żeby działał z webrowerem IE, ale nie firefoxem. Oto moja hacky rozwiązanie dla IEObsługa Select2 z Selenium webdriverem

public static void SetSelect2Option(this IWebDriver driver, By locator, string subContainerClass, string searchTerm, TimeSpan? ajaxWaitTimeSpan = null) 
    { 
     var select2Product = driver.FindElement(locator); 
     select2Product.Click(); 
     var searchBox = driver.FindElement(By.CssSelector(subContainerClass + " .select2-input")); 
     searchBox.SendKeys(searchTerm); 
     if (ajaxWaitTimeSpan != null) 
     { 
      driver.Manage().Timeouts().ImplicitlyWait(ajaxWaitTimeSpan.Value); 
     } 
     var selectedItem = driver.FindElements(By.CssSelector(subContainerClass + " .select2-results li")).First(); 
     selectedItem.Click(); 
     selectedItem.SendKeys(Keys.Enter); 
    } 

W Firefoksie, to rozwiązanie działa, aż do osiągnięcia punktu SendKeys zadzwonić gdzie po prostu zawiesza się i przechodzi do następnego etapu bez faktycznie zapłonów select2 do wypełnienia wybranego elementu.

Mam również zmęczony przy użyciu api http://code.google.com/p/selenium/wiki/AdvancedUserInteractions z podobnymi wynikami.

Czy ktoś już wcześniej miał podobny problem?

Odpowiedz

24

Czy możesz nam pokazać również lokalizatory? Oto, co przetestowałem bez żadnych problemów.

Uwaga

  1. Aby otworzyć okno, użyj wybierz selektor css #s2id_e1 .select2-choice lub równoważne XPath.
  2. Upewnij się, że #select2-drop jest widoczny, przez selektor css #select2-drop:not([style*='display: none']) lub równoważny XPath.
  3. Pamiętaj, aby kliknąć element do wyboru, używając subContainerClass + .select2-results li.select2-result-selectable lub równoważnego XPath.
var driver = new FirefoxDriver(); 
driver.Url = "http://ivaynberg.github.io/select2/"; 

var select2Product = driver.FindElement(By.CssSelector("#s2id_e1 .select2-choice")); 
select2Product.Click(); 

string subContainerClass = "#select2-drop:not([style*='display: none'])"; 
var searchBox = driver.FindElement(By.CssSelector(subContainerClass + " .select2-input")); 
searchBox.SendKeys("Ohio"); 

var selectedItem = driver.FindElements(By.CssSelector(subContainerClass + " .select2-results li.select2-result-selectable")).First(); 
selectedItem.Click(); 
+2

FWIW, musiałem użyć 'ClickAt' 5,5 zamiast kliknięć, aby to zadziałało. – Daniel

+0

@Daniel: Bardziej prawdopodobne jest, że nakładają się na siebie inne elementy. Jaka wersja? Którą przeglądarkę? –

+0

To jest w Selenium 2.4.0 w FF. Używam IDE, ale spodziewam się, że zachowanie będzie podobne. Jestem nowy w Selenium, ale nie mogę sobie wyobrazić, co spowodowałoby, że kliknięcie nie zadziała, gdy kliknie to. Zachowanie za pomocą kliknięcia nie powoduje wyświetlenia menu wyboru2. Twoja odpowiedź była pomocna w doprowadzeniu mnie do właściwych elementów ... – Daniel

2

Oto stałe, wielokrotnego użytku rozwiązanie, które zajmuje się dodatkowy problem interakcji z wielu dropdowns select2 na jednej stronie.

Z jakiegoś powodu webdriver nie zastanawiał się nad tym, czy wysłana wartość wyszukiwania będzie widoczna, mimo że można ją było zobaczyć na ekranie, a kursor był w niej. Właśnie na to sprawdza test "jeśli wyświetlany". Następnie używa innego selektora.

Jest to funkcja, która umożliwia wysyłanie identyfikatora pola, które chcesz interakcji z (mniej średnia s2id_) i wartości, aby wybrać (lub przynajmniej wystarczająco dużo, aby dokonać wyboru.)

dodatkowe thread.sleep() s były właśnie po to, aby mi pomóc. Nie sądzę, żeby miały one wpływ na wynik.

public void SelectDropDownOption(string dropDownID, string option) 
    { 
     for (int second = 0; ; second++) 
     { 
      if (second >= 60) Assert.Fail("timeout"); 
      try 
      { 
       if (driver.FindElement(By.CssSelector("div[ID^=s2id_" + dropDownID + "]>a.select2-choice")).Displayed) break; 
      } 
      catch (Exception) 
      { } 
      Thread.Sleep(1000); 
     } 

     driver.FindElement(By.CssSelector("div[ID^=s2id_" + dropDownID + "]>a.select2-choice")).Click(); 
     Thread.Sleep(1000); 

     if (driver.FindElement(By.CssSelector("input.select2-input.select2-focused")).Displayed == true) 
     { 
      driver.FindElement(By.CssSelector("input.select2-input.select2-focused")).SendKeys(option); 
      Thread.Sleep(500); 
      driver.FindElement(By.CssSelector("input.select2-input.select2-focused")).SendKeys(Keys.Enter); 
      Thread.Sleep(500); 
     } 
     else 
     { 
      driver.FindElement(By.CssSelector("input.select2-focusser.select2-offscreen")).SendKeys(option); 
      Thread.Sleep(500); 
      driver.FindElement(By.CssSelector("input.select2-focusser.select2-offscreen")).SendKeys(Keys.Enter); 
      Thread.Sleep(500); 
     } 

    } 
+0

To jest dobry przykład naprawdę złej praktyki kodowania. –

+2

@HappyBird, Wszyscy jesteśmy tutaj, aby się uczyć. Czy możesz zaproponować ulepszenia? Moje rozwiązanie może nie być idealne, ale uważam, że oferuje wiele przydatnych informacji. – KyleK

+0

Przepraszam, nie muszę być niegrzeczny. Mam na myśli to, że 'Thread.Sleep()' należy unikać w jak największym stopniu. –

5

Spędziłem trochę czasu, aby działać w FF, Chrome i IE8-11.

  1. Kliknij rozwijaną strzałkę
  2. Kliknij żądaną li

Oto mój uproszczony kod:

[FindsBy(How = How.ClassName, Using = "select2-arrow")] 
private IWebElement Selector { get; set; } 

private void selectItem(string itemText) 
{ 
    Selector.Click(); // open the drop 
    var drop = Driver.FindElement(By.Id("select2-drop")); // exists when open only 
    var item = drop.FindElement(By.XPath(String.Format("//li[contains(translate(., '{0}', '{1}'), '{1}')]", itemText.ToUpper(), itemText.ToLower()))); 
    item.Click(); 
} 
3

Oto mój kod (Getting/Wyświetlanie):

dojazd select2 dostępne elementy (wyniki):

public List<WebElement> getDataFromSelect2(String elementXpath) 
{  
    WebElement select2Element = driver.findElement(By.xpath(elementXpath)); 
    select2Element.click();  

    WebDriverWait webDriverWait = new WebDriverWait(driver, 90); 
    webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//ul[@class='select2-results']//div"))); 

    WebElement select2ElementResults=driver.findElement(By.xpath("//div[@id='select2-drop']/ul[@class='select2-results']")); 
    List<WebElement> selectResultsAsListCollection = select2ElementResults.findElements(By.tagName("div")); 

    return selectResultsAsListCollection; 
} 

Wyświetlanie select2 dostępnych elementów (Wyniki)

Stosując select2 o id (Attribute): s2id_autogen1:

List<WebElement> select2Results = getDataFromSelect2("//input[@id='s2id_autogen1']"); 

for(WebElement item: select2Results) 
{ 
    System.out.println(item.getText()); 
} 
2

, że stosuje się poniżej kodu, aby wybrać odpowiednią opcję i pracował. To musi być również szybsze niż wykonywanie wielu kliknięć.

String script = "$('select#yearSelector').trigger($.Event('change',{val:'" + year + "'}))"; 
((JavascriptExecutor) driver).executeScript(script); 

A w Pythonie, jeśli ten jeden-liner nie działa, spróbuj dzieląc go na jego składników:

value = ['a', 'b', 'c'] 
script = "var elem = $('select#tradingMarketSelect'); " 
script += "elem.val(%s); " % value 
script += "elem.change();" 
self.driver.execute_script(script) 
1
protected void SelectOptionForSelect2(IWebDriver driver, string id, string text) 
{ 
    var element = driver.FindElement(By.Id(id)).FindElement(By.XPath("following-sibling::*[1]")); 
    element.Click(); 

    element = driver.FindElement(By.CssSelector("input[type=search]")); 
    element.SendKeys(text); 

    Thread.Sleep(1000); 
    element.SendKeys(Keys.Enter); 
} 
Powiązane problemy