Jak wstawić datę w Selenium w jQuery Datepicker?

Datepicker – to pole tekstowe, przeznaczone do wprowadzenia daty. Kiedy na nie klikniemy pojawia się kalendarz, w którym możemy wybrać odpowiednią datę. Prezentację różnych wariantów tego elementu można znaleźć na stronie jQuery. Nie wiem, na ile wygodniejsza dla człowieka jest praca z kalendarzem w porównaniu ze zwykłym polem tekstowym, ale dla testera automatycznego jest to prawdziwy koszmar. Aby wprowadzić w taki sposób datę trzeba wykonać wiele czynności – kliknąć w pole tekstowe, aby pojawił się kalendarz, wielokrotnym klikaniem na strzałki w lewo i w prawo wybrać odpowiedni miesiąc i rok a następnie z tablicy odpowiedni dzień miesiąca. Tyle kliknięć myszką tylko po to, aby wypełnić jedno pole tekstowe. Trzeba jeszcze sprawdzić, czy odpowiedni miesiąc i rok znajduje się na prawo czy na lewo od już wybranego. To jeszcze nie wszystko. Kalendarz jest animowany, dlatego należy dodać przed każdym kliknięciem oczekiwanie na pojawienie się elementów i oczekiwanie na zakończenie się animacji. Ogólnie rzecz biorąc, możemy spędzić godziny na pisaniu funkcji służącej do wypełnienia tego pola.

Czy istnieje jakaś alternatywa?

Pierwsza myśl, która przychodzi do głowy jest oczywista – a gdybyśmy nie korzystali z kalendarza? Przecież jest to zwykłe pole tekstowe, więc można w nie po prostu wprowadzić tekst.

public void SetDatepicker(IWebDriver driver, string cssSelector, string date)

{

    new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until<bool>(

        d => driver.FindElement(By.CssSelector(cssSelector)).Displayed);

    driver.FindElement(By.CssSelector(cssSelector)).SendKeys(date);

}

(ten oraz poniższe przykłady kodu są napisane w języku C#)

Problem w tym, że w momencie kiedy zaczynamy wprowadzać tekst, automatycznie pojawi się kalendarz i nie zniknie nawet gdy już skończymy tę czynność.

Aby kalendarz został zamknięty trzeba przenieść fokus w jakieś inne miejsce – na przykład w inne pole tekstowe lub kliknąć w dowolne puste miejsce na stronie.

public void SetDatepicker(IWebDriver driver, string cssSelector, string date)

{

    new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until<bool>(

        d => driver.FindElement(By.CssSelector(cssSelector)).Displayed);

    driver.FindElement(By.CssSelector(cssSelector)).SendKeys(date);

    driver.FindElement(By.CssSelector("body")).Click();

}

public void SetDatepicker(IWebDriver driver, string cssSelector, string date)

{

    new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until<bool>(

        d => driver.FindElement(By.CssSelector(cssSelector)).Displayed);

​}

Jednakże kliknięcie w inne pole jest trudne, ponieważ może zakrywać je kalendarz. Natomiast jeśli klikniemy w dowolne miejsce na stronie to może ono okazać się „zajęte”, a wtedy przypadkiem wejdziemy w jakiś link albo naciśniemy jakiś przycisk, co spowoduje niepożądany efekt.

Jednak główny problem czyha na nas gdzie indziej. Czasami pole tekstowe nie może być edytowane,
a bywa i tak, że w ogóle go nie ma. Jest tylko kalendarz.

Co robić w takich przypadkach?

Jest inne wyjście – należy użyć jQuery API do interakcji z tym elementem. Kalendarz posiada metodę setDate, do której można się odnieść w następujący sposób:

    (driver as IJavaScriptExecutor).ExecuteScript(

        String.Format("$('{0}').datepicker('setDate', '{1}')", cssSelector, date));

)​

Przykład użycia:

IWebDriver driver = new FirefoxDriver();

driver.Url = @"http://jqueryui.com/datepicker/";

driver.SwitchTo().Frame(driver.FindElement(By.CssSelector("iframe.demo-frame")));

SetDatepicker(driver, "#datepicker", "02/20/2002");

Ten sposób jest uniwersalny, a jego praca nie zależy od wyglądu kalendarza. Pracuje on szybciej niż wprowadzenie tekstu w pole tekstowe, a tym bardziej niż 5 – 10 kliknięć myszą.

Czy to „uczciwe”? Czy nie omijamy przy tym jakiś błędów? Możliwe, że tak. Jeśli deweloperzy mają wadliwą wersję jQuery, w której działa API, ale są problemy z GUI to nasze autotesty tego nie wychwycą. Jeśli to Państwa niepokoi, to powinniście zapomnieć o wszystkim co zostało wyżej napisane i wykorzystywać sposób polegający na klikaniu myszką.

Jeśli jednak macie Państwo zaufanie do deweloperów jQuery – można śmiało wykorzystać API, a wtedy Wasze testy będą szybsze i bardziej stabilne.

Tak, zaufanie może zdziałać cuda!

Dla Java:

Java setDatepicker:

public void setDatepicker(WebDriver driver, String cssSelector, String date) {

  new WebDriverWait(driver, 30000).until(

    (WebDriver d) -> d.findElement(By.cssSelector(cssSelector)).isDisplayed());

  JavascriptExecutor.class.cast(driver).executeScript(

    String.format("$('%s').datepicker('setDate', '%s')", cssSelector, date));

}

Przykład:

WebDriver driver = new FirefoxDriver();

driver.get("http://jqueryui.com/datepicker/");

driver.switchTo().frame(

  driver.findElement(By.cssSelector("iframe.demo-frame")));

setDatepicker(driver, "#datepicker", "02/20/2002");
Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn