Skip to content

Commit 6e153f8

Browse files
committed
Wait for extension recording and get path from WebDriverManager API
1 parent 92bf8a6 commit 6e153f8

File tree

7 files changed

+188
-74
lines changed

7 files changed

+188
-74
lines changed

pom.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
24
<modelVersion>4.0.0</modelVersion>
35

46
<groupId>io.github.bonigarcia</groupId>
@@ -14,6 +16,7 @@
1416
<commons-lang3.version>3.17.0</commons-lang3.version>
1517
<commons-compress.version>1.27.1</commons-compress.version>
1618
<httpclient5.version>5.4.3</httpclient5.version>
19+
<jna-platform.version>5.13.0</jna-platform.version>
1720

1821
<!-- provided -->
1922
<selenium.version>4.31.0</selenium.version>
@@ -145,6 +148,11 @@
145148
<artifactId>httpclient5</artifactId>
146149
<version>${httpclient5.version}</version>
147150
</dependency>
151+
<dependency>
152+
<groupId>net.java.dev.jna</groupId>
153+
<artifactId>jna-platform</artifactId>
154+
<version>${jna-platform.version}</version>
155+
</dependency>
148156

149157
<dependency>
150158
<groupId>org.seleniumhq.selenium</groupId>

src/main/java/io/github/bonigarcia/wdm/WebDriverManager.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,19 @@ public void stopRecording() {
10551055
webDriverList.get(0).stopRecording();
10561056
}
10571057

1058+
public Path getRecordingPath() {
1059+
return webDriverList.get(0).getRecordingPath();
1060+
}
1061+
1062+
public Path getRecordingPath(WebDriver driver) {
1063+
Optional<WebDriverBrowser> webDriverBrowser = findWebDriverBrowser(
1064+
driver);
1065+
if (webDriverBrowser.isPresent()) {
1066+
return webDriverBrowser.get().getRecordingPath();
1067+
}
1068+
return null;
1069+
}
1070+
10581071
@SuppressWarnings("unchecked")
10591072
public List<Map<String, Object>> getLogs(WebDriver driver) {
10601073
List<Map<String, Object>> logs = new ArrayList<>();
@@ -1757,7 +1770,9 @@ protected synchronized WebDriver instantiateDriver() {
17571770
.orElse(getCapabilities());
17581771
driver = getWebDriverCreator()
17591772
.createRemoteWebDriver(remoteAddress, caps);
1760-
webDriverList.add(new WebDriverBrowser(driver));
1773+
webDriverList.add(new WebDriverBrowser(driver,
1774+
getDriverManagerType().getBrowserNameLowerCase(),
1775+
config().getOperatingSystem()));
17611776

17621777
} else {
17631778
driver = createLocalWebDriver();
@@ -1895,7 +1910,9 @@ protected WebDriver createDockerWebDriver() {
18951910
browserContainer.setBrowserName(browserName);
18961911
String seleniumServerUrl = browserContainer.getContainerUrl();
18971912

1898-
WebDriverBrowser driverBrowser = new WebDriverBrowser();
1913+
WebDriverBrowser driverBrowser = new WebDriverBrowser(
1914+
getDriverManagerType().getBrowserNameLowerCase(),
1915+
config().getOperatingSystem());
18991916
driverBrowser.addDockerContainer(browserContainer);
19001917
driverBrowser.setSeleniumServerUrl(seleniumServerUrl);
19011918
log.trace("The Selenium Server URL is {}", seleniumServerUrl);
@@ -1956,7 +1973,10 @@ protected synchronized WebDriver createLocalWebDriver()
19561973
: Class.forName(managerType.browserClass());
19571974
driver = getWebDriverCreator().createLocalWebDriver(browserClass,
19581975
capabilities);
1959-
webDriverList.add(new WebDriverBrowser(driver));
1976+
1977+
webDriverList.add(new WebDriverBrowser(driver,
1978+
getDriverManagerType().getBrowserNameLowerCase(),
1979+
config().getOperatingSystem()));
19601980
}
19611981
return driver;
19621982
}

src/main/java/io/github/bonigarcia/wdm/docker/DockerService.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@
3737
import java.net.URI;
3838
import java.nio.file.Path;
3939
import java.nio.file.Paths;
40-
import java.text.SimpleDateFormat;
4140
import java.time.Duration;
4241
import java.util.ArrayList;
4342
import java.util.Arrays;
44-
import java.util.Date;
4543
import java.util.List;
4644
import java.util.Optional;
4745
import java.util.UUID;
@@ -85,6 +83,7 @@
8583
import io.github.bonigarcia.wdm.config.WebDriverManagerException;
8684
import io.github.bonigarcia.wdm.docker.DockerContainer.DockerBuilder;
8785
import io.github.bonigarcia.wdm.versions.VersionComparator;
86+
import io.github.bonigarcia.wdm.webdriver.Recording;
8887

8988
/**
9089
* Docker Service.
@@ -106,9 +105,6 @@ public class DockerService {
106105
private static final String BETA = "beta";
107106
private static final String DEV = "dev";
108107
private static final String LATEST_MINUS = LATEST + "-";
109-
private static final String RECORDING_EXT = ".mp4";
110-
private static final String SEPARATOR = "_";
111-
private static final String DATE_FORMAT = "yyyy.MM.dd_HH.mm.ss.SSS";
112108
private static final int POLL_TIME_MSEC = 500;
113109

114110
private Config config;
@@ -788,15 +784,12 @@ public Path getRecordingPath(DockerContainer browserContainer) {
788784
Path dockerRecordingPath = config.getDockerRecordingOutput();
789785

790786
if (dockerRecordingPath.toString().toLowerCase(ROOT)
791-
.endsWith(RECORDING_EXT)) {
787+
.endsWith(Recording.DOCKER_RECORDING_EXT)) {
792788
recordingPath = dockerRecordingPath;
793789
} else {
794-
String sessionId = browserContainer.getSessionId();
795-
Date now = new Date();
796-
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
797-
String recordingFileName = browserContainer.getBrowserName()
798-
+ SEPARATOR + dateFormat.format(now) + SEPARATOR + sessionId
799-
+ RECORDING_EXT;
790+
String recordingFileName = Recording.getRecordingNameForDocker(
791+
browserContainer.getBrowserName(),
792+
browserContainer.getSessionId());
800793
String prefix = config.getDockerRecordingPrefix();
801794
if (!isNullOrEmpty(prefix)) {
802795
recordingFileName = prefix + recordingFileName;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* (C) Copyright 2025 Boni Garcia (https://bonigarcia.github.io/)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
package io.github.bonigarcia.wdm.webdriver;
18+
19+
import java.text.SimpleDateFormat;
20+
import java.util.Date;
21+
22+
/**
23+
* Recording naming shared logic.
24+
*
25+
* @author Boni Garcia
26+
* @since 6.1.0
27+
*/
28+
public class Recording {
29+
30+
public static final String DOCKER_RECORDING_EXT = ".mp4";
31+
public static final String EXTENSION_RECORDING_EXT = ".webm";
32+
private static final String SEPARATOR = "_";
33+
private static final String DATE_FORMAT = "yyyy.MM.dd_HH.mm.ss.SSS";
34+
35+
public static String getRecordingName(String browserName,
36+
String sessionId) {
37+
Date now = new Date();
38+
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
39+
return browserName + SEPARATOR + dateFormat.format(now) + SEPARATOR
40+
+ sessionId;
41+
}
42+
43+
public static String getRecordingNameForDocker(String browserName,
44+
String sessionId) {
45+
return getRecordingNameForDocker(browserName, sessionId)
46+
+ DOCKER_RECORDING_EXT;
47+
}
48+
49+
}

src/main/java/io/github/bonigarcia/wdm/webdriver/WebDriverBrowser.java

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,24 @@
2121

2222
import java.net.MalformedURLException;
2323
import java.net.URL;
24+
import java.nio.file.Files;
2425
import java.nio.file.Path;
26+
import java.nio.file.Paths;
27+
import java.time.Duration;
28+
import java.time.Instant;
2529
import java.util.ArrayList;
2630
import java.util.List;
2731
import java.util.Map;
2832

2933
import org.openqa.selenium.JavascriptExecutor;
3034
import org.openqa.selenium.WebDriver;
35+
import org.openqa.selenium.remote.RemoteWebDriver;
3136
import org.slf4j.Logger;
3237

38+
import com.sun.jna.platform.win32.KnownFolders;
39+
import com.sun.jna.platform.win32.Shell32Util;
40+
41+
import io.github.bonigarcia.wdm.config.OperatingSystem;
3342
import io.github.bonigarcia.wdm.docker.DockerContainer;
3443

3544
/**
@@ -42,7 +51,16 @@ public class WebDriverBrowser {
4251

4352
final Logger log = getLogger(lookup().lookupClass());
4453

54+
final String DEFAULT_DOWNLOADS_FOLDER = "Downloads";
55+
final String LINUX_ENV_DOWNLOAD_DIR = "XDG_DOWNLOAD_DIR";
56+
final String USER_HOME_PROPERTY = "user.home";
57+
static final int RECORDING_TIMEOUT_SEC = 5;
58+
static final int POLL_TIME_MSEC = 500;
59+
4560
WebDriver driver;
61+
String recordingName;
62+
String browserName;
63+
OperatingSystem os;
4664
List<DockerContainer> dockerContainerList;
4765
String browserContainerId;
4866
String noVncUrl;
@@ -51,12 +69,17 @@ public class WebDriverBrowser {
5169
Path recordingPath;
5270
int identityHash;
5371

54-
public WebDriverBrowser() {
72+
public WebDriverBrowser(String browserName, OperatingSystem os) {
73+
this.browserName = browserName;
74+
this.os = os;
5575
this.dockerContainerList = new ArrayList<>();
5676
}
5777

58-
public WebDriverBrowser(WebDriver driver) {
78+
public WebDriverBrowser(WebDriver driver, String browserName,
79+
OperatingSystem os) {
5980
super();
81+
this.browserName = browserName;
82+
this.os = os;
6083
setDriver(driver);
6184
}
6285

@@ -155,11 +178,13 @@ public Object executeJavaScript(String jsCommand) {
155178
}
156179

157180
public void startRecording() {
158-
((JavascriptExecutor) driver).executeScript(
159-
"window.postMessage({ type: \"startRecording\" });");
181+
String recordingName = Recording.getRecordingName(browserName,
182+
((RemoteWebDriver) driver).getSessionId().toString());
183+
startRecording(recordingName);
160184
}
161185

162186
public void startRecording(String recordingName) {
187+
setRecordingName(recordingName);
163188
((JavascriptExecutor) driver).executeScript(
164189
"window.postMessage({ type: \"startRecording\", name: \""
165190
+ recordingName + "\" }, \"*\");");
@@ -168,6 +193,63 @@ public void startRecording(String recordingName) {
168193
public void stopRecording() {
169194
((JavascriptExecutor) driver).executeScript(
170195
"window.postMessage({ type: \"stopRecording\" }, \"*\");");
196+
waitForRecording();
197+
}
198+
199+
public Path getDownloadsFolderPath() {
200+
Path downloadsPath;
201+
if (os.isWin()) {
202+
downloadsPath = Paths.get(Shell32Util
203+
.getKnownFolderPath(KnownFolders.FOLDERID_Downloads));
204+
} else if (os.isMac()) {
205+
downloadsPath = Paths.get(System.getProperty(USER_HOME_PROPERTY),
206+
DEFAULT_DOWNLOADS_FOLDER);
207+
} else {
208+
String xdgDownloadDir = System.getenv(LINUX_ENV_DOWNLOAD_DIR);
209+
if (xdgDownloadDir != null && !xdgDownloadDir.isEmpty()) {
210+
downloadsPath = Paths.get(xdgDownloadDir);
211+
} else {
212+
downloadsPath = Paths.get(
213+
System.getProperty(USER_HOME_PROPERTY),
214+
DEFAULT_DOWNLOADS_FOLDER);
215+
}
216+
}
217+
return downloadsPath;
218+
}
219+
220+
public boolean waitForRecording() {
221+
Path downloadsPath = getDownloadsFolderPath();
222+
Path filePath = Paths.get(downloadsPath.toString(), getRecordingName());
223+
Instant start = Instant.now();
224+
Duration timeout = Duration.ofSeconds(RECORDING_TIMEOUT_SEC);
225+
log.trace("Waiting for recording at {}", filePath);
226+
227+
while (true) {
228+
if (Files.exists(filePath)) {
229+
log.debug("Recording found at {}", filePath);
230+
setRecordingPath(filePath);
231+
return true;
232+
}
233+
if (Duration.between(start, Instant.now()).compareTo(timeout) > 0) {
234+
log.warn(
235+
"Timeout of {} seconds reached, recording {} not found",
236+
RECORDING_TIMEOUT_SEC, filePath);
237+
return false;
238+
}
239+
try {
240+
Thread.sleep(POLL_TIME_MSEC);
241+
} catch (InterruptedException e) {
242+
Thread.currentThread().interrupt();
243+
}
244+
}
245+
}
246+
247+
public String getRecordingName() {
248+
return recordingName + Recording.EXTENSION_RECORDING_EXT;
249+
}
250+
251+
public void setRecordingName(String recordingName) {
252+
this.recordingName = recordingName;
171253
}
172254

173255
}

src/test/java/io/github/bonigarcia/wdm/test/watcher/RecordChromeTest.java

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818

1919
//tag::snippet-in-doc[]
2020
import static java.lang.invoke.MethodHandles.lookup;
21-
import static org.assertj.core.api.Assertions.fail;
21+
import static org.assertj.core.api.Assertions.assertThat;
2222
import static org.slf4j.LoggerFactory.getLogger;
2323

24-
import java.io.File;
24+
import java.nio.file.Path;
2525
import java.time.Duration;
26-
import java.util.concurrent.TimeUnit;
2726

2827
import org.junit.jupiter.api.AfterEach;
2928
import org.junit.jupiter.api.BeforeEach;
@@ -40,19 +39,13 @@ class RecordChromeTest {
4039

4140
static final Logger log = getLogger(lookup().lookupClass());
4241

43-
static final int REC_TIMEOUT_SEC = 10;
44-
static final int POLL_TIME_MSEC = 100;
45-
static final String REC_FILENAME = "myRecordingChrome";
46-
static final String REC_EXT = ".webm";
47-
4842
WebDriver driver;
49-
File targetFolder;
50-
WebDriverManager wdm = WebDriverManager.chromedriver().watch();
43+
WebDriverManager wdm;
5144

5245
@BeforeEach
5346
void setup() {
47+
wdm = WebDriverManager.chromedriver().watch();
5448
driver = wdm.create();
55-
targetFolder = new File(System.getProperty("user.home"), "Downloads");
5649
}
5750

5851
@AfterEach
@@ -65,7 +58,7 @@ void test() throws InterruptedException {
6558
driver.get(
6659
"https://bonigarcia.dev/selenium-webdriver-java/slow-calculator.html");
6760

68-
wdm.startRecording(REC_FILENAME);
61+
wdm.startRecording();
6962

7063
// 1 + 3
7164
driver.findElement(By.xpath("//span[text()='1']")).click();
@@ -79,22 +72,10 @@ void test() throws InterruptedException {
7972

8073
wdm.stopRecording();
8174

82-
long timeoutMs = System.currentTimeMillis()
83-
+ TimeUnit.SECONDS.toMillis(REC_TIMEOUT_SEC);
84-
85-
File recFile;
86-
do {
87-
recFile = new File(targetFolder, REC_FILENAME + REC_EXT);
88-
if (System.currentTimeMillis() > timeoutMs) {
89-
fail("Timeout of " + REC_TIMEOUT_SEC
90-
+ " seconds waiting for recording " + recFile);
91-
break;
92-
}
93-
Thread.sleep(POLL_TIME_MSEC);
94-
95-
} while (!recFile.exists());
75+
Path recordingPath = wdm.getRecordingPath();
76+
assertThat(recordingPath).exists();
9677

97-
log.debug("Recording available at {}", recFile);
78+
log.debug("Recording available at {}", recordingPath);
9879
}
9980

10081
}

0 commit comments

Comments
 (0)