Repository navigation
Add experimental geb-playwright driver - #330
Conversation
Register the optional geb-direct submodule, Playwright 1.61 dependency, JaCoCo coverage gate, browser install task, and CI Chromium install step.
Implement PlaywrightSession, PlaywrightWebDriver/WebElement, locator and network helpers, tracing, waits, input, storage, emulation, and related facades so existing Geb DSL can run on Playwright without changing the default Selenium path.
Cover WebDriver core paths, Geb Browser/Page DSL, frames, windows, alerts, network, locators, waits, storage, emulation, and facade helpers with a 90% JaCoCo line coverage gate.
Add module README and manual chapter covering configuration, browser install, advanced Playwright surfaces, and Selenium default path notes.
Filter cookie reads/deletes by the active page URL/host so multi-domain BrowserContexts match Selenium WebDriver cookie semantics.
There was a problem hiding this comment.
⚠️ Not ready to approve
There are a few concrete correctness/lint concerns (e.g., selector mapping edge cases and CodeNarc-triggering dead/unused imports/fields) that should be addressed before merging.
Pull request overview
Adds a new optional geb-direct module that lets Geb run on a Playwright-backed WebDriver/WebElement adapter while keeping the default Selenium WebDriver path unchanged. This introduces a Playwright session/context abstraction plus a set of “facade” helpers to expose Playwright-only capabilities (tracing, network routing, locators, etc.) through Geb’s existing Browser/DSL surfaces, along with module docs and CI setup for installing browsers.
Changes:
- Introduces
module/geb-directwith a Playwright→WebDriver adapter (PlaywrightWebDriver,PlaywrightWebElement, session + helpers). - Adds a comprehensive Spock test suite for adapter behavior and Playwright facades (with skip flags).
- Updates docs, dependency catalog, Gradle wiring, and CI to install Playwright Chromium before running
check.
File summaries
| File | Description |
|---|---|
| settings.gradle | Adds the new module:geb-direct to the multi-project build. |
| module/geb-direct/src/test/groovy/geb/direct/support/PlaywrightSpecSupport.groovy | Shared test helpers for driver creation, local server, and temp files. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightWebDriverSpec.groovy | Basic WebDriver surface smoke coverage (navigation/actions/JS/screenshot/locators). |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightWebDriverSmokeSpec.groovy | Jetty-backed end-to-end WebDriver interaction smoke test. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightWebDriverCoreSpec.groovy | Core adapter behavior tests (timeouts, cookies, frames, actions, keys, async scripts). |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightWebDriverBrowserFeatureSpec.groovy | Verifies Geb Browser integrations (frames/windows/uploads) against Playwright driver. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightOptionsSpec.groovy | Tests PlaywrightOptions defaults and copy/config behavior. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightHelpersSpec.groovy | Exercises helper facades (keyboard/mouse/storage/wait/emulation) on a live page. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightFacadeCoverageSpec.groovy | Broad facade coverage including tracing reporter, waits, routing, downloads, PDF, a11y, video. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightDriverSpec.groovy | Tests PlaywrightDriver.config factory behavior (independent option copies). |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightBySpec.groovy | Tests By→Playwright selector mapping and escaping. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightAlertAndWindowSpec.groovy | Alert/dialog and window manager behavior tests. |
| module/geb-direct/src/test/groovy/geb/direct/PlaywrightAdvancedFeaturesSpec.groovy | Exercises higher-level Playwright features (routing, tracing, PDF, API client, storage, console). |
| module/geb-direct/src/test/groovy/geb/direct/GebDirectSmokePage.groovy | Simple Geb Page for verifying content DSL on the Playwright driver. |
| module/geb-direct/src/test/groovy/geb/direct/GebBrowserPlaywrightSpec.groovy | Verifies Geb Browser/Page/content DSL works on the Playwright-backed driver. |
| module/geb-direct/src/main/groovy/geb/direct/report/PlaywrightTraceReporter.groovy | Geb reporter that writes a trace zip and starts a new trace. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightWindow.groovy | WebDriver Window adapter (viewport-based best-effort). |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightWebElement.groovy | WebElement adapter backed by Playwright Locator with Selenium-like semantics. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightWebDriver.groovy | Main WebDriver facade over a Playwright BrowserContext/Page plus helper facades. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightWait.groovy | Wait facade mapping common Playwright page/context wait primitives. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightVideoSupport.groovy | Small helper to access recorded video path. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightTracing.groovy | Tracing start/stop wrapper over session tracing state. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightTouchscreen.groovy | Touchscreen wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightTimeouts.groovy | WebDriver Timeouts adapter (implicit wait + script/page load timeouts). |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightTargetLocator.groovy | WebDriver TargetLocator adapter (frames/windows/alerts). |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightStorage.groovy | Local/session storage helper via page evaluation. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightSession.groovy | Playwright lifecycle: create/close, context options, tracing, dialog/event tracking. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightPdf.groovy | Chromium PDF wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightOptions.groovy | Options model + deep copy used by config factories and sessions. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightNetwork.groovy | Routing/interception wrapper plus request/response wait passthrough. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightNavigation.groovy | WebDriver Navigation adapter. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightMouse.groovy | Mouse wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightLocators.groovy | Semantic locator helpers returning Selenium WebElements. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightKeyboard.groovy | Keyboard wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightHar.groovy | HAR routing wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightEmulation.groovy | Emulation + permissions helper wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightDriver.groovy | Factory entrypoint: create and config {} driver factory closures. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightDownloads.groovy | Download helper wrapper. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightCoverage.groovy | Coverage facade with explicit unsupported behavior where absent. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightCookieJar.groovy | Selenium-semantics cookie jar adapter scoped to current document host. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightConsole.groovy | Console message + page error collection access/clear. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightBy.groovy | Selenium By→Playwright selector mapping. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightBrowserSupport.groovy | Entry points to access Playwright driver/page/context + helper facades from Geb Browser. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightApiClient.groovy | Playwright APIRequestContext wrapper for test-side HTTP calls. |
| module/geb-direct/src/main/groovy/geb/direct/PlaywrightAccessibility.groovy | Accessibility snapshot wrapper. |
| module/geb-direct/README.md | Module README with setup, usage, options, and limitations. |
| module/geb-direct/geb-direct.gradle | Module build, dependencies, skip flags, Playwright browser install task, JaCoCo gate. |
| gradle/libs.versions.toml | Adds Playwright dependency coordinates/version. |
| doc/manual/src/docs/asciidoc/index.adoc | Includes the new manual chapter. |
| doc/manual/src/docs/asciidoc/022-geb-direct.adoc | New manual chapter documenting Geb Direct with Playwright. |
| .github/workflows/build-check.yml | Installs Playwright Chromium before running check in CI. |
Review details
- Files reviewed: 51/51 changed files
- Comments generated: 6
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Apply valid review feedback for window minimize dead state, className selector edge cases, HAR unroute clarity, and unused imports. Green codenarcTest which was failing Build/test/quality check on CI.
Copilot review follow-up (39e0327)Addressed the valid review comments and the CI failure:
CI
All six Copilot review threads marked resolved. |
ManualAnchorsSpec failed in CI because auto-generated header ids for Installation and other sections collided with existing chapters.
|
CI failure root cause: |
|
@jamesfredley This is really cool! |
|
I did start at Other options I considered:
Playwright communicates directly with the browser engines using their native low-level debugging/automation protocols: Chromium → Chrome DevTools Protocol (CDP) Playwright skips the WebDriver server entirely. Its Java (or Node) client talks more directly to the browser process using the engine’s own protocol. |
|
@matrei Thank you, I am hopeful this resolves our flaky test issues. |
|
Wouldn't reactive as a name be better? it's only direct because it doesn't use polling. it uses push? |
|
I still lean towards geb-direct. If that gets voted down strongly, geb-playwright would be my next vote. |
|
I think the name is less important, more important is to get it into Geb |
I disagree, naming is extremely important, and hard to change afterwards. |
|
Hey! Late to the party, but I'm on team |
…pers The Playwright-backed driver only needs a WebDriver adapter. Call Page and BrowserContext directly for Playwright features that have no WebDriver equivalent.
Simplification passQuestion for this change: is a Playwright backend for Geb the smallest thing that still lets existing Geb code run? The previous draft answered that by re-implementing Playwright.
RemovedThese types only forwarded to
Also removed the tests that existed to walk those wrappers (
KeptThe WebDriver surface Geb actually calls:
Playwright-only work: def playwrightDriver = browser.driver as PlaywrightWebDriver
playwrightDriver.page.getByTestId('submit').click()
playwrightDriver.context.route('**/api/**') { route -> route.abort() }Tests
Diff against the previous tip: 53 files, +414 / −2053. The Grails 8 proof on |
|
Looks good. I just resolved the merge conflict. Once the checks pass, we should be good to merge. May need to make some fix-forward changes later, but this seems as good a place to start as any. |
Summary
Experimental, optional Playwright-backed driver for Geb (
geb-playwright). Selenium stays the default.geb-coredoes not depend on Playwright unless a project adds this module and configuresPlaywrightDriver.The module is a WebDriver adapter so existing Geb code (
Browser, pages, the content DSL, modules,waitFor, reporting) can run on Playwright. It does not wrap Playwright's own API. Tests that need network routing, locators, tracing, or anything else Playwright already exposes usedriver.pageanddriver.context.The artifact, package, and configuration may change or be removed. This module is not covered by Geb's compatibility guarantees.
Configuration
Install a browser once per machine and CI image:
npx playwright install chromium # or ./gradlew :module:geb-playwright:installPlaywrightBrowsersSkip the module's browser tests with
-Dgeb.playwright.skip=trueorPLAYWRIGHT_SKIP=true.What is included
module/geb-playwright— WebDriver / WebElement adapter, driver factory, context options, trace reporterdoc/manual/src/docs/asciidoc/022-geb-playwright.adoccheckKnown limits
driver.manage().logs()is unsupportedGrails note
Re-ran the Grails 8 proof on
apache/grails-corebranchfeature/grails-geb-playwright-local(843dc0b215) againstorg.apache.groovy.geb:geb-playwrightand packagegeb.playwright. Local integration tests: 5 tests, 0 failures (PlaywrightStressSpec,PlaywrightUploadSpec,ContextPathSpectwice,GebConfigSpec). The BOM map key isgeb-spock-playwrightso the published POM still usesgeb-spock.version.Checklist
geb-playwright