feat(electron-service): migrate to shared @wdio/native-cdp-bridge; retire @wdio/electron-cdp-bridge - #481
Conversation
…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>
|
Standing release PR: #456 · 8 packages queued · open 29h 41m · ✅ ready to merge Release Preview — 9 packages
These changes will be added to the release PR (#456) when merged: Changelog@wdio/tauri-service wdio-tauri-service@v1.1.0 → 1.2.0Changed
tauri-plugin-wdio-webdriver tauri-plugin-wdio-webdriver@v1.1.0 → 1.2.0Changed
@wdio/flutter-service N/A → 0.1.0Changed
@wdio/dioxus-service N/A → 1.1.0Changed
@wdio/electron-service wdio-electron-service@v10.1.0 → 10.2.0Added
@wdio/native-spy wdio-native-spy@v1.1.0 → 1.2.0Changed
@wdio/native-utils wdio-native-utils@v2.4.0 → 2.5.0Changed
@wdio/react-native-service N/A → 1.1.0Changed
dioxus-package-test-app N/A → 0.2.0Changed
After merge — predicted release
Updated automatically by ReleaseKit |
|
| 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
%%{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
Reviews (1): Last reviewed commit: "feat(electron-service): migrate to share..." | Re-trigger Greptile
What
Migrate
@wdio/electron-serviceoff its bespoke@wdio/electron-cdp-bridgeonto the shared single-targetCdpBridgefrom@wdio/native-cdp-bridge, and retire@wdio/electron-cdp-bridge. Mirrors the electrobun rework in #335.Closes #340.
How — composition, not subclassing
ElectronCdpBridgenow holds aCdpBridgeand delegatessend/on/off(re-declaring the CDP-typed generic overloads), keeping its Electron connect orchestration (Runtime.enable/disable→ wait forexecutionContextCreated→ capturecontextId→ inject bootstrap script) and thecontextIdgetter.This was the deciding factor: #335 deliberately sealed the bridge's options to a private
#options, which broke the oldextends CdpBridgesubclass (it readthis.options.timeout). Composition depends only on the bridge's public API, so it:classifyTargetoption) — 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
devtools-protocoldevDep for the delegating generics)CdpBridgeOptionsimport@wdio/electron-cdp-bridge→@wdio/native-cdp-bridge...actualpreservesREQUEST_TIMEOUT)packages/electron-cdp-bridge/build:electron, releasekitskipPackages,scripts/test-package.ts,_ci-package/_releaseworkflowsnative-cdp-bridgedependent (convention-driven; only the spec's assertions changed)Non-issues (verified)
--inspecthost:port, so the bridge default is never used.close(): electron creates a fresh bridge per session; it never close-then-reconnects.Verification
pnpm build:electron✅ ·tsc --noEmit✅bridge.spec.tsreworked)pnpm test:scripts95/95 ✅Release / follow-up
-nextfirst) via the standing-PR +scope:electron+ release label — this PR doesn't bump versions.npm deprecate @wdio/electron-cdp-bridgepost-release (filed as a separate issue).🤖 Generated with Claude Code