Прокрутіть елемент до перегляду із селеном


207

Чи є в Selenium 1.x або 2.x спосіб прокручування вікна браузера, щоб певний елемент, ідентифікований XPath, переглядав браузер? У Selenium є метод фокусування, але він, схоже, фізично не прокручує погляд у FireFox. Хтось має якісь пропозиції, як це зробити?

Причина, що мені це потрібно, - це тестування клацання елемента на сторінці. На жаль, подія, здається, не працює, якщо елемент не видно. У мене немає контролю над кодом, який спрацьовує при натисканні на елемент, тому я не можу налагоджувати або вносити зміни до нього, тому найпростішим рішенням є прокручування елемента на вигляд.


Ви можете спробувати цього хакі, якщо нічого іншого не працює для вас : stackoverflow.com/a/53771434/7093031
YB Причина

Відповіді:


214

Спробував багато речей щодо прокрутки, але наведений нижче код дав кращі результати.

Це буде прокручуватися, поки елемент не буде переглянуто:

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
Це акуратне рішення, коли у вас може бути елемент position: fixedна своїй сторінці, і це затемнює елемент, який Selenium хоче натиснути. Досить часто ці нерухомі елементи йдуть внизу, тож налаштування scrollIntoView(true)зручно переміщує її до верхньої частини огляду.
Mandible79

3
На основі новітньої версії селену (2,53) це зараз чудове допоміжне рішення. Селен не завжди прокручує елемент до перегляду, тому це безумовно корисно.
Зойдберг

20
Передайте , trueщоб , scrollIntoViewякщо об'єкт ви прокрутки знаходиться під де ви зараз перебуваєте, falseякщо об'єкт ви прокрутки вище , де ви зараз перебуваєте. Мені важко було зрозуміти це.
Великі гроші

2
Для чого потрібен сон ниток? ExecuteScript має бути синхронним
riccardo.tasso

1
@ riccardo.tasso може бути здійснено сон для боротьби з невідомими цільовим додатком. Якщо в ньому є динамічна прокрутка, або односторінковий додаток, який завантажує наступний біт сторінки після прокрутки, серед інших можливостей. Виходячи з досвіду, Selenium часто ламав сайт моєї компанії, оскільки автоматизована дія відбувалася швидше, ніж Javascript могла виконати, і, таким чином, пройшла неповна модель даних. Деякі місця можуть вважати це помилкою, але мені сказали: "Ніхто не міг посилатися на такий сценарій, тому це не справжня помилка". Це життя.
Солонотікс

157

Ви можете використовувати org.openqa.selenium.interactions.Actionsклас для переміщення до елемента.

Java:

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

Пітон:

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

7
Чи спрацює це, якщо WebElement не знаходиться у порту перегляду?
virusrocks

9
@Dominik: Як Selenium перемістить мишу на елемент, який знаходиться поза екраном? ОБОВ'ЯЗКОВО він повинен спочатку прокрутити елемент у подання, а потім перемістити мишкою на нього. Я тестував це. Цей код працює на Firefox Webdriver 2.48, але є помилка: Якщо у вас є рамка на сторінці, прокрутка не працює належним чином у програмі iframe, тоді як елемент element.LocationOnScreenOnceScrollIntoView прокручується правильно. (Хоча в документації сказано, що ця команда повертає лише місцеположення, вона також прокручується!)
Elmue

7
Документи на seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… тепер чітко вказують "Переміщення миші на середину елемента. Елемент прокручується до перегляду та його розташування обчислюється за допомогою getBoundingClientRect. "
Джордж Пантазес

5
Вищевказаний код є "офіційним способом" Java Selenium хоче, щоб ви прокрутили елемент у вікно перегляду, проте після спроби багатьох речей реалізація JS мені здалася більш надійною. Цей метод зокрема.
Kenji Miwa

2
Не працювали для мене: - | Замість цього використовується stackoverflow.com/a/23902068/661414 .
Leukipp

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

Ви можете спробувати це.


1
Дякую. Мені потрібно було скористатися цим методом у випадку, коли автоматична прокрутка Selenium викликала, щоб інший елемент затушовував елемент, на який мені потрібно було натиснути. Я зміг прокрутити довільну суму, щоб зробити елемент видимим у вікні перегляду, не затушовуючись.
Даніель Річнак

Це буде працювати лише в FIrefox, Chrome і IE, не підтримують цей метод
virusrocks

Ось чому ви використовуєте js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);для IE та Firefox та js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);для Chrome. Простий.
IamBatman

((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");Це працювало в Chrome. І єдине рішення, яке насправді працювало на мене. У тій же ситуації, що і у першого коментатора, у мене внизу був фіксований елемент, який постійно затушовував елемент, який мені потрібно було натиснути.
срібло


15

Якщо ви хочете прокрутити вікно Firefox за допомогою веб-диска Selenium, одним із способів є використання JavaScript у коді Java. Код JavaScript для прокручування вниз (до низу веб-сторінки) такий:

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

10

Націлювання на будь-який елемент і надсилання клавіш вниз (або вгору / вліво / вправо), здається, також працює. Я знаю, що це трохи хак, але я не дуже в курсі використання JavaScript для вирішення проблеми прокрутки.

Наприклад:

WebElement.sendKeys(Keys.DOWN);

Це не менш хак, ніж використання js, і це справді найпростіша річ. Я виявив це, головним чином, проблемою з IE, коли клацання намагається прокрутити елемент до перегляду, але це не зовсім робить його. Рішення настільки ж елегантне, використовуючи {PGUP}, якщо виконано з належним сценарієм спробу / лову / циклу.
джибс

Ти врятував мій день! Спасибі
Єсько Р.

У моєму випадку справа була справою. Це хороший хак (проти всіх js-хаків).
акостадінов

Дякую @DevDave! Еквівалент в C #:var elem = driver.FindElement(By.Id("element_id")); elem.SendKeys(Keys.PageDown);
Ватт

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

Щоб отримати більше прикладів, перейдіть сюди . Все російською мовою, але код Java є міжкультурним :)


Чи можу я зрозуміти, чому існує -1 для цього рішення?
josephnvu

Тому що він працює лише у Firefox. Жоден інший браузер не підтримує цей метод.
Уейн Аллен

Якщо комусь потрібен переклад з російської мови для вищезгаданого документа, будемо раді допомогти.
monkrus

8

У Selenium нам потрібно скористатися виконавцем JavaScript, щоб прокрутити елемент або прокрутити сторінку:

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

У наведеному вище твердженні elementє точний елемент, де нам потрібно прокрутити. Я спробував вищевказаний код, і він працював на мене.

У мене є повний пост та відео про це:

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


@Mukesh otwani наведений вище код буде прокручуватися вниз, але як abt прокручувати вгору, не використовуючи жодних пікселів, визначених у ньому.
хан

6

Ви можете використовувати цей фрагмент коду для прокрутки:

C #

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

Там у вас є


6

Це працювало для мене:

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

5

Selenium 2 намагається прокрутити елемент і натиснути на нього. Це тому, що Selenium 2 не буде взаємодіяти з елементом, якщо він не вважає, що його видно.

Прокрутка до елемента відбувається неявно, тому вам просто потрібно знайти предмет і потім працювати з ним.


19
Як це відповідь на запитання?
reinierpost

57
Схоже, для мене це не працює. Я отримую помилки "елемент, який не можна натискати" для елементів, які не видно
DevDave

5
@DevDave У мене така ж проблема, за винятком мого випадку, селен не виконує натискання на елемент і немає винятків. Раніше у мене не було проблем, і я не знаю, що це спричинило.
Зейнаб Аббасімазар

5
Неявна прокрутка відрізняється між браузерами. У мене є тест елемента у спливаючому меню, що знаходиться внизу сторінки. Завдяки Ruby gem selenium_webdriver 2.43 я знаходжу браузер Chrome-37 (і я вважаю, що Internet Explorer) дійсно прокручує пункт меню в огляд і клацає його. Але, здається, Firefox 32 взагалі не прокручується, а потім виходить з ладу "Елемент на даний момент не видно, і тому він не може взаємодіяти з".
лижник

9
Ця відповідь неправильна. Відповідно до специфікації для Selenium 2.0 WebElement.click()потрібно, щоб елемент був видно, щоб натиснути на нього. Він не прокручується від вашого імені.
Гілі

5

Використовуйте драйвер, щоб надіслати такі елементи, як ключ pagedownабо downarrowключ, щоб привести елемент у поле перегляду. Я знаю, що це занадто просте рішення і може бути застосоване не у всіх випадках.


1
Це нісенітниця. Можливо, вам доведеться надіслати десяток сторінки на велику сторінку. Це повільно і не надійно.
Elmue

2
Так. Я згоден. Але я сказав "не застосовується у всіх випадках"
Ganesh S

Знайти відоме elementна сторінці, що переглядається, та надіслати PageDown element.SendKeys(Keys.PageDown);мені працювало.
Гокул

Я б радив використовувати клавішу Alt, щоб ви не прокручували сторінку та використовували пункт try / razen (Python) для обробки помилок, які можуть виникати під час спроби надсилати ключі до деяких елементів.
Алекс К.

4

З мого досвіду, Selenium Webdriver не автоматично прокручує елемент до клацання, коли на сторінці є більше одного прокручуваного розділу (що досить часто).

Я використовую Ruby, і для мого AUT мені довелося мавпочки виправити метод натискання наступним чином;

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

Метод 'location_once_scroll_into_view' є існуючим методом у класі WebElement.

Я вдячний, що ви можете не використовувати Ruby, але це повинно дати вам кілька ідей.


Я заявив про це вище module Capybara :: module Node, і мені потрібно було дзвонити, native.location_once_scrolled_into_viewа не просто location_once_scrolled_into_view. Я також врятувався ::Selenium::WebDriver::Error::UnknownError, саме це я часто отримую у Firefox 44.0.2. Але я вважаю, що це рішення не є досить гнучким, і в кінцевому підсумку перекладаю <Element>.native.location_once_scrolled_into_viewдзвінки в сам тест на прийняття, з подальшим негайним поданням, page.execute_script('window.scrollByPages(-1)')де це необхідно.
Аль-Чу

У Ватіра є метод, Element#scroll_into_viewякий делегує селену location_once_scrolled_into_view. Але обидва не відрізняються від поведінки за замовчуванням Seleniums, тому елементи переповнення все ще можуть перешкоджати тому, що ми намагаємось натиснути.
акостадінов

3

Сценарій Ruby для прокрутки елемента до перегляду наведено нижче.

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

2

Іноді я також стикався з проблемою прокрутки селену. Тому я використовував javaScriptExecuter для досягнення цього.

Для прокручування вниз:

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

Або також

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

Для прокручування вгору:

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

Або,

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

2

Якщо ви вважаєте, що інші відповіді були надто хиткими, це теж занадто, але інжекції JavaScript не задіяні.

Коли кнопка вимкнена на екрані, вона перемикається та прокручується до неї, тому повторіть спробу ... ¯ \ _ (ツ) _ / ¯

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

2

Це повторне рішення з JavaScript, але з доданим елементом очікування.

В іншому випадку ElementNotVisibleExceptionможе з’явитися, якщо виконується деяка дія на елементі.

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

?? <- що означає?
Чой

1

Я використав цей спосіб для прокрутки елемента та натисніть:

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();
}

У моєму випадку scrollIntoView(false)працював, але scrollIntoView(true)не став. Або може працювати , це залежить від вашого сценарію.
rsenna

У мене справа навпаки - справжні роботи, помилкові помилки, але тільки наскільки йде клік. У ньому правильно прокручується помилка, і це те, що я віддаю перевагу, але з будь-якої причини Selenium все ще не може побачити її для натискання. Використовуючи справжні сувої, все занадто високо, але принаймні це працює.
Білл Хілеман

Користувальницькі ключі вводять замість клацання, коли це можливо - це дозволяє уникнути проблем, якщо браузер не має 100% збільшення.
Зунайр

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

1

Ви можете зайти на сторінку Прокручування веб-елементів та веб-сторінки - Selenium WebDriver за допомогою 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 Я пам'ятаю, що його підтримують і в Chrome. З якоюсь конкретною проблемою ви могли зіткнутися?
virusrocks

1

У більшості випадків прокрутка цього коду спрацює.

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

1

JAVA

Спробуйте прокрутки для елемента використовувати x yположення, і використання JavascriptExecutorз цим аргументом: "window.scrollBy(x, y)".

Після імпорту:

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

Спочатку потрібно отримати x yелемент розташування.

//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 +")");

1

Я не впевнений, що питання все-таки актуальне, але після посилання на документа прокруткиIntoView з https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView .

Найпростішим рішенням було б

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

Це прокручує елемент у центрі сторінки.


0

Типова поведінка Selenium нас для прокрутки, так що елемент ледь видно у верхній частині вікна перегляду. Також не всі браузери мають таку саму поведінку. Це дуже незадоволює. Якщо ви записуєте відео з тестів веб-переглядача, як я, те, що ви хочете, - це елемент, який прокручується до поля перегляду та буде вертикально розташований по центру .

Ось моє рішення для 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;
}

А потім, для прокрутки, ви називаєте це так:

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);
}

функція getViewPortHeight відсутня ... Припущення, ви приймаєте висоту цільового елемента
Shubham Jain

0

Ось як я це роблю з PHP webDriver для Selenium. Він працює на автономному сервері 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();

Примітка: я використовую індивідуальну версію веб-драйвера Element34 PHP. Але жодних змін в ядрі немає. Я просто використовую свою "сприйняття" замість "елемента". Але це не впливає на конкретну справу. Автор драйвера каже, "щоб дозволити майже всі виклики API бути прямою трансформацією того, що визначено в самому протоколі WebDriver". Тому у вас не повинно виникнути проблем з іншими мовами програмування.

Просто натискання не буде працювати в моїх налаштуваннях. Він зробить прокрутку замість клацання, тому мені довелося натиснути двічі, не викликаючи "location_in_view ()".

Примітка. Цей метод працює для елементів, які можна переглядати, як введення кнопки типу.

Погляньте на сторінку: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location

В описі JsonWireProtocol # пропонується використовувати location + moveto, оскільки location _in_view - це внутрішній метод.


0

Щось для мене працювало, це використовувати метод Browser.MoveMouseToElement на елементі внизу вікна браузера. Чудом це працювало в Internet Explorer, Firefox та Chrome.

Я вибрав це через техніку інжекції JavaScript тільки тому, що він відчував себе менш хакітним.


Яка мова програмування це?
акостадінов

0

Я робив тестування з компонентами ADF, і ви повинні мати окрему команду для прокрутки, якщо використовується ледаче завантаження. Якщо об'єкт не завантажений, і ви намагаєтеся знайти його за допомогою Selenium, Selenium викине виняток, який не знайдено.


0

Якщо нічого не працює, спробуйте це перед натисканням:

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

У Java ми можемо прокручувати за допомогою JavaScript, як у наступному коді:

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

Ви можете призначити бажане значення змінній "elm.scrollTop".


0

Рішення таке:

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

Цей код працює для мене:

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

Працює для мене. У реалізації Dart WebDriver ще немає дій.
Günter Zöchbauer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.