Skip to content

feat(electron-service): migrate to shared @wdio/native-cdp-bridge; retire @wdio/electron-cdp-bridge - #481

Merged
goosewobbler merged 1 commit into
mainfrom
feat/340-electron-native-cdp-bridge
Jun 25, 2026
Merged

feat(electron-service): migrate to shared @wdio/native-cdp-bridge; retire @wdio/electron-cdp-bridge#481
goosewobbler merged 1 commit into
mainfrom
feat/340-electron-native-cdp-bridge

Conversation

@goosewobbler

Copy link
Copy Markdown
Contributor

What

Migrate @wdio/electron-service off its bespoke @wdio/electron-cdp-bridge onto the shared single-target CdpBridge from @wdio/native-cdp-bridge, and retire @wdio/electron-cdp-bridge. Mirrors the electrobun rework in #335.

Closes #340.

How — composition, not subclassing

ElectronCdpBridge now holds a CdpBridge and delegates send/on/off (re-declaring the CDP-typed generic overloads), keeping its Electron connect orchestration (Runtime.enable/disable → wait for executionContextCreated → capture contextId → inject bootstrap script) and the contextId getter.

This was the deciding factor: #335 deliberately sealed the bridge's options to a private #options, which broke the old extends CdpBridge subclass (it read this.options.timeout). Composition depends only on the bridge's public API, so it:

  • removes the fragile base-class coupling that motivated this migration;
  • is the single pattern that fits both electron and electrobun (electrobun already composes via the classifyTarget option) — no artificial empty subclass forced on electrobun.

The lost timeout is recovered as #timeout = options?.timeout ?? REQUEST_TIMEOUT (re-exported by the bridge), keeping electron's context-wait in lockstep with the bridge's effective request timeout.

Changes

  • bridge.ts — composition refactor (+ devtools-protocol devDep for the delegating generics)
  • service.ts / serviceConfig.ts — re-point the CdpBridgeOptions import
  • package.json — swap dep @wdio/electron-cdp-bridge@wdio/native-cdp-bridge
  • bridge.spec.ts — mock the held bridge (...actual preserves REQUEST_TIMEOUT)
  • Deleted packages/electron-cdp-bridge/
  • Infra — turbo, root build:electron, releasekit skipPackages, scripts/test-package.ts, _ci-package/_release workflows
  • detect-changes — electron now derives as a native-cdp-bridge dependent (convention-driven; only the spec's assertions changed)
  • Docs/templates/skill — live references updated; historical (CHANGELOG, release-notes, agent-os specs) left intact

Non-issues (verified)

  • Default port 9229→9222: electron always passes an explicit --inspect host:port, so the bridge default is never used.
  • Terminal close(): electron creates a fresh bridge per session; it never close-then-reconnects.

Verification

  • pnpm build:electron ✅ · tsc --noEmit
  • electron-service unit suite 517/517 ✅ (bridge.spec.ts reworked)
  • pnpm test:scripts 95/95
  • Biome lint+format on changed files ✅
  • Token-level grep sweep clean (only the historical CHANGELOG entry remains)

Heavy CI-grade checks (test:package:electron, electron E2E) left to CI.

Release / follow-up

  • Target 10.2.0 (-next first) via the standing-PR + scope:electron + release label — this PR doesn't bump versions.
  • Follow-up to npm deprecate @wdio/electron-cdp-bridge post-release (filed as a separate issue).

🤖 Generated with Claude Code

…tire @wdio/electron-cdp-bridge (#340)

ElectronCdpBridge now composes the shared single-target CdpBridge from
@wdio/native-cdp-bridge instead of subclassing the bespoke
@wdio/electron-cdp-bridge, which is retired. Composition depends only on the
bridge's public API (the shared bridge keeps its options private), removing the
fragile base-class coupling that motivated the migration; electrobun already
composes, so the repo converges on a single pattern.

- ElectronCdpBridge delegates send/on/off and owns its context-wait timeout
  (options?.timeout ?? REQUEST_TIMEOUT) since the bridge no longer exposes options
- Re-point type imports + package dep; add devtools-protocol devDep for the
  CDP-typed delegating signatures; rework bridge.spec.ts to mock the held bridge
- Delete packages/electron-cdp-bridge; re-point turbo, releasekit, test-package.ts,
  CI pack/release workflows, detect-changes, and docs/issue templates

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Standing release PR: #456 · 8 packages queued · open 29h 41m · ✅ ready to merge

Release Preview — 9 packages

Note: Labels on this PR are advisory in standing-pr mode (saw: scope:electron). Bumps come from conventional commits in the standing PR; override by editing labels on the standing PR itself. Add release:immediate to bypass the standing PR and release this PR directly.

These changes will be added to the release PR (#456) when merged:

Changelog

@wdio/tauri-service wdio-tauri-service@v1.1.0 → 1.2.0

Changed

  • Update version to 1.2.0
tauri-plugin-wdio-webdriver tauri-plugin-wdio-webdriver@v1.1.0 → 1.2.0

Changed

  • Update version to 1.2.0
@wdio/flutter-service N/A → 0.1.0

Changed

  • Update version to 0.1.0
@wdio/dioxus-service N/A → 1.1.0

Changed

  • Update version to 1.1.0
@wdio/electron-service wdio-electron-service@v10.1.0 → 10.2.0

Added

@wdio/native-spy wdio-native-spy@v1.1.0 → 1.2.0

Changed

  • Update version to 1.2.0
@wdio/native-utils wdio-native-utils@v2.4.0 → 2.5.0

Changed

  • Update version to 2.5.0
@wdio/react-native-service N/A → 1.1.0

Changed

  • Update version to 1.1.0
dioxus-package-test-app N/A → 0.2.0

Changed

  • Update version to 0.2.0

After merge — predicted release

No version escalation — this PR's changes will be included in the queued release without affecting the projected versions.

Package Standing PR This PR After merge
@wdio/dioxus-service 1.1.0 1.1.0 1.1.0
@wdio/flutter-service 0.1.0 0.1.0 0.1.0
@wdio/native-spy 1.2.0 1.2.0 1.2.0
@wdio/native-utils 2.5.0 2.5.0 2.5.0
@wdio/react-native-service 1.1.0 1.1.0 1.1.0
@wdio/tauri-service 1.2.0 1.2.0 1.2.0
dioxus-package-test-app 0.2.0 0.2.0 0.2.0
tauri-plugin-wdio-webdriver 1.2.0 1.2.0 1.2.0

Updated automatically by ReleaseKit

@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR migrates @wdio/electron-service from its bespoke @wdio/electron-cdp-bridge to the shared @wdio/native-cdp-bridge, switching from inheritance to composition, and retires the electron-specific bridge package entirely.

  • ElectronCdpBridge now holds a CdpBridge and delegates send/on/off with re-declared CDP-typed generic overloads, preserving the full Electron setup flow (Runtime.enable/disable → context resolution → bootstrap injection) in its own connect().
  • Infrastructure (turbo, CI, build scripts, releasekit, detect-changes) is consistently updated from electron-cdp-bridge to native-cdp-bridge across all references; the test suite is reworked to mock the held bridge's prototype methods.

Confidence Score: 5/5

Safe to merge. The composition refactor is mechanically correct and the delegated public surface covers every usage site in the service.

The switch from inheritance to composition is clean: on/off/send delegate to the held CdpBridge after connect() guarantees a live #connection, so the NOT_CONNECTED guard in CdpBridge.on() is never hit in normal flow. #timeout is derived with the same ?? REQUEST_TIMEOUT default the bridge applies internally, keeping context-wait deadlines in sync. The removed close() method is not called anywhere in the service (logCapture.ts uses only on/off, service.ts never calls close() on the bridge). All infrastructure changes — turbo, CI pack steps, release workflow, skipPackages, detect-changes — are consistently updated with no stale references to electron-cdp-bridge.

No files require special attention.

Important Files Changed

Filename Overview
packages/electron-service/src/bridge.ts Core refactor: ElectronCdpBridge switches from extends to composition, correctly delegating send/on/off after connect(); timeout is recovered via a local #timeout field mirroring the bridge's default.
packages/electron-service/test/bridge.spec.ts Test suite reworked to mock CdpBridge.prototype methods (spread ...actual preserves REQUEST_TIMEOUT) and return both the wrapper and the held bridge for assertion; timing and sequencing analysis confirms correctness.
packages/electron-service/package.json Dependency swapped from @wdio/electron-cdp-bridge to @wdio/native-cdp-bridge; devtools-protocol added as devDep to provide CDP type definitions for the delegating generic overloads.
turbo.json Build pipeline for electron-cdp-bridge removed; electron-service build dependency changed to native-cdp-bridge#build; consistent with package.json dep change.
scripts/test-package.ts All references to electron-cdp-bridge (directory lookup, pack commands, tarball discovery, override injection) correctly updated to native-cdp-bridge.
.github/workflows/_release.reusable.yml Removed explicit --filter for electron-cdp-bridge; comment correctly explains that @wdio/electron-service... transitively pulls in native-cdp-bridge.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant S as ElectronWorkerService
    participant E as ElectronCdpBridge
    participant B as CdpBridge (#bridge)
    participant C as Connection

    S->>E: new ElectronCdpBridge(options)
    E->>B: new CdpBridge(options)
    S->>E: connect()
    E->>B: "#bridge.connect()"
    B->>C: discover targets + open WebSocket
    C-->>B: connected
    B-->>E: resolved
    E->>E: "#getContextIdHandler() — register listener"
    E->>B: "#bridge.on('Runtime.executionContextCreated', cb)"
    B->>C: connection.on(event, cb)
    E->>B: "#bridge.send('Runtime.enable')"
    B->>C: connection.send(...)
    C-->>E: Runtime.executionContextCreated event fires
    E->>E: resolve contextId
    E->>B: "#bridge.off('Runtime.executionContextCreated', cb)"
    E->>B: "#bridge.send('Runtime.disable')"
    E->>B: "#bridge.send('Runtime.evaluate', bootstrap)"
    E-->>S: connect() resolved
    S->>E: send(method, params)
    E->>B: "#bridge.send(method, params)"
    B->>C: connection.send(...)
    C-->>S: result
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant S as ElectronWorkerService
    participant E as ElectronCdpBridge
    participant B as CdpBridge (#bridge)
    participant C as Connection

    S->>E: new ElectronCdpBridge(options)
    E->>B: new CdpBridge(options)
    S->>E: connect()
    E->>B: "#bridge.connect()"
    B->>C: discover targets + open WebSocket
    C-->>B: connected
    B-->>E: resolved
    E->>E: "#getContextIdHandler() — register listener"
    E->>B: "#bridge.on('Runtime.executionContextCreated', cb)"
    B->>C: connection.on(event, cb)
    E->>B: "#bridge.send('Runtime.enable')"
    B->>C: connection.send(...)
    C-->>E: Runtime.executionContextCreated event fires
    E->>E: resolve contextId
    E->>B: "#bridge.off('Runtime.executionContextCreated', cb)"
    E->>B: "#bridge.send('Runtime.disable')"
    E->>B: "#bridge.send('Runtime.evaluate', bootstrap)"
    E-->>S: connect() resolved
    S->>E: send(method, params)
    E->>B: "#bridge.send(method, params)"
    B->>C: connection.send(...)
    C-->>S: result
Loading

Reviews (1): Last reviewed commit: "feat(electron-service): migrate to share..." | Re-trigger Greptile

@goosewobbler
goosewobbler merged commit 9b85607 into main Jun 25, 2026
489 of 492 checks passed
@goosewobbler
goosewobbler deleted the feat/340-electron-native-cdp-bridge branch June 25, 2026 00:09
@github-actions github-actions Bot mentioned this pull request Jun 25, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope:electron Electron service and CDP bridge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate @wdio/electron-service to @wdio/native-cdp-bridge (10.2.0)

1 participant