Gulir Elemen ke Tampilan dengan Selenium

208

Apakah ada cara di Selenium 1.x atau 2.x untuk menggulir jendela peramban sehingga elemen tertentu yang diidentifikasi oleh XPath terlihat di peramban? Ada metode fokus di Selenium, tetapi tampaknya tidak secara fisik menggulir tampilan di FireFox. Adakah yang punya saran tentang cara melakukan ini?

Alasan saya membutuhkan ini adalah saya sedang menguji klik suatu elemen pada halaman. Sayangnya acara tersebut tampaknya tidak berfungsi kecuali elemen tersebut terlihat. Saya tidak memiliki kendali atas kode yang menyala ketika elemen diklik, jadi saya tidak bisa men-debug atau membuat modifikasi, jadi, solusi termudah adalah dengan menggulir item ke tampilan.

Dan saat diminta
sumber
Anda dapat mencoba yang ini jika tidak ada yang berhasil untuk Anda : stackoverflow.com/a/53771434/7093031
YB Sebab

Jawaban:

215

Telah mencoba banyak hal sehubungan dengan gulir, tetapi kode di bawah ini memberikan hasil yang lebih baik.

Ini akan menggulir hingga elemen terlihat:

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
sumber
6
Ini adalah solusi yang rapi untuk ketika Anda mungkin memiliki elemen dengan position: fixeddi halaman Anda dan itu mengaburkan elemen yang ingin diklik Selenium. Cukup sering elemen-elemen tetap ini pergi di bagian bawah, jadi pengaturan scrollIntoView(true)memindahkannya dengan baik ke bagian atas viewport.
Mandible79
3
Berdasarkan versi selenium terbaru (2,53), ini sekarang merupakan solusi penolong yang hebat. Selenium tidak selalu menggulir elemen ke dalam tampilan, jadi ini pasti berguna.
Zoidberg
20
Lulus dalam trueuntuk scrollIntoViewjika objek Anda menggulir ke bawah adalah di mana Anda saat ini berada, falsejika objek Anda menggulir ke atas di mana Anda saat ini. Saya mengalami kesulitan mencari tahu itu.
Uang Besar
2
Mengapa Anda perlu tidur thread? executeScript harus sinkron
riccardo.tasso
1
@ riccardo.tasso tidur mungkin telah diterapkan untuk berurusan dengan aplikasi target yang tidak diketahui. Jika memiliki pengguliran dinamis, atau aplikasi satu halaman yang memuat bit halaman berikutnya setelah pengguliran, di antara kemungkinan lainnya. Berbicara dari pengalaman, Selenium sering merusak situs perusahaan saya karena tindakan otomatis terjadi lebih cepat daripada Javascript bisa menyelesaikan, dan dengan demikian melewati model data yang tidak lengkap. Beberapa tempat mungkin menganggapnya sebagai bug, tetapi saya diberitahu "Tidak ada manusia yang bisa melakukan skenario seperti itu, jadi itu bukan bug nyata." C'est la vie.
Solonotix
157

Anda bisa menggunakan org.openqa.selenium.interactions.Actionskelas untuk pindah ke elemen.

Jawa:

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

Python:

from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.sl.find_element_by_id('my-id')).perform()
sascha
sumber
7
Apakah ini akan berfungsi jika WebElement tidak ada di View Port?
virusrocks
9
@Dominik: Bagaimana Selenium akan memindahkan mouse ke elemen yang ada di luar layar? Jelas itu pertama-tama harus menggulir elemen ke tampilan dan kemudian memindahkan mouse ke sana. Saya mengujinya. Kode ini berfungsi di Firefox Webdriver 2.48 tetapi ada bug: Ketika Anda memiliki iframe di halaman, scrolling tidak berfungsi dengan benar di elemen iframe while.LocationOnScreenOnceScrolledIntoView scrolls dengan benar. (Meskipun dokumentasi mengatakan bahwa perintah ini hanya mengembalikan lokasi, ia juga menggulir!)
Elmue
8
Dokumen di seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… sekarang dengan jelas menyatakan "Gerakkan mouse ke tengah elemen. Elemen tersebut digulir ke tampilan dan lokasinya dihitung menggunakan getBoundingClientRect. "
George Pantazes
5
Kode di atas adalah "cara resmi" Java Selenium ingin Anda melakukan scroll elemen ke viewport namun setelah mencoba banyak hal implementasi JS tampaknya bekerja lebih andal bagi saya. Metode ini khususnya.
Kenji Miwa
2
Tidak bekerja untuk saya: - | Digunakan stackoverflow.com/a/23902068/661414 sebagai gantinya.
Leukipp
28
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

Anda mungkin ingin mencoba ini.

Mayur
sumber
1
Terima kasih. Saya perlu menggunakan metode ini dalam kasus di mana gulir-otomatis Selenium menyebabkan elemen lain mengaburkan elemen yang perlu saya klik. Saya dapat menggulir jumlah yang sewenang-wenang untuk membuat elemen terlihat di viewport, tanpa dikaburkan.
Daniel Richnak
Ini hanya akan berfungsi di FIrefox, Chrome dan IE tidak mendukung metode ini
virusrocks
Inilah mengapa Anda menggunakan js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);untuk IE dan Firefox dan js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);untuk Chrome. Sederhana.
IamBatman
((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");Ini berfungsi di Chrome. Dan satu-satunya solusi yang benar-benar bekerja untuk saya. Situasi yang sama dengan komentator pertama, saya memiliki elemen tetap di bagian bawah yang terus mengaburkan elemen yang saya butuhkan untuk mengklik.
perak
15

Jika Anda ingin menggulir pada jendela Firefox menggunakan webdriver Selenium, salah satu caranya adalah menggunakan JavaScript dalam kode Java. Kode JavaScript untuk digulir ke bawah (ke bawah halaman web) adalah sebagai berikut:

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

Menargetkan setiap elemen dan mengirim kunci ke bawah (atau atas / kiri / kanan) tampaknya berfungsi juga. Saya tahu ini sedikit hack, tapi saya tidak terlalu suka menggunakan JavaScript untuk menyelesaikan masalah scrolling.

Sebagai contoh:

WebElement.sendKeys(Keys.DOWN);
DevDave
sumber
Ini tidak kurang dari hack daripada menggunakan js dan ini benar-benar hal yang paling sederhana. Saya menemukan ini terutama masalah dengan IE di mana klik mencoba untuk menggulir elemen ke tampilan tetapi tidak cukup membuatnya. Solusi sama elegannya dengan menggunakan {PGUP} jika dilakukan dengan skenario try / catch / loop yang tepat.
jibbs
Kamu menyelamatkan hariku! Terima kasih
Jesko R.
Di halaman kasus saya turun adalah hal yang berhasil. Ini adalah hack yang bagus (vs semua hacks js).
akostadinov
Terima kasih @DevDave! Setara dalam 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);

Untuk lebih banyak contoh, buka di sini . Semua dalam bahasa Rusia, tetapi kode Java adalah lintas-budaya :)

VovecUdalec
sumber
Bisakah saya mengerti mengapa ada -1 untuk solusi ini?
josephnvu
Karena hanya berfungsi di Firefox. Tidak ada browser lain yang mendukung metode ini.
Wayne Allen
Jika seseorang membutuhkan terjemahan dari bahasa Rusia untuk dokumen yang disebutkan di atas, dengan senang hati akan membantu.
monkrus
8

Di Selenium, kita perlu mengambil bantuan pelaksana JavaScript untuk menggulir ke elemen atau menggulir halaman:

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

Dalam pernyataan di atas elementadalah elemen yang tepat di mana kita perlu menggulir. Saya mencoba kode di atas, dan itu berhasil untuk saya.

Saya punya posting dan video lengkap tentang ini:

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

Mukesh otwani
sumber
@Mukesh otwani kode di atas akan gulir ke bawah, tetapi bagaimana abt gulir ke atas tanpa menggunakan piksel yang ditentukan di dalamnya.
khan
6

Anda dapat menggunakan potongan kode ini untuk menggulir:

C #

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

Itu dia

Mohsin Awan
sumber
6

Ini bekerja untuk saya:

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

Selenium 2 mencoba untuk menggulir ke elemen dan kemudian mengkliknya. Ini karena Selenium 2 tidak akan berinteraksi dengan suatu elemen kecuali jika ia berpikir bahwa itu terlihat.

Menggulir ke elemen terjadi secara implisit sehingga Anda hanya perlu menemukan item dan kemudian bekerja dengannya.

AutomaticTester
sumber
19
Bagaimana ini merupakan jawaban untuk pertanyaan itu?
reinierpost
57
Sepertinya tidak berfungsi seperti itu untuk saya. Saya mendapatkan kesalahan 'elemen tidak dapat diklik' untuk elemen yang tidak terlihat
DevDave
5
@DevDave Saya memiliki masalah yang sama, kecuali dalam kasus saya, selenium tidak melakukan aksi klik pada elemen dan tidak ada pengecualian. Saya tidak punya masalah sebelumnya dan saya tidak tahu apa yang menyebabkannya.
Zeinab Abbasimazar
5
Pengguliran implisit bervariasi di antara browser. Saya memiliki tes elemen di menu pop-up di tengah halaman. Dengan Ruby gem selenium_webdriver 2.43 saya menemukan chromium-browser 37 (dan saya percaya Internet Explorer) memang gulir item menu ke tampilan dan klik itu. Tetapi Firefox 32 tampaknya tidak menggulir sama sekali, dan kemudian gagal dengan "Elemen saat ini tidak terlihat sehingga tidak dapat berinteraksi dengan".
skierpage
9
Jawaban ini salah. Menurut spesifikasi untuk Selenium 2.0 WebElement.click()diperlukan elemen yang akan terlihat untuk mengkliknya. Itu tidak akan bergulir atas nama Anda.
Gili
5

Gunakan driver untuk mengirim kunci seperti pagedownatau downarrowkunci untuk membawa elemen ke tampilan. Saya tahu ini solusi yang terlalu sederhana dan mungkin tidak berlaku dalam semua kasus.

Ganesh S
sumber
1
Ini tidak masuk akal. Anda mungkin harus mengirim selusin halaman ke bawah pada halaman besar. Ini lambat dan tidak dapat diandalkan.
Elmue
2
Iya. Saya setuju. Tapi saya memang mengatakan "tidak berlaku dalam semua kasus"
Ganesh S
Menemukan beberapa yang diketahui elementdi halaman yang dapat dilihat dan mengirim PageDown element.SendKeys(Keys.PageDown);bekerja untuk saya.
Gokul
Saya menyarankan untuk menggunakan tombol Alt sehingga Anda tidak menggulir halaman dan menggunakan coba / kecuali (Python) klausa untuk menangani kesalahan yang dapat terjadi saat mencoba mengirim kunci ke beberapa elemen.
Alex K.
4

Dari pengalaman saya, Selenium Webdriver tidak otomatis menggulir ke elemen saat diklik ketika ada lebih dari satu bagian yang dapat digulir pada halaman (yang cukup umum).

Saya menggunakan Ruby, dan untuk AUT saya, saya harus menambal metode klik sebagai berikut;

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

Metode 'location_once_scrolled_into_view' adalah metode yang ada di kelas WebElement.

Saya menghargai Anda mungkin tidak menggunakan Ruby tetapi itu harus memberi Anda beberapa ide.

Robbie Wareham
sumber
Saya menyatakan di atas module Capybara :: module Node, dan saya perlu menelepon, native.location_once_scrolled_into_viewbukan hanya location_once_scrolled_into_view. Saya juga diselamatkan ::Selenium::WebDriver::Error::UnknownError, itulah yang sering saya dapatkan di Firefox 44.0.2. Tetapi saya menemukan solusi ini tidak cukup fleksibel dan pada akhirnya menempatkan <Element>.native.location_once_scrolled_into_viewpanggilan dalam tes penerimaan itu sendiri, segera diikuti oleh page.execute_script('window.scrollByPages(-1)')tempat yang diperlukan.
Al Chou
Watir memiliki metode Element#scroll_into_viewyang mendelegasikan ke Selenium's location_once_scrolled_into_view. Tetapi keduanya tidak berbeda dari perilaku default Selenium sehingga elemen overflow masih dapat menghalangi apa pun yang kita coba klik.
akostadinov
3

Script Ruby untuk menggulir elemen ke tampilan adalah seperti di bawah ini.

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

Terkadang saya juga menghadapi masalah bergulir dengan Selenium. Jadi saya menggunakan javaScriptExecuter untuk mencapai ini.

Untuk menggulir ke bawah:

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

Atau juga

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

Untuk menggulir ke atas:

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

Atau,

js.executeScript("scroll(0, -250);");
Anuraj R
sumber
2

Jika Anda berpikir jawaban lain terlalu rumit, yang ini terlalu, tetapi tidak ada injeksi JavaScript yang terlibat.

Ketika tombol dimatikan layar, itu rusak dan gulir ke sana, jadi coba lagi ... ¯ \ _ (ツ) _ / ¯

try
{
    element.Click();
}
catch {
    element.Click();
}
vicentedealencar
sumber
2

Ini adalah solusi berulang dengan JavaScript, tetapi dengan tambahan elemen yang menunggu.

Jika tidak, ElementNotVisibleExceptiondapat muncul jika beberapa tindakan pada elemen sedang dilakukan.

this.executeJavaScriptFunction("arguments[0].scrollIntoView(true);", elementToBeViewable);
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(ExpectedConditions.visibilityOf(elementToBeViewable));
Lukasz
sumber
?? <- apa artinya?
Choi
1

Saya telah menggunakan cara ini untuk menggulir elemen dan klik:

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
sumber
Dalam kasus saya, scrollIntoView(false)berhasil, tetapi scrollIntoView(true)tidak. Anda tidak dapat bekerja , itu tergantung pada skenario Anda.
rsenna
Kasus saya adalah sebaliknya - true works, false gagal, tetapi hanya sejauh klik. Itu memang gulir dengan benar untuk salah, dan itu yang saya sukai, tetapi untuk alasan apa pun Selenium masih tidak dapat melihatnya untuk klik. Menggunakan gulungan sejati semuanya terlalu tinggi, tetapi setidaknya itu berfungsi.
Bill Hileman
Sendkey pengguna masuk bukannya klik bila memungkinkan - itu menghindari masalah jika browser tidak 100% zoom.
Zunair
1
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}
omnomnom
sumber
1

Anda mungkin ingin mengunjungi halaman Gulir elemen Web dan halaman Web- Selenium WebDriver menggunakan 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);");
}
virusrocks
sumber
@AbhishekBedi Saya ingat bahwa itu didukung di Chrome juga. Adakah masalah khusus yang mungkin Anda hadapi?
virusrocks
1

Dalam sebagian besar situasi untuk menggulir kode ini akan berfungsi.

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

JAWA

Coba gulir ke elemen memanfaatkan x yposisi, dan gunakan JavascriptExecutordengan argumen ini:"window.scrollBy(x, y)" .

Impor berikut:

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

Pertama, Anda perlu mencari x ylokasi elemen.

//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
sumber
1

Saya tidak yakin apakah pertanyaannya masih relevan tetapi setelah merujuk ke dokumentasi scrollIntoView dari https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView .

Solusi termudah adalah

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

Ini menggulir elemen ke tengah halaman.

Kiranjith
sumber
0

Perilaku default Selenium kami untuk menggulir sehingga elemen tersebut nyaris tidak terlihat di bagian atas viewport. Juga, tidak semua browser memiliki perilaku yang sama persis. Ini sangat tidak memuaskan. Jika Anda merekam video dari tes browser Anda, seperti yang saya lakukan, yang Anda inginkan adalah elemen tersebut untuk menggulir ke tampilan dan dipusatkan secara vertikal .

Ini solusi saya untuk 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;
}

Dan kemudian, untuk menggulir, Anda menyebutnya seperti ini:

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
sumber
Fungsi getViewPortHeight tidak ada ... Dengan asumsi Anda mengambil ketinggian elemen target
Shubham Jain
0

Inilah cara saya melakukannya dengan PHP webDriver untuk Selenium. Ini berfungsi untuk server mandiri 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();

Catatan: Saya menggunakan versi kustom dari Element34 PHP-webdriver. Namun tidak ada perubahan pada intinya. Saya hanya menggunakan "selamat" bukan "elemen". Tapi itu tidak berpengaruh pada kasus tersebut. Penulis driver mengatakan "untuk memungkinkan hampir semua panggilan API menjadi transformasi langsung dari apa yang didefinisikan dalam protokol WebDriver itu sendiri." Jadi Anda seharusnya tidak memiliki masalah dengan bahasa pemrograman lain.

Mengklik saja tidak akan berfungsi di pengaturan saya. Ini akan melakukan gulir bukannya klik, jadi saya harus mengklik dua kali tanpa memanggil "location_in_view ()".

Catatan: Metode ini berfungsi untuk elemen yang dapat dilihat, seperti input tombol ketik.

Lihatlah: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location

Deskripsi untuk JsonWireProtocol # menyarankan penggunaan lokasi + moveto, karena lokasi _in_view adalah metode internal.

Konstantin Ivanov
sumber
0

Sesuatu yang berhasil bagi saya adalah menggunakan metode Browser.MoveMouseToElement pada elemen di bagian bawah jendela browser. Ajaibnya itu bekerja di Internet Explorer, Firefox, dan Chrome.

Saya memilih ini daripada teknik injeksi JavaScript hanya karena rasanya kurang hacky.

David Peters
sumber
Bahasa pemrograman mana ini?
akostadinov
0

Saya telah melakukan pengujian dengan komponen ADF dan Anda harus memiliki perintah terpisah untuk menggulir jika lazy loading digunakan. Jika objek tidak dimuat dan Anda berusaha menemukannya menggunakan Selenium, Selenium akan melempar pengecualian elemen-tidak-ditemukan.

pengguna3781490
sumber
0

Jika tidak ada yang berhasil, coba ini sebelum mengklik:

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
sumber
0

Di Jawa kita dapat menggulir dengan menggunakan JavaScript, seperti dalam kode berikut:

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

Anda dapat menetapkan nilai yang diinginkan ke variabel "elm.scrollTop".

Hemant
sumber
0

Solusinya adalah:

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
sumber
0

Kode ini berfungsi untuk saya:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");
vishal Singh
sumber
Bekerja untukku. Implementasi Dart WebDriver belum memiliki tindakan.
Günter Zöchbauer