Skip to content

Commit

Permalink
1. Upgrade to selenium version 4.27.0
Browse files Browse the repository at this point in the history
2. Add Firefox driver and Docker Firefox driver.
  • Loading branch information
jumperchen committed Nov 29, 2024
1 parent 236241b commit 8f21e22
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 22 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version=1.4.26.0.3
version=1.4.27.0.0

# dependencies
junitVersion=5.11.3
seleniumVersion=4.26.0
seleniumVersion=4.27.0
dockerJunitVersion=2.3.0
webdrivermanagerVersion=5.9.2
hamcrestVersion=3.0
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/org/zkoss/test/webdriver/BaseTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.support.ui.ExpectedConditions;
Expand Down Expand Up @@ -187,7 +188,7 @@ protected WebDriver getWebDriver() {
if (driver == null) {
ChromeOptions driverOptions = getWebDriverOptions();
driver = isUsingRemoteWebDriver(driverOptions)
? new DockerChromeRemoteWebDriver(getRemoteWebDriverUrl(), driverOptions)
? new DockerRemoteWebDriver(getRemoteWebDriverUrl(), driverOptions)
: new ChromiumHeadlessDriver(driverOptions, isHeadless());
}
return driver;
Expand All @@ -205,6 +206,9 @@ protected boolean isUseDocker() {
protected boolean isUsingRemoteWebDriver(ChromeOptions driverOptions) {
return isUseDocker();
}
protected boolean isUsingRemoteWebDriver(FirefoxOptions driverOptions) {
return isUseDocker();
}

/**
* Gets the WebDriver options.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/* DockerFirefoxDriverTestCase.java
Purpose:
Description:
History:
10:45 AM 2024/11/29, Created by jumperchen
Copyright (C) 2024 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.test.webdriver;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;

import com.palantir.docker.compose.DockerComposeExtension;
import com.palantir.docker.compose.configuration.ShutdownStrategy;
import com.palantir.docker.compose.connection.waiting.HealthChecks;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.api.parallel.ResourceLock;

/**
* A test case with a Firefox WebDriver running in a Docker container.
* @author jumperchen
*/
@ResourceLock("dockerResource")
public abstract class DockerFirefoxDriverTestCase extends FirefoxWebDriverTestCase {
// enable to use docker env.
protected final boolean isUseDocker() {
return true;
}


protected String getRemoteWebDriverUrl() {
final int externalPort = firefoxDocker.containers().container("hub").port(4444).getExternalPort();
return "http://localhost:" + externalPort + "/wd/hub";
}

protected FileLock globalLock;

private static final String tempDir = new SimpleDateFormat("yyyyMMdd").format(new java.util.Date());

// create a temp file for docker compose.yml
protected String exportResource(String file) {
InputStream resourceAsStream = ClassLoader.getSystemResourceAsStream(
"docker/docker-compose.yml");
try {
Path path = Paths.get(System.getProperty("java.io.tmpdir"), tempDir, "zkWebdriver").resolve(file);
if (!Files.isDirectory(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (path.toFile().exists()) {
path.toFile().delete();
}

// always copy the docker-compose.yml to the temp file
Files.copy(resourceAsStream, path, StandardCopyOption.REPLACE_EXISTING);

// try to acquire a global lock for each DockerWebDriver
RandomAccessFile files = new RandomAccessFile(path.toFile(), "rw");
FileChannel channel = files.getChannel();
while (true) {
try {
globalLock = channel.tryLock();
if (globalLock.isValid()) {
break;
}
} catch (Throwable e) {
// File is already locked in this thread or virtual machine
}
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
return path.toAbsolutePath().toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@AfterAll
public void unlockGlobalLock() {
if (globalLock != null) {
try {
globalLock.release();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

@RegisterExtension
public final DockerComposeExtension firefoxDocker = DockerComposeExtension.builder()
.file(exportResource("docker/docker-compose.yml"))
.useDockerComposeV2(Boolean.parseBoolean(System.getProperty("useDockerComposeV2", "true")))
.waitingForService("hub", HealthChecks.toRespondOverHttp(4444,
(port) -> port.inFormat("http://$HOST:$EXTERNAL_PORT/ui/index.html")))
.waitingForService("firefox", HealthChecks.toHaveAllPortsOpen())
.shutdownStrategy(ShutdownStrategy.KILL_DOWN)
.build();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* DockerChromeRemoteWebDriver.java
/* DockerRemoteWebDriver.java
Purpose:
Description:
History:
Thu Mar 26 11:11:20 CST 2020, Created by rudyhuang
Expand All @@ -28,12 +28,12 @@
* @see <a href="https://crbug.com/1010288">Chrome is not supporting --lang parameter with language that contains a '-' while using headless mode</a>
* @author rudyhuang
*/
public class DockerChromeRemoteWebDriver extends RemoteWebDriver {
public DockerChromeRemoteWebDriver(URL remoteAddress, Capabilities capabilities) {
public class DockerRemoteWebDriver extends RemoteWebDriver {
public DockerRemoteWebDriver(URL remoteAddress, Capabilities capabilities) {
super(remoteAddress, capabilities);
}

public DockerChromeRemoteWebDriver(String url, Capabilities capabilities) {
public DockerRemoteWebDriver(String url, Capabilities capabilities) {
this(toURL(url), capabilities);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected String getRemoteWebDriverUrl() {
private static final String tempDir = new SimpleDateFormat("yyyyMMdd").format(new java.util.Date());

// create a temp file for docker compose.yml
private String exportResource(String file) {
protected String exportResource(String file) {
InputStream resourceAsStream = ClassLoader.getSystemResourceAsStream(
"docker/docker-compose.yml");
try {
Expand Down
64 changes: 64 additions & 0 deletions src/main/java/org/zkoss/test/webdriver/FirefoxHeadlessDriver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* FirefoxHeadlessDriver.java
Purpose:
Description:
History:
10:36 AM 2024/11/29, Created by jumperchen
Copyright (C) 2024 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.test.webdriver;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxDriverService;
import org.openqa.selenium.firefox.FirefoxOptions;

/**
* A local running Firefox GeckoDriver. By default it runs in headless mode.
* @author jumperchen
*/
public class FirefoxHeadlessDriver extends FirefoxDriver {
static {
WebDriverManager.firefoxdriver().setup();
System.setProperty("webdriver.gecko.logfile", String.format("%s/geckodriver.log", System.getProperty("java.io.tmpdir")));
System.setProperty("webdriver.gecko.log.level", "debug");
}

public FirefoxHeadlessDriver() {
this(true);
}

public FirefoxHeadlessDriver(boolean headless) {
this(new FirefoxOptions(), headless);
}

public FirefoxHeadlessDriver(FirefoxOptions options) {
this(options, true);
}

public FirefoxHeadlessDriver(FirefoxOptions options, boolean headless) {
super(headlessSettings(options, headless));
}

public FirefoxHeadlessDriver(FirefoxDriverService service) {
this(service, new FirefoxOptions());
}

public FirefoxHeadlessDriver(FirefoxDriverService service, FirefoxOptions options) {
this(service, options, true);
}

public FirefoxHeadlessDriver(FirefoxDriverService service, FirefoxOptions options, boolean headless) {
super(service, headlessSettings(options, headless));
}

private static FirefoxOptions headlessSettings(FirefoxOptions options, boolean headless) {
if (headless) {
options.addArguments("--headless");
}
return options;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* FirefoxWebDriverTestCase.java
Purpose:
Description:
History:
2:00 PM 2024/11/29, Created by jumperchen
Copyright (C) 2024 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.test.webdriver;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxOptions;

/**
* A Firefox WebDriver test case.
* @author jumperchen
*/
public class FirefoxWebDriverTestCase extends WebDriverTestCase{

protected FirefoxOptions getFirefixOptions() {
FirefoxOptions options = new FirefoxOptions();

options.addArguments("--width=1920", "--height=1080");
options.addPreference("moz:firefoxOptions", "--remote-allow-origins=*");
return options;
}

protected WebDriver getWebDriver() {
if (driver == null) {
FirefoxOptions driverOptions = getFirefixOptions();
driver = isUsingRemoteWebDriver(driverOptions)
? new DockerRemoteWebDriver(getRemoteWebDriverUrl(), driverOptions)
: new FirefoxHeadlessDriver(getFirefixOptions(), isHeadless());
}
return driver;
}
}
24 changes: 12 additions & 12 deletions src/main/resources/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,9 @@ services:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443

# edge:
# image: selenium/node-edge:4.11.0-20230801
# shm_size: 2gb
# depends_on:
# - hub
# environment:
# - SE_EVENT_BUS_HOST=hub
# - SE_EVENT_BUS_PUBLISH_PORT=4442
# - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
#
# firefox:
# image: selenium/node-firefox:4.11.0-20230801
# edge:
# image: selenium/node-edge:latest
# shm_size: 2gb
# depends_on:
# - hub
Expand All @@ -32,6 +22,16 @@ services:
# - SE_EVENT_BUS_PUBLISH_PORT=4442
# - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

firefox:
image: selenium/node-firefox:latest
shm_size: 2gb
depends_on:
- hub
environment:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443

hub:
image: selenium/hub:latest
container_name: hub
Expand Down

0 comments on commit 8f21e22

Please sign in to comment.