1. 概述

本快速教程中,我们将学习如何利用 Selenium WebDriver 使用 JavaScript 模拟点击 HTML 元素。

在我们的示例中,我们将使用 JUnit 和 Selenium 打开 https://baeldung-cn.com 这个网站,并搜索关键字为 “Selenium” 的文章。

2. Mavn 依赖

First, we add the selenium-java and junit dependencies to our project in the pom.xml:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
</dependency>

3. 配置

Next, we need to configure WebDriver. In this example, we'll use its Chrome implementation:

@Before
public void setUp() {
    System.setProperty("webdriver.chrome.driver", new File("src/main/resources/chromedriver.mac").getAbsolutePath());
    driver = new ChromeDriver();
}

We're using a method annotated with @Before to do the initial setup before each test. Inside we're setting the webdriver.chrome.driver property defining the chrome driver location. After that, we're instantiating the WebDriver object.

When the test finishes we should close the browser window. We can do it by placing the driver.close() statement in a method annotated with @After. This makes sure it'll be executed even if the test fails:

@After
public void cleanUp() {
    driver.close();
}

4. 打开浏览器

Now, we can create a test case that will do our first step – open the website:

@Test
public void whenSearchForSeleniumArticles_thenReturnNotEmptyResults() {
    driver.get("https://baeldung.com");
    String title = driver.getTitle();
    assertEquals("Baeldung | Java, Spring and Web Development tutorials", title);
}

Here, we use the driver.get() method to load the webpage. Next, we verify its title to make sure we're in the right place.

5. 使用 JavaScript 点击元素

Selenium comes with a handy WebElement#click method that invokes a click event on a given element. But in some cases click action is not possible.

One example is if we want to click a disabled element. In that case, WebElement#click throws an IllegalStateException. Instead, we can use Selenium's JavaScript support.

To do this, the first thing that we'll need is the JavascriptExecutor. Since we are using the ChromeDriver implementation, we can simply cast it to what we need:

JavascriptExecutor executor = (JavascriptExecutor) driver;

After getting the JavascriptExecutor, we can use its executeScript method. The arguments are the script itself and an array of script parameters. In our case, we invoke the click method on the first argument:

executor.executeScript("arguments[0].click();", element);

Now, lets put it together into a single method that we'll call clickElement:

private void clickElement(WebElement element) {
    JavascriptExecutor executor = (JavascriptExecutor) driver;
    executor.executeScript("arguments[0].click();", element);
}

And finally, we can add this to our test:

@Test
public void whenSearchForSeleniumArticles_thenReturnNotEmptyResults() {
    // ... load https://baeldung.com
    WebElement searchButton = driver.findElement(By.className("nav--menu_item_anchor"));
    clickElement(searchButton);

    WebElement searchInput = driver.findElement(By.id("search"));
    searchInput.sendKeys("Selenium");

    WebElement seeSearchResultsButton = driver.findElement(By.cssSelector(".btn-search"));
    clickElement(seeSearchResultsButton);
}

6. 不可点击的元素

One of the most common problems occurring while clicking an element using JavaScript is executing the click script before the element is clickable. In this situation, the click action won't happen but the code will continue to execute.

To overcome this issue, we have to hold back the execution until the clicking is available. We can use WebDriverWait#until to wait until the button is rendered.

First, W**ebDriverWait object requires two parameters; the driver and a timeout:

WebDriverWait wait = new WebDriverWait(driver, 5000);

Then, we call until, giving the expected elementToBeClickable condition:

wait.until(ExpectedConditions.elementToBeClickable(By.className("nav--menu_item_anchor")));

And once that returns successfully, we know we can proceed:

WebElement searchButton = driver.findElement(By.className("nav--menu_item_anchor"));
clickElement(searchButton);

For more available condition methods refer to the official documentation.

7. 总结

In this tutorial, we've learned how to click an element in Selenium using JavaScript. As always, the source for the article is available over on GitHub.