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.

Dan at Demand
źródło
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
Amith
źródło
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()
sascha
źródło
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.

Mayur
źródło
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));");
Ankit Pandey
źródło
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);
DevDave
źródło
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 :)

VovecUdalec
źródło
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
źródło
@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

Mohsin Awan
źródło
6

To działało dla mnie:

IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);
ULKSSS
źródło
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ć.

AutomatedTester
źródło
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.

Ganesh S.
źródło
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.

Robbie Wareham
źródło
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
Satheesh Kumar
źródło
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);");
Anuraj R.
źródło
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();
}
vicentedealencar
źródło
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));
Łukasz
źródło
?? <- 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();
}
Bibek
źródło
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});")
}
mniam mniam mniam
źródło
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);");
}
wirusrocks
źródło
@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);
SarojPurbey
źródło
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 +")");
FrianH
źródło
1

Nie jestem pewien, czy pytanie jest nadal aktualne, ale po odwołaniu się do dokumentacji scrollIntoView z https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView .

Najłatwiejszym rozwiązaniem byłoby

executor.executeScript("arguments[0].scrollIntoView({block: \"center\",inline: \"center\",behavior: \"smooth\"});",element);

Spowoduje to przewinięcie elementu do środka strony.

Kiranjith
źródło
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);
}
djangofan
źródło
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ą.

Konstantin Iwanow
źródło
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.

David Peters
źródło
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.

użytkownik3781490
źródło
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);
}
Prateek
źródło
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”.

Hemant
źródło
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);
}
akhilesh gulati
źródło
0

Ten kod działa dla mnie:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");
Vishal Singh
źródło
Pracuje dla mnie. Implementacja Dart WebDriver nie ma jeszcze działań.
Günter Zöchbauer