2013-11-23 3240 views
8

當一個元素與硒不在一起時,一個人試圖與它交互時,硒通常會首先隱式地將元素滾動到視圖中。這很好,除了令人討厭的是它通常將元素放入視圖中。我的意思是,如果元素在窗口下面,它將向下滾動,直到元素剛好接近窗口的邊緣。selenium滾動元素到(視圖的中心)視圖

通常這是好的,但在網站上工作時,與它周圍的邊框,這將導致大量此類錯誤

Selenium::WebDriver::Error::UnknownError: 
     unknown error: Element is not clickable at point (438, 747). Other element would receive the click: <body>...</body> 

因爲平時網頁的邊框是超過它的,但無論如何都會嘗試點擊該元素。無論如何處理這個?也許會自動移動元素到屏幕的中心,當看不見?我正在考慮通過ruby來修補猴子。

回答

7

這應該爲了工作,以滾動的元素插入的視圖中心:

WebElement element = driver.findElement(By.xxx("xxxx")); 

String scrollElementIntoMiddle = "var viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);" 
              + "var elementTop = arguments[0].getBoundingClientRect().top;" 
              + "window.scrollBy(0, elementTop-(viewPortHeight/2));"; 

((JavascriptExecutor) driver).executeScript(scrollElementIntoMiddle, element); 
+0

謝謝。這個比scrollIntoView好 – bugCracker

0

您可以在這裏通過javascript使用顯式滾動操作。在這種情況下,您會發現元素(如果我正確理解您的問題,則此部分已經工作),然後將窗口滾動到指定的位置,然後與元素進行交互。

在java中,這將是:

WebElement element = driver.findElement(By.id("tabs")).findElement(By.className("youarehere")); 
Point p = element.getLocation(); 
((JavascriptExecutor) driver).executeScript("window.scroll(" + p.getX() + "," + (p.getY() + 200) + ");"); 
0

下面的代碼將滾動,直到元素在視圖,

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

這是一個很好的建議,但後來我不得不爲我排在接觸的每一個元素做到這一點。我正在尋找一種適用於整個會話的方法 – mango

3

是的,它可以自動滾動瀏覽器,使我們與之交互的任何元素都在窗口中居中。我有以下工作示例,書面和使用硒的webdriver-2.41.0和Firefox 28

完全披露在紅寶石測試:您可能需要編輯代碼略有的部分得到這個正常工作。接下來的解釋。

Selenium::WebDriver::Mouse.class_eval do 
    # Since automatic centering of elements can be time-expensive, we disable 
    # this behavior by default and allow it to be enabled as-needed. 
    self.class_variable_set(:@@keep_elements_centered, false) 

    def self.keep_elements_centered=(enable) 
    self.class_variable_set(:@@keep_elements_centered, enable) 
    end 

    def self.keep_elements_centered 
    self.class_variable_get(:@@keep_elements_centered) 
    end 

    # Uses javascript to attempt to scroll the desired element as close to the 
    # center of the window as possible. Does nothing if the element is already 
    # more-or-less centered. 
    def scroll_to_center(element) 
    element_scrolled_center_x = element.location_once_scrolled_into_view.x + element.size.width/2 
    element_scrolled_center_y = element.location_once_scrolled_into_view.y + element.size.height/2 

    window_pos = @bridge.getWindowPosition 
    window_size = @bridge.getWindowSize 
    window_center_x = window_pos[:x] + window_size[:width]/2 
    window_center_y = window_pos[:y] + window_size[:height]/2 

    scroll_x = element_scrolled_center_x - window_center_x 
    scroll_y = element_scrolled_center_y - window_center_y 

    return if scroll_x.abs < window_size[:width]/4 && scroll_y.abs < window_size[:height]/4 

    @bridge.executeScript("window.scrollBy(#{scroll_x}, #{scroll_y})", ""); 
    sleep(0.5) 
    end 

    # Create a new reference to the existing function so we can re-use it. 
    alias_method :base_move_to, :move_to 

    # After Selenium does its own mouse motion and scrolling, do ours. 
    def move_to(element, right_by = nil, down_by = nil) 
    base_move_to(element, right_by, down_by) 
    scroll_to_center(element) if self.class.keep_elements_centered 
    end 
end 

推薦用法:

在任何的代碼段上,其中元件是通常離屏的開始啓用自動定心,則之後將其禁用。

注意:此代碼似乎不適用於鏈式操作。例如:

driver.action.move_to(element).click.perform 

滾動修復似乎不更新click位置。在上面的例子中,它會點擊元素的預滾動位置,產生錯誤點擊。

爲什麼move_to

我選擇了move_to,因爲大多數基於鼠標的操作都使用它,並且在此步驟中會出現Selenium現有的「滾動到視圖」行爲。這個特定的補丁不適用於任何在某個級別上不會調用move_to的鼠標交互,也不期望它可以與任何鍵盤交互一起工作,但理論上,如果您包裝正確的函數,類似的方法也應該起作用。

爲什麼sleep

我不確定爲什麼在通過executeScript滾動後需要sleep命令。通過我的特殊設置,我可以刪除sleep命令,它仍然有效。 Similar examplesother developers'網絡包括sleep命令延遲範圍從0.1到3秒。作爲一個瘋狂的猜測,我會說這是爲了交叉兼容性的原因。

如果我不想猴子補丁怎麼辦?

正如你所建議的那樣,理想的解決方案是改變Selenium的「滾動到視圖」行爲,但我相信這種行爲是由selenium-webdriver gem以外的代碼控制的。在路徑變冷之前,我一直追溯到Bridge

對於猴子補丁厭惡的scroll_to_center法正常工作,與一些換人的獨立方法,其中driver是您Selenium::WebDriver::Driver例如:

  • driver.manage.window.position而不是 @bridge.getWindowPosition
  • driver.manage.window.size,而不是 @bridge.getWindowSize
  • driver.execute_script而不是 @bridge.executeScript