Add optional geb-direct Playwright backend - #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: |
Summary
Optional Playwright-backed driver for Geb (
geb-direct), without changing the default Selenium WebDriver path.Geb remains WebDriver-centric. This module implements a Playwright-backed
WebDriver/WebElementadapter so existing Geb surfaces (Browser, Page Objects, content DSL,$(),waitFor, modules, reporting integrations) keep working when users opt in.Motivation
Selenium-backed browser tests are often flaky in CI: brittle waits, remote driver/container networking, and weak debugging. Playwright provides:
geb-directbrings those strengths in as an opt-in backend.Generic design
driver = PlaywrightDriver.config { ... }inGebConfigorg.apache.groovy.geb:geb-direct(same version line as other Geb modules)WebDriveradapterPlaywrightBrowserSupportfacades (network, tracing, locators, wait, storage, emulation, downloads, HAR, console, API, PDF, a11y, video)cacheDriverPerThreadunder parallel workersConfiguration example
Browser install
npx playwright install chromium # or module task: ./gradlew :module:geb-direct:installPlaywrightBrowsersSkip browser tests:
-Dgeb.direct.playwright.skip=trueorPLAYWRIGHT_SKIP=true.Module layout
module/geb-direct- adapter + facades + tests + READMEdoc/manual/src/docs/asciidoc/022-geb-direct.adoccheckinbuild-check.ymlVerification (local)
Known initial-adapter limits
Browser.networkLatencyis not mapped yetGrails-specific validation
Grails 8 currently drives Geb through Testcontainers + Selenium (
ContainerGebSpec/BrowserWebDriverContainer). That stack is a major source of CI pain.geb-direct)@Integrationserverhost.testcontainers.internal:porthttp://localhost:$serverPortFileDetector/ copy into containerwaitForDo you still need Testcontainers with Playwright?
Proof branch on grails-core (no PR opened)
Branch (based on
8.0.x):https://github.com/apache/grails-core/tree/feature/grails-geb-playwright-local
Adds:
PlaywrightGebSpec+GrailsPlaywrightGebExtension+PlaywrightBrowserHoldergeb-direct/ Geb8.0.2-SNAPSHOT(mavenLocal for validation)playwright-geb): context-path, GebConfig, wait/type/click stress, local uploadRe-run on that branch:
Result of that validation: 5 tests, 0 failures against live Grails
@Integrationapps.Mailing-list alignment
This matches the optional
geb-direct/org.apache.groovy.gebdirection discussed on the Groovy mailing list: keep Selenium default, add Playwright as opt-in, preserve Geb DSL.Checklist