如何在 Selenium 中將元素捲動到視圖中
1.概述
當使用 Selenium 自動化 Web 應用程式時,與螢幕外元素互動時經常會遇到挑戰。
Selenium 可能無法點擊或輸入元素,除非它們在視窗中可見。然而,在實際應用中,網頁通常包含過多元素,無法在一個螢幕上顯示。例如,我們可能會遇到較長的表單和表格,需要捲動才能有效地與它們互動。在這種情況下,我們需要一種可靠的方法將元素滾動到視圖中,理想情況下,將它們置於螢幕中央,以便於互動。
在本教程中,我們將探討如何在 Selenium 中將元素捲動到視圖中。
2.問題陳述
讓我們考慮自動化一個帶有三個輸入欄位的長 Web 表單:
-
firstName
:在頂部可見 -
middleName
:位於頁面中間某處 -
lastName
:顯示在底部
由於欄位之間分隔較大,導致某些元素在許多裝置上極有可能超出螢幕範圍。當欄位超出視野範圍時,Selenium 可能無法點擊或輸入,從而導致視覺驗證變得困難。
使用 Selenium 的預設scrollIntoView()
方法有時會產生不必要的結果:
- 將元素與視窗的頂部或底部對齊,而不是中心
- 將元素部分隱藏在黏性標題下
- 需要在多個地方重複滾動邏輯
然而,主要目標是將元素平滑地滾動到視口的垂直中心。為此,我們透過 Selenium JavascriptExecutor
使用 JavaScript 執行。
3. 設定項目
讓我們從建立一個簡單的 Maven 專案開始:
$ mvn archetype:generate -DgroupId=com.baeldung.scrollelementintoview \
-DartifactId=scrollelementintoview \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
以下是該專案的關鍵文件:
scrollelementintoview/
├── pom.xml
├── src
│ ├── main
│ │ ├── java/com/baeldung/scrollelementintoview/ScrollElementIntoView.java
│ │ └── resources/form.html
│ └── test
│ └── java/com/baeldung/scrollelementintoview/ScrollElementIntoViewUnitTest.java
...
此外,讓我們為pom.xml
檔案新增範例設定和依賴項:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Selenium Java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.25.0</version>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<!-- Update Surefire plugin to support JUnit 5 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin>
</plugins>
</build>
透過這些新增功能,我們包括用於瀏覽器自動化的 Selenium、用於編寫和運行測試的 JUnit 5
、用於編譯的 Java 17
配置、確保使用更新的 Surefire 插件正確執行測試,並保持一致的 UTF 8
編碼。
4.新增關鍵文件
因此,讓我們新增構成主要項目邏輯的文件。
4.1. HTML頁面
首先,我們建立form.html
檔案:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Long Form Example</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 0; }
.container { width: 50%; margin: auto; padding: 20px; }
label { margin-top: 20px; font-weight: bold; display: block; }
input, button { margin-top: 5px; padding: 10px; font-size: 16px; }
.spacer { height: 600px; } /* Simulate long form */
</style>
</head>
<body>
<div class="container">
<h1>Long Form Example</h1>
<label for="firstName">First Name:</label>
<input type="text" id="firstName" name="firstName">
<div class="spacer"></div>
<label for="middleName">Middle Name:</label>
<input type="text" id="middleName" name="middleName">
<div class="spacer"></div>
<label for="lastName">Last Name:</label>
<input type="text" id="lastName" name="lastName">
<div class="spacer"></div>
<button type="submit">Submit</button>
</div>
</body>
</html>
總而言之,上面的簡單 HTML 頁面模擬了一個長表單,其中有多個輸入字段,由大間隔符分隔。
4.2. 主類
接下來,讓我們建立主類別ScrollElementIntoView.java
:
package com.baeldung.scrollelementintoview;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.JavascriptExecutor;
import java.net.URL;
public class ScrollElementIntoView {
private WebDriver driver;
public void setUp() {
driver = new ChromeDriver();
driver.manage().window().maximize();
URL formUrl = getClass().getClassLoader().getResource("form.html");
if (formUrl != null) {
driver.get(formUrl.toString());
} else {
throw new RuntimeException("form.html not found in resources");
}
}
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
public void scrollToElementCenter(WebElement element) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(
"const rect = arguments[0].getBoundingClientRect();" +
"window.scrollBy({ top: rect.top + window.pageYOffset - (window.innerHeight / 2) + (rect.height / 2), behavior: 'smooth' });",
element
);
}
public void runDemo() throws InterruptedException {
WebElement firstName = driver.findElement(By.id("firstName"));
WebElement middleName = driver.findElement(By.id("middleName"));
WebElement lastName = driver.findElement(By.id("lastName"));
scrollToElementCenter(firstName);
Thread.sleep(1000);
firstName.sendKeys("John");
scrollToElementCenter(middleName);
Thread.sleep(1000);
middleName.sendKeys("William");
scrollToElementCenter(lastName);
Thread.sleep(1000);
lastName.sendKeys("Doe");
Thread.sleep(2000);
}
public WebDriver getDriver() {
return driver;
}
public static void main(String[] args) {
ScrollElementIntoView demo = new ScrollElementIntoView();
try {
demo.setUp();
demo.runDemo();
} catch (Exception e) {
e.printStackTrace();
} finally {
demo.tearDown();
}
}
}
現在,讓我們來看看該課程的細分:
-
new ChromeDriver()
:啟動一個新的 Chrome 瀏覽器實例來執行自動化 -
driver.manage().window().maximize()
:確保瀏覽器完全可見,以實現精確滾動 -
getClass().getClassLoader().getResource(“form.html”)
:直接從resources
目錄載入表單 -
JavascriptExecutor
:執行 JavaScript 以將元素精確地捲動到視窗的中心 -
window.scrollBy
:平滑地將視窗捲動到計算位置 -
Thread.sleep()
:新增延遲,以便我們可以在執行過程中直觀地觀察滾動 -
driver.quit()
:關閉瀏覽器並徹底結束會話
在這種情況下, JavascriptExecutor
介面使 Selenium 能夠在瀏覽器中運行自訂 JavaScript,從而使我們能夠精確控制滾動行為。因此,我們可以自動捲動表單欄位並在每個欄位中輸入文本,從而展示如何在與螢幕外的元素進行互動之前將其帶入視圖。
4.3. 測試類
此外,讓我們建立測試類別ScrollElementIntoViewUnitTest.java
:
package com.baeldung.scrollelementintoview;
import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import static org.junit.jupiter.api.Assertions.assertEquals;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ScrollElementIntoViewUnitTest {
private ScrollElementIntoView helper;
private WebDriver driver;
@BeforeAll
void init() {
helper = new ScrollElementIntoView();
helper.setUp();
driver = helper.getDriver();
}
@AfterAll
void tearDown() {
helper.tearDown();
}
@Test
@DisplayName("Should scroll and fill First Name field")
void givenFirstNameField_whenScrolledIntoView_thenFieldIsFilled() {
WebElement firstName = driver.findElement(By.id("firstName"));
helper.scrollToElementCenter(firstName);
firstName.sendKeys("John");
assertEquals("John", firstName.getAttribute("value"));
}
@Test
@DisplayName("Should scroll and fill Middle Name field")
void givenMiddleNameField_whenScrolledIntoView_thenFieldIsFilled() {
WebElement middleName = driver.findElement(By.id("middleName"));
helper.scrollToElementCenter(middleName);
middleName.sendKeys("William");
assertEquals("William", middleName.getAttribute("value"));
}
@Test
@DisplayName("Should scroll and fill Last Name field")
void givenLastNameField_whenScrolledIntoView_thenFieldIsFilled() {
WebElement lastName = driver.findElement(By.id("lastName"));
helper.scrollToElementCenter(lastName);
lastName.sendKeys("Doe");
assertEquals("Doe", lastName.getAttribute("value"));
}
}
這裡主要需要專注在三個部分:
-
givenFirstNameField_whenScrolledIntoView_thenFieldIsFilled
:將firstName
欄位捲動到檢視中,輸入「John”
,並驗證輸入 -
givenMiddleNameField_whenScrolledIntoView_thenFieldIsFilled
:將middleName
欄位捲動到檢視中,輸入「William”
,並驗證輸入 -
givenLastNameField_whenScrolledIntoView_thenFieldIsFilled
:將lastName
欄位捲動到檢視中,輸入「Doe”
,並驗證輸入
換句話說,測試驗證了我們可以使用 Selenium 將每個螢幕外的輸入欄位平滑地滾動到視圖中並與它們成功互動。
5. 運行項目和故障排除
此時,我們可以運行主類別來查看滾動效果:
$ mvn clean compile exec:java -Dexec.mainClass="com.baeldung.scrollelementintoview.ScrollElementIntoView"
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
此外,讓我們執行測試來確認一切正常:
$ mvn test
...
[INFO] Results:
[INFO]
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
有時,執行 Selenium 腳本可能會導致特定於環境的小錯誤,但修復起來相當簡單:
-
Browser doesn't open
:請驗證Google Chrome
和ChromeDriver
是否已正確安裝並在我們的系統 PATH 中可用 -
Element not found
:確保測試中的元素 ID 與form.html
中的元素 ID 匹配 -
File not loading
:確認form.html
存在於src/main/resources/
目錄下
透過遵循這些步驟,我們可以確保 Selenium 設定順利運行,並且滾動和互動邏輯在不同環境中按預期執行。
6. 結論
在本文中,我們示範如何使用 Selenium 將元素平滑地捲動到視窗的中心。
因此,我們利用 Selenium 來確保螢幕外元素完全可見且易於互動。因此,我們現在可以解決一些常見問題,例如元素在黏性標題下部分隱藏,或在視口內對齊不一致。此外,在處理較長或複雜的網頁時,自動化現在應該更加可靠且更易於預測。
與往常一樣,原始碼可在 GitHub 上取得。