Przewiń element do widoku za pomocą Selenium


207

Czy w Selenium 1.x lub 2.x istnieje sposób przewijania okna przeglądarki, tak aby określony element identyfikowany przez XPath był widoczny w przeglądarce? W Selenium istnieje metoda ustawiania ostrości, ale nie wydaje się, aby fizycznie przewijała widok w FireFox. Czy ktoś ma jakieś sugestie, jak to zrobić?

Potrzebuję tego, dlatego, że testuję kliknięcie elementu na stronie. Niestety zdarzenie nie działa, chyba że element jest widoczny. Nie mam kontroli nad kodem, który uruchamia się po kliknięciu elementu, więc nie mogę debugować ani modyfikować go, więc najłatwiejszym rozwiązaniem jest przewinięcie elementu do widoku.


Możesz spróbować tego hacky, jeśli nic więcej nie działa dla ciebie : stackoverflow.com/a/53771434/7093031
YB Przyczyna

Odpowiedzi:


214

Próbowałem wielu rzeczy w odniesieniu do przewijania, ale poniższy kod zapewnił lepsze wyniki.

To będzie przewijać, dopóki element nie będzie widoczny:

WebElement element = driver.findElement(By.id("id_of_element"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500); 

//do anything you want with the element

6
Jest to dobre rozwiązanie, gdy możesz mieć element position: fixedna swojej stronie i przesłania on element, który Selenium chce kliknąć. Dość często te stałe elementy znajdują się na dole, więc ustawienie scrollIntoView(true)ładnie przenosi je na górę rzutni.
Mandible79

3
Oparte na najnowszej wersji selenu (2.53), jest to teraz świetne rozwiązanie pomocnicze. Selen nie zawsze przewija element do widoku, więc na pewno się przyda.
Zoidberg,

20
Proszę przejść truedo scrollIntoViewjeżeli przedmiotem jesteś przewijając jest pod którym aktualnie jesteś, falsejeśli obiekt jesteś przewijając jest powyżej, gdzie aktualnie jesteśmy. Trudno mi było to rozgryźć.
Big Money

2
Dlaczego potrzebujesz snu na wątku? skrypt executeScript powinien być synchroniczny
riccardo.tasso

1
@ riccardo.tasso mógł zostać zaimplementowany sen, aby poradzić sobie z nieznaną aplikacją docelową. Jeśli ma dynamiczne przewijanie lub aplikację na jednej stronie, która ładuje kolejny kawałek strony po przewinięciu, między innymi. Mówiąc z doświadczenia, Selenium często psuje witrynę mojej firmy, ponieważ zautomatyzowane działanie odbywało się szybciej niż Javascript może zakończyć, a tym samym przekazało niepełny model danych. Niektóre miejsca mogą uznać to za błąd, ale powiedziano mi: „Żaden człowiek nigdy nie mógłby przywołać takiego scenariusza, więc nie jest to prawdziwy błąd”. C'est la vie.
Solonotix,

157

Możesz użyć org.openqa.selenium.interactions.Actionsklasy, aby przejść do elementu.

Jawa:

WebElement element = driver.findElement(By.id("my-id"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

Pyton:

from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.sl.find_element_by_id('my-id')).perform()

7
Czy to zadziała, jeśli WebElement nie znajduje się w porcie widoku?
wirusrocks

9
@Dominik: W jaki sposób Selenium przesunie mysz do elementu znajdującego się poza ekranem? OCZYWIŚCIE musi najpierw przewinąć element do widoku, a następnie przesunąć do niego mysz. Przetestowałem to. Ten kod działa w przeglądarce Firefox Webdriver 2.48, ale występuje błąd: jeśli na stronie znajduje się element iframe, przewijanie nie działa poprawnie w elemencie iframe podczas przewijania elementu element.LocationOnScreenOnceScrolledIntoView. (Chociaż dokumentacja mówi, że to polecenie zwraca tylko lokalizację, przewija również!)
Elmue

7
Dokumenty w seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… teraz wyraźnie określają: „Przesuwa mysz na środek elementu. Element jest przewijany do widoku, a jego położenie jest obliczane za pomocą getBoundingClientRect. ”
George Pantazes

5
Powyższy kod jest „oficjalnym sposobem” Java Selenium, abyś przewinął element do rzutni, jednak po wypróbowaniu wielu rzeczy implementacja JS wydawała mi się bardziej niezawodna. W szczególności ta metoda .
Kenji Miwa,

2
Nie działało dla mnie: - | Używane stackoverflow.com/a/23902068/661414 zamiast.
Leukipp,

28
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

Możesz spróbować tego.


1
Dzięki. Musiałem użyć tej metody w przypadku, gdy automatyczne przewijanie Selenium powodowało, że inny element przesłaniał element, który musiałem kliknąć. Udało mi się przewinąć dowolną kwotę, aby element był widoczny w okienku ekranu, bez zasłaniania.
Daniel Richnak,

Działa to tylko w FIrefox, Chrome i IE nie obsługuje tej metody
virusrocks

Właśnie dlatego korzystasz js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);z IE, Firefox i js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);Chrome. Prosty.
IamBatman

((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");To działało w Chrome. I jedyne rozwiązanie, które faktycznie dla mnie zadziałało. Taka sama sytuacja, jak w przypadku pierwszego komentatora, miałem na dole stały element, który zasłaniał element, który musiałem kliknąć.
srebrny


15

Jeśli chcesz przewijać okno Firefox za pomocą webdriver Selenium, jednym ze sposobów jest użycie JavaScript w kodzie Java. Kod JavaScript do przewijania w dół (na dół strony internetowej) wygląda następująco:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, document.documentElement.clientHeight));");

10

Wydaje się, że celowanie w dowolny element i wysyłanie klawiszy w dół (lub w górę / w lewo / w prawo) również działa. Wiem, że to trochę włamanie, ale tak naprawdę nie jestem zainteresowany użyciem JavaScript do rozwiązania problemu z przewijaniem.

Na przykład:

WebElement.sendKeys(Keys.DOWN);

Jest to nie mniej hack niż używanie js i jest to naprawdę najprostsza rzecz. Znalazłem ten problem przede wszystkim w IE, w którym kliknięcie próbuje przewinąć element do widoku, ale go nie robi. Rozwiązanie jest równie eleganckie przy użyciu {PGUP}, jeśli jest wykonane z odpowiednim scenariuszem try / catch / loop.
jibbs

Uratowałeś mi dzień! Dzięki
Jesko R.

W moim przypadku sprawdziło się przewrócenie strony. To fajny hack (w porównaniu do wszystkich hacków js).
akostadinov

Dzięki @DevDave! Odpowiednik w C #:var elem = driver.FindElement(By.Id("element_id")); elem.SendKeys(Keys.PageDown);
Watth

9
webElement = driver.findElement(By.xpath("bla-bla-bla"));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElement);

Aby uzyskać więcej przykładów, przejdź tutaj . Wszystko po rosyjsku, ale kod Java jest międzykulturowy :)


Czy mogę zrozumieć, dlaczego dla tego rozwiązania istnieje -1?
josephnvu,

Ponieważ działa tylko w przeglądarce Firefox. Żadne inne przeglądarki nie obsługują tej metody.
Wayne Allen

Jeśli ktoś potrzebuje tłumaczenia z języka rosyjskiego na wyżej wymieniony dokument, chętnie pomoże.
monkrus

8

W Selenium musimy skorzystać z pomocy JavaScript, aby przewinąć do elementu lub przewinąć stronę:

je.executeScript("arguments[0].scrollIntoView(true);", element);

W powyższym zestawieniu elementjest dokładny element, w którym musimy przewijać. Wypróbowałem powyższy kod i zadziałał on dla mnie.

Mam kompletny post i wideo na ten temat:

http://learn-automation.com/how-to-scroll-into-view-in-selenium-webdriver/


@Mukesh otwani powyższy kod będzie przewijany w dół, ale jak abt przewija w górę bez użycia zdefiniowanych w nim pikseli.
khan

6

Możesz użyć tego fragmentu kodu, aby przewijać:

DO#

var element = Driver.FindElement(By.Id("element-id"));
Actions actions = new Actions(Driver);
actions.MoveToElement(element).Perform();

Masz to


6

To działało dla mnie:

IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);

5

Selenium 2 próbuje przewinąć do elementu, a następnie kliknąć go. Wynika to z faktu, że Selenium 2 nie będzie oddziaływać z elementem, dopóki nie uzna, że ​​jest widoczny.

Przewijanie do elementu odbywa się niejawnie, więc wystarczy znaleźć element, a następnie z nim pracować.


19
Jak to jest odpowiedź na pytanie?
reinierpost

57
nie wydaje mi się działać w ten sposób. Dostaję błędy „element niemożliwy do kliknięcia” dla elementów, które są
niewidoczne

5
@DevDave Mam ten sam problem, z wyjątkiem tego, że w moim przypadku selen nie wykonuje akcji kliknięcia na elemencie i nie ma wyjątków. Nie miałem wcześniej problemu i nie wiem, co to spowodowało.
Zeinab Abbasimazar

5
Ukryte przewijanie różni się w zależności od przeglądarki. Mam test elementu w wyskakującym menu w części strony. Dzięki klejnotowi Ruby selenium_webdriver 2.43 znajduję przeglądarkę chromu 37 (i wierzę, że Internet Explorer) rzeczywiście przewija element menu do widoku i klika go. Ale Firefox 32 nie wydaje się wcale przewijać, a następnie kończy się niepowodzeniem z informacją „Element nie jest obecnie widoczny, więc nie można z nim wchodzić w interakcje”.
narciarzy

9
Ta odpowiedź jest zła. Zgodnie ze specyfikacją Selenium 2.0 WebElement.click()wymaga, aby element był widoczny, aby go kliknąć. Nie będzie przewijać się w twoim imieniu.
Gili

5

Użyj sterownika, aby wysłać klucze takie jak klawisz pagedownlub downarrow, aby wyświetlić element. Wiem, że jest to zbyt proste rozwiązanie i może nie mieć zastosowania we wszystkich przypadkach.


1
To nonsens. Być może będziesz musiał wysłać kilkanaście stron w dół na dużej stronie. Jest wolny i niezawodny.
Elmue

2
Tak. Zgadzam się. Ale powiedziałem: „nie dotyczy wszystkich przypadków”
Ganesh S

Znalezienie niektórych znanych elementna widocznej stronie i wysłanie PageDown element.SendKeys(Keys.PageDown);działało dla mnie.
Gokul

Radzę używać klawisza Alt, aby nie przewijać strony i używać klauzuli try / wyjątkiem (Python) do obsługi błędów, które mogą wystąpić podczas próby wysłania kluczy do niektórych elementów.
Alex K.

4

Z mojego doświadczenia wynika, że ​​Selenium Webdriver nie przewija automatycznie do elementu po kliknięciu, gdy na stronie znajduje się więcej niż jedna przewijana sekcja (co jest dość powszechne).

Używam Ruby, a dla mojego AUT musiałem załatać metodę kliknięcia w następujący sposób;

class Element

      #
      # Alias the original click method to use later on
      #
      alias_method :base_click, :click

      # Override the base click method to scroll into view if the element is not visible
      # and then retry click
      #
      def click
        begin
          base_click
        rescue Selenium::WebDriver::Error::ElementNotVisibleError
          location_once_scrolled_into_view
          base_click
        end
      end

Metoda „location_once_scrolled_into_view” jest istniejącą metodą klasy WebElement.

Doceniam, że nie używasz Ruby, ale powinno dać ci kilka pomysłów.


Zadeklarowałem powyższe module Capybara :: module Nodei musiałem zadzwonić native.location_once_scrolled_into_viewzamiast po prostu location_once_scrolled_into_view. Uratowałem również ::Selenium::WebDriver::Error::UnknownError, co często otrzymuję w Firefoksie 44.0.2. Uważam jednak, że to rozwiązanie nie jest wystarczająco elastyczne, i ostatecznie poddałem <Element>.native.location_once_scrolled_into_viewwywołania samemu testowi akceptacji, a następnie w page.execute_script('window.scrollByPages(-1)')razie potrzeby natychmiast .
Al Chou

Watir ma metodę, Element#scroll_into_viewktóra deleguje do Selenium location_once_scrolled_into_view. Ale oba nie robią nic innego niż domyślne zachowanie Selenium, więc elementy przepełnienia nadal mogą blokować to, co próbujemy kliknąć.
akostadinov

3

Skrypt Ruby do przewijania elementu do widoku jest jak poniżej.

$driver.execute_script("arguments[0].scrollIntoView(true);", element)
sleep(3)
element.click

2

Czasami miałem również problem z przewijaniem za pomocą Selenium. Więc użyłem javaScriptExecuter, aby to osiągnąć.

Aby przewinąć w dół:

WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollBy(0, 250)", "");

Lub też

js.executeScript("scroll(0, 250);");

Do przewijania w górę:

js.executeScript("window.scrollBy(0,-250)", "");

Lub,

js.executeScript("scroll(0, -250);");

2

Jeśli uważasz, że inne odpowiedzi były zbyt hackerskie, ta też jest taka, ale nie wiąże się to z iniekcją JavaScript.

Gdy przycisk jest poza ekranem, łamie się i przewija do niego, więc spróbuj ponownie ... ¯ \ _ (ツ) _ / ¯

try
{
    element.Click();
}
catch {
    element.Click();
}

2

Jest to powtarzające się rozwiązanie z JavaScript, ale z dodanym oczekiwaniem na element.

W przeciwnym razie ElementNotVisibleExceptionmoże się pojawić, jeśli wykonywana jest akcja na elemencie.

this.executeJavaScriptFunction("arguments[0].scrollIntoView(true);", elementToBeViewable);
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(ExpectedConditions.visibilityOf(elementToBeViewable));

?? <- co to znaczy?
Choi

1

Użyłem tego sposobu do przewijania elementu i kliknięcia:

List<WebElement> image = state.getDriver().findElements(By.xpath("//*[contains(@src,'image/plus_btn.jpg')]"));

for (WebElement clickimg : image)
{
  ((JavascriptExecutor) state.getDriver()).executeScript("arguments[0].scrollIntoView(false);", clickimg);
  clickimg.click();
}

W moim przypadku scrollIntoView(false)działało, ale scrollIntoView(true)nie działało . Albo może działać , to zależy od twojego scenariusza.
rsenna

Mój przypadek jest odwrotny - prawda działa, fałsz kończy się niepowodzeniem, ale tylko w zakresie kliknięcia. Przewija poprawnie dla fałszu i to jest to, co wolę, ale z jakiegokolwiek powodu Selenium nadal nie widzi go po kliknięciu. Używanie prawdziwych zwojów jest o wiele za wysokie, ale przynajmniej działa.
Bill Hileman,

Klawisze wysyłania użytkownika wprowadzają zamiast klikać, gdy tylko jest to możliwe - pozwala to uniknąć problemów, jeśli przeglądarka nie ma powiększenia 100%.
Zunair

1
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}

1

Możesz odwiedzić stronę Przewiń elementy sieciowe i stronę internetową Selenium WebDriver za pomocą Javascript :

public static void main(String[] args) throws Exception {

    // TODO Auto-generated method stub
    FirefoxDriver ff = new FirefoxDriver();
    ff.get("http://toolsqa.com");
    Thread.sleep(5000);
    ff.executeScript("document.getElementById('text-8').scrollIntoView(true);");
}

@AbhishekBedi Pamiętam, że jest również obsługiwany w Chrome. Czy masz jakiś konkretny problem?
wirusrocks

1

W większości sytuacji do przewijania ten kod będzie działał.

WebElement element = driver.findElement(By.xpath("xpath_Of_Element"));                 
js.executeScript("arguments[0].click();",element);

1

JAWA

Spróbuj przewinąć do elementu użyj x ypozycji i użyj JavascriptExecutorz tym argumentem:"window.scrollBy(x, y)" .

Po imporcie:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.JavascriptExecutor;

Najpierw musisz uzyskać x ylokalizację elementu.

//initialize element
WebElement element = driver.findElement(By.id("..."));

//get position
int x = element.getLocation().getX();
int y = element.getLocation().getY();

//scroll to x y 
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(" +x +", " +y +")");


0

Domyślne zachowanie Selenium polegające na przewijaniu powoduje, że element jest ledwo widoczny u góry rzutni. Ponadto nie wszystkie przeglądarki zachowują się dokładnie tak samo. To jest bardzo niezadowalające. Jeśli nagrywasz filmy z testów przeglądarki, tak jak ja, chcesz, aby element przewinął się do widoku i był wyśrodkowany pionowo .

Oto moje rozwiązanie dla Java:

public List<String> getBoundedRectangleOfElement(WebElement we)
{
    JavascriptExecutor je = (JavascriptExecutor) driver;
    List<String> bounds = (ArrayList<String>) je.executeScript(
            "var rect = arguments[0].getBoundingClientRect();" +
                    "return [ '' + parseInt(rect.left), '' + parseInt(rect.top), '' + parseInt(rect.width), '' + parseInt(rect.height) ]", we);
    System.out.println("top: " + bounds.get(1));
    return bounds;
}

A następnie, aby przewinąć, nazywasz to tak:

public void scrollToElementAndCenterVertically(WebElement we)
{
    List<String> bounds = getBoundedRectangleOfElement(we);
    Long totalInnerPageHeight = getViewPortHeight(driver);
    JavascriptExecutor je = (JavascriptExecutor) driver;
    je.executeScript("window.scrollTo(0, " + (Integer.parseInt(bounds.get(1)) - (totalInnerPageHeight/2)) + ");");
    je.executeScript("arguments[0].style.outline = \"thick solid #0000FF\";", we);
}

brakuje funkcji getViewPortHeight ... W założeniu bierzesz wysokość elementu docelowego
Shubham Jain

0

Oto jak to zrobić z PHP webDriver dla Selenium. Działa dla autonomicznego serwera Selenium 2.39.0 + https://github.com/Element-34/php-webdriver + Firefox 25.0

$element=$session->welement("xpath", "//input[@value='my val']");
$element->click();
$element=$session->welement("xpath", "//input[@value='ma val2']");
$element->location_in_view(); // < -- this is the candy
$element->click();

Uwaga: korzystam z dostosowanej wersji elementu WWW PHP Element34 PHP. Ale w rdzeniu nie ma żadnych zmian. Po prostu używam mojego „powitania” zamiast „elementu”. Ale nie ma to wpływu na przedmiotową sprawę. Autor sterownika mówi „aby zezwolić, aby prawie wszystkie wywołania API były bezpośrednią transformacją tego, co zdefiniowano w samym protokole WebDriver”. Więc nie powinieneś mieć problemu z innymi językami programowania.

Samo kliknięcie nie działa w mojej konfiguracji. Spowoduje to przewinięcie zamiast kliknięcia, więc musiałem kliknąć dwa razy bez wywoływania „location_in_view ()”.

Uwaga: Ta metoda działa w przypadku elementów, które można wyświetlić, takich jak przycisk wprowadzania typu.

Spójrz na: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location

Opis JsonWireProtocol # sugeruje użycie położenia + moveto, ponieważ lokalizacja _w_view jest metodą wewnętrzną.


0

Coś, co zadziałało, to użycie metody Browser.MoveMouseToElement na elemencie w dolnej części okna przeglądarki. Cudem działało w Internet Explorerze, Firefoksie i Chrome.

Wybrałem to zamiast techniki wstrzykiwania JavaScript tylko dlatego, że było mniej hackerskie.


Który to język programowania?
akostadinov

0

Testowałem komponenty ADF i musisz mieć osobne polecenie przewijania, jeśli używane jest opóźnione ładowanie. Jeśli obiekt nie zostanie załadowany, a Ty spróbujesz go znaleźć za pomocą Selenium, Selenium zgłosi wyjątek polegający na nieodnalezieniu elementu.


0

Jeśli nic nie działa, wypróbuj to przed kliknięciem:

public void mouseHoverJScript(WebElement HoverElement) {

    String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}";
    ((JavascriptExecutor) driver).executeScript(mouseOverScript, HoverElement);
}

0

W Javie możemy przewijać za pomocą JavaScript, jak w poniższym kodzie:

driver.getEval("var elm = window.document.getElementById('scrollDiv'); if (elm.scrollHeight > elm.clientHeight){elm.scrollTop = elm.scrollHeight;}");

Możesz przypisać żądaną wartość do zmiennej „elm.scrollTop”.


0

Rozwiązaniem jest:

public void javascriptclick(String element)
{
    WebElement webElement = driver.findElement(By.xpath(element));
    JavascriptExecutor js = (JavascriptExecutor) driver;

    js.executeScript("arguments[0].click();", webElement);
    System.out.println("javascriptclick" + " " + element);
}

0

Ten kod działa dla mnie:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");

Pracuje dla mnie. Implementacja Dart WebDriver nie ma jeszcze działań.
Günter Zöchbauer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.