Skip to content

Commit 3d8334b

Browse files
authored
feat(cloud): add LambdaTest provider support (#223)
* feat(cloud): add LambdaTest provider support * fix(cloud): address LambdaTest review feedback
1 parent b58ac2d commit 3d8334b

13 files changed

Lines changed: 365 additions & 10 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1111

1212
- **Fix: `@PreCondition` session restore on a fresh browser** — the cached cookies and localStorage were silently dropped when the next test started on `about:blank`, so only the first test per thread was logged in. Restore now navigates to the origin the session was captured on first.
1313

14+
- **LambdaTest cloud provider** — `execution.mode: lambdatest` now creates W3C
15+
`LT:Options` sessions, supports environment-based credentials and capability
16+
overrides, and links each cloud session from the HTML report. (#197)
17+
18+
- **Cloud execution mode validation** — `execution.mode` now accepts the
19+
existing `browserstack` and `saucelabs` providers, alongside `local`,
20+
`remote`, and the new `lambdatest` provider.
21+
1422
- **Trace shows browser console errors** — when `browser.captureConsoleErrors: true`, the JS errors collected for a test now appear in its trace file under "Console Errors", next to the steps and failure details, so a shared trace includes what the browser logged. No change when the option is off. (#130)
1523

1624
- **Network mocking on Firefox via WebDriver BiDi** — `networkMock().stub(...)` now uses WebDriver BiDi network interception under the hood when supported by the driver (including Firefox and BiDi-enabled drivers), falling back to Chrome DevTools Protocol (CDP) for Chromium-based drivers. The existing stubbing API (`returnJson`, `returnBody`, `returnStatus`, `delay`, `clear`) works identically across Chrome and Firefox. (#196)

‎docs-site/docs/changelog.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ All notable changes to Selenium Boot are documented here.
1111

1212
## [Unreleased]
1313

14+
- **LambdaTest cloud provider** — `execution.mode: lambdatest` now creates W3C
15+
`LT:Options` sessions, supports environment-based credentials and capability
16+
overrides, and links each cloud session from the HTML report. (#197)
17+
18+
- **Cloud execution mode validation** — `execution.mode` now accepts the
19+
existing `browserstack` and `saucelabs` providers, alongside `local`,
20+
`remote`, and the new `lambdatest` provider.
21+
1422
- **Trace shows browser console errors** — when `browser.captureConsoleErrors: true`, the JS errors collected for a test now appear in its trace file under "Console Errors", next to the steps and failure details, so a shared trace includes what the browser logged. No change when the option is off. (#130)
1523

1624
- **Network mocking on Firefox via WebDriver BiDi** — `networkMock().stub(...)` now uses WebDriver BiDi network interception under the hood when supported by the driver (including Firefox and BiDi-enabled drivers), falling back to Chrome DevTools Protocol (CDP) for Chromium-based drivers. The existing stubbing API (`returnJson`, `returnBody`, `returnStatus`, `delay`, `clear`) works identically across Chrome and Firefox. (#196)

‎docs-site/docs/cloud-execution.md‎

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
---
2-
description: "Run Selenium tests on BrowserStack and Sauce Labs with zero code changes. Switch from local Chrome to cloud browsers by editing one config line."
2+
description: "Run Selenium tests on BrowserStack, Sauce Labs, and LambdaTest with zero code changes. Switch from local Chrome to cloud browsers by editing one config line."
33
id: cloud-execution
44
title: Cloud Execution
55
sidebar_position: 12
66
---
77

88
# Cloud Execution
99

10-
Selenium Boot supports running your test suite on **BrowserStack** and **Sauce Labs** with zero test-code changes. Switch from local Chrome to a cloud browser farm by changing one line in `selenium-boot.yml`.
10+
Selenium Boot supports running your test suite on **BrowserStack**, **Sauce Labs**, and **LambdaTest** with zero test-code changes. Switch from local Chrome to a cloud browser farm by changing one line in `selenium-boot.yml`.
1111

1212
:::caution Requires Selenium Boot 3.2.1+
13-
Cloud execution (`execution.mode: browserstack` or `saucelabs`) requires **Selenium Boot 3.2.1 or later**. It does not work in any earlier release — config loading rejects any `execution.mode` other than `local` or `remote` at startup — regardless of what the examples on this page show.
13+
Cloud execution (`execution.mode: browserstack`, `saucelabs`, or `lambdatest`) requires **Selenium Boot 3.2.1 or later**.
1414
:::
1515

1616
---
@@ -25,6 +25,7 @@ All four execution modes share the same driver lifecycle — tests use `getDrive
2525
| `remote` | Your own Selenium Grid / Selenoid / Moon |
2626
| `browserstack` | BrowserStack Automate cloud |
2727
| `saucelabs` | Sauce Labs cloud |
28+
| `lambdatest` | LambdaTest cloud |
2829

2930
---
3031

@@ -242,6 +243,64 @@ Ensure your BrowserStack / Sauce Labs plan allows the number of concurrent sessi
242243

243244
---
244245

246+
## LambdaTest
247+
248+
### Prerequisites
249+
250+
1. Sign up at [lambdatest.com](https://www.lambdatest.com)
251+
2. Copy your LambdaTest username and access key from your account settings
252+
253+
### Config
254+
255+
```yaml title="selenium-boot.yml"
256+
execution:
257+
mode: lambdatest
258+
lambdatest:
259+
username: ${LT_USERNAME}
260+
accessKey: ${LT_ACCESS_KEY}
261+
platform: "Windows 11"
262+
browser: chrome
263+
browserVersion: latest
264+
265+
browser:
266+
name: chrome
267+
268+
timeouts:
269+
explicit: 10
270+
pageLoad: 30
271+
```
272+
273+
The provider uses LambdaTest's W3C `LT:Options` capability and the
274+
`https://hub.lambdatest.com/wd/hub` hub URL. Keys under `capabilities` are
275+
merged into `LT:Options`, so they override the generated defaults:
276+
277+
```yaml
278+
execution:
279+
mode: lambdatest
280+
lambdatest:
281+
username: ${LT_USERNAME}
282+
accessKey: ${LT_ACCESS_KEY}
283+
platform: "Windows 11"
284+
browser: chrome
285+
browserVersion: latest
286+
capabilities:
287+
build: "v2.1.0"
288+
video: true
289+
```
290+
291+
Set environment variables before running:
292+
293+
```bash
294+
export LT_USERNAME=your_username
295+
export LT_ACCESS_KEY=your_access_key
296+
mvn test
297+
```
298+
299+
After each test, the HTML report includes a **☁ View Session** link to the
300+
LambdaTest session logs.
301+
302+
---
303+
245304
## Switching between environments
246305

247306
Use Maven profiles or environment variables to switch execution targets without changing any YAML file:
@@ -265,7 +324,7 @@ Keep separate YAML files per environment — each imports shared settings and on
265324

266325
```yaml title="selenium-boot.yml"
267326
execution:
268-
mode: browserstack # local | remote | browserstack | saucelabs
327+
mode: browserstack # local | remote | browserstack | saucelabs | lambdatest
269328
270329
# ── BrowserStack ───────────────────────────────────────────────
271330
browserstack:
@@ -292,6 +351,16 @@ execution:
292351
capabilities: # raw sauce:options overrides
293352
recordVideo: true
294353
354+
# ── LambdaTest ─────────────────────────────────────────────────
355+
lambdatest:
356+
username: ${LT_USERNAME}
357+
accessKey: ${LT_ACCESS_KEY}
358+
platform: "Windows 11"
359+
browser: chrome
360+
browserVersion: latest
361+
capabilities: # raw LT:Options overrides
362+
video: true
363+
295364
browser:
296365
name: chrome
297366

‎docs-site/docs/configuration.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ browser:
6262

6363
# ── Execution ───────────────────────────────────────────────────────────────
6464
execution:
65-
mode: local # local | remote | browserstack | saucelabs
65+
mode: local # local | remote | browserstack | saucelabs | lambdatest
6666
baseUrl: https://your-app.com
6767
gridUrl: http://localhost:4444 # only for remote mode
6868

‎docs-site/docs/intro.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Outcomes first — the API that delivers each one is on the right so you can jum
118118
| **Verify what actually landed in the DB** | `db().assertRowExists()`, `db().query().assertValue()` — plain JDBC, no ORM |
119119
| **Assert on the email your app sent** | `mailbox().waitForEmail(to("user@test.com"))` — Mailhog, Mailtrap, Outlook, IMAP |
120120
| **Skip the browser for non-UI tests** | `@NoBrowser` — DB assertions, API checks, file operations, no WebDriver |
121-
| **Run on real cloud browsers unchanged** | `execution.mode: browserstack` / `saucelabs` — session URL in HTML report |
121+
| **Run on real cloud browsers unchanged** | `execution.mode: browserstack` / `saucelabs` / `lambdatest` — session URL in HTML report |
122122
| **Understand failures without digging** | AI failure analysis — Claude explains why a test failed and suggests a fix |
123123
| **Locators that repair themselves** | Self-healing fallback strategies when a locator fails |
124124
| **Know which tests will flake next** | Flakiness prediction — risk scores from run history, radar chart in report |

‎docs-site/docs/quarantine.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ A committed YAML file solves this cleanly:
4343
| Survives fresh clones | ✅ — it's in git |
4444
| No external services needed | ✅ — just a YAML file |
4545
| Auditable | ✅ — changes go through PRs |
46-
| Works with all execution modes | ✅ — local, remote, BrowserStack, Sauce Labs |
46+
| Works with all execution modes | ✅ — local, remote, BrowserStack, Sauce Labs, LambdaTest |
4747
| Works across team members | ✅ — everyone gets the same list |
4848

4949
---

‎src/main/java/com/seleniumboot/config/ConfigurationLoader.java‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,14 @@ private static void validate(SeleniumBootConfig config) {
163163
}
164164

165165
String mode = config.getExecution().getMode();
166-
if (!"local".equalsIgnoreCase(mode) && !"remote".equalsIgnoreCase(mode)) {
166+
if (!"local".equalsIgnoreCase(mode)
167+
&& !"remote".equalsIgnoreCase(mode)
168+
&& !"browserstack".equalsIgnoreCase(mode)
169+
&& !"saucelabs".equalsIgnoreCase(mode)
170+
&& !"lambdatest".equalsIgnoreCase(mode)) {
167171
throw new IllegalStateException(
168-
"execution.mode must be 'local' or 'remote', got: '" + mode + "'");
172+
"execution.mode must be 'local', 'remote', 'browserstack', "
173+
+ "'saucelabs', or 'lambdatest', got: '" + mode + "'");
169174
}
170175

171176
if (config.getTimeouts() == null

‎src/main/java/com/seleniumboot/config/SeleniumBootConfig.java‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@ public void setMaxActiveSessions(int maxActiveSessions) {
226226

227227
private BrowserStack browserstack = new BrowserStack();
228228
private SauceLabs saucelabs = new SauceLabs();
229+
private LambdaTest lambdatest = new LambdaTest();
230+
231+
public LambdaTest getLambdatest() {return lambdatest;}
232+
public void setLambdatest(LambdaTest v) {this.lambdatest = v;}
229233

230234
public BrowserStack getBrowserstack() { return browserstack; }
231235
public void setBrowserstack(BrowserStack v) { this.browserstack = v; }
@@ -287,6 +291,28 @@ public static final class SauceLabs {
287291
public java.util.Map<String, Object> getCapabilities() { return capabilities; }
288292
public void setCapabilities(java.util.Map<String, Object> v) { this.capabilities = v != null ? v : new java.util.LinkedHashMap<>(); }
289293
}
294+
295+
public static final class LambdaTest {
296+
private String username;
297+
private String accessKey;
298+
private String platform = "Windows 11";
299+
private String browser = "chrome";
300+
private String browserVersion = "latest";
301+
private java.util.Map<String, Object> capabilities = new java.util.LinkedHashMap<>();
302+
303+
public String getUsername() { return username; }
304+
public void setUsername(String v) { this.username = v; }
305+
public String getAccessKey() { return accessKey; }
306+
public void setAccessKey(String v) { this.accessKey = v; }
307+
public String getPlatform() { return platform; }
308+
public void setPlatform(String v) { this.platform = v; }
309+
public String getBrowser() { return browser; }
310+
public void setBrowser(String v) { this.browser = v; }
311+
public String getBrowserVersion() { return browserVersion; }
312+
public void setBrowserVersion(String v){ this.browserVersion = v; }
313+
public java.util.Map<String, Object> getCapabilities() { return capabilities; }
314+
public void setCapabilities(java.util.Map<String, Object> v) { this.capabilities = v != null ? v : new java.util.LinkedHashMap<>(); }
315+
}
290316
}
291317

292318
public static final class Retry {

‎src/main/java/com/seleniumboot/driver/DriverManager.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public static void createDriver() {
132132

133133
DRIVER.set(driver);
134134

135-
// Capture cloud session URL for BrowserStack / Sauce Labs
135+
// Capture cloud session URL for BrowserStack / Sauce Labs / LambdaTest
136136
try {
137137
String mode = SeleniumBootContext.getConfig().getExecution().getMode();
138138
if (driver instanceof org.openqa.selenium.remote.RemoteWebDriver rdw) {
@@ -141,6 +141,8 @@ public static void createDriver() {
141141
CLOUD_SESSION_URL.set(BrowserStackProvider.SESSION_URL_PREFIX + sessionId);
142142
} else if ("saucelabs".equalsIgnoreCase(mode)) {
143143
CLOUD_SESSION_URL.set(SauceLabsProvider.SESSION_URL_PREFIX + sessionId);
144+
} else if ("lambdatest".equalsIgnoreCase(mode)) {
145+
CLOUD_SESSION_URL.set(LambdaTestProvider.SESSION_URL_PREFIX + sessionId);
144146
}
145147
}
146148
} catch (Exception ignored) {}

‎src/main/java/com/seleniumboot/driver/DriverProviderFactory.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public static DriverProvider getProvider() {
2828
return new SauceLabsProvider();
2929
}
3030

31+
if ("lambdatest".equalsIgnoreCase(executionMode)) {
32+
return new LambdaTestProvider();
33+
}
34+
3135
// Custom providers registered via SPI or programmatically take precedence
3236
DriverProvider custom = DriverProviderRegistry.find(browser);
3337
if (custom != null) {

0 commit comments

Comments
 (0)