Skip to content

feat(electron): add session-scoped API mocking tools - #146

Merged
Winify merged 4 commits into
webdriverio:mainfrom
nthompson-bitwarden:add-electron-mocks-support
Sep 15, 2026
Merged

Winify merged 4 commits into
webdriverio:mainfrom
nthompson-bitwarden:add-electron-mocks-support

Conversation

@nthompson-bitwarden

@nthompson-bitwarden nthompson-bitwarden commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

Adds shared, session-scoped mocking tools: mock, get_mock_calls, and manage_mock, with optional mockType: 'electron' | 'browser'.

  • WebDriver browser sessions default to browser, including sessions whose metadata omits runtime.
  • Electron sessions require an explicit selector. Electron API function mocking is implemented; selecting browser mocking returns a clear “not implemented yet” error.
  • iOS/Android Appium sessions are unsupported. Missing sessions/metadata and Electron mocks outside Electron sessions fail before mock service calls.
  • Electron mocks support return, resolved, rejected, and queued-once JSON values, with clear/reset/restore actions. Browser ownership and per-target serialization preserve isolation, ordering, and retries.
  • All three tools participate in traces and executable replay generation. Replay requires mockType: 'electron' and rejects missing or unsupported selectors.
  • Documents the shared API and session routing. Browser mocking implementation and script-tool consolidation remain follow-up work.

Types of changes

  • Polish (an improvement for an existing feature)
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update (improvements to the project's docs)
  • Specification changes (updates to WebDriver command specifications)
  • Internal updates (everything related to internal scripts, governance documentation and CI files)

Validation

  • 118 focused tests passed: routing matrix across all three tools, malformed targets/selectors, concurrency, session replacement, lifecycle, trace mapping, and executable replay.
  • Full suite: 594 tests passed across 39 files. The initial sandbox run blocked a localhost integration socket; rerunning with socket access passed.
  • Non-mutating ESLint: zero errors (60 warnings); TypeScript checking passed.
  • Bundle and npm package build passed.
  • Registered MCP SDK stdio client against the built server: schema discovery and runtime errors passed; real Electron 43.2.0 fixture returned queued/default mock values, recorded two calls, cleared to zero, reset/reconfigured successfully, and restored the original function. Headless Chrome confirmed browser defaults and Electron rejection across all three tools.
  • Appium routing and missing metadata are covered by unit tests; no live mobile-device validation was performed.

Checklist

  • I have squashed commits that belong together
  • I have tested with Claude Desktop (or another MCP-compatible client)
  • I have read the CONTRIBUTING doc
  • I have added the necessary documentation for new/changed tools (if appropriate)
  • I have added proper type definitions for new commands (if appropriate)

Reviewers: @webdriverio/project-committers

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no actionable correctness, security, or repository-rule violations remain.

Summary

  • Registers mock, get_mock_calls, and manage_mock with explicit runtime and target validation.
  • Serializes operations per browser and target while isolating handles by session.
  • Adds trace mappings and executable recording translations for configuration, inspection, reset, restoration, and recreation.
  • Documents supported behaviors, session routing, lifecycle semantics, and current browser/Appium limitations.
  • Adds focused coverage for validation, concurrency, session replacement, tracing, and generated replay.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Client[MCP client] --> Tool[mock tools]
  Tool --> Context[Validate active session and mockType]
  Context --> Queue[Per-browser, per-target operation queue]
  Queue --> Handle[Electron mock handle cache]
  Handle --> Configure[Configure behavior]
  Handle --> Inspect[Refresh and inspect calls]
  Handle --> Manage[Clear, reset, or restore]
  Manage -->|restore| Remove[Release cached handle]
  Tool --> History[Session history]
  Tool --> Trace[Trace actions]
  History --> Generator[Generated Electron replay]
Loading

Reviews (3) · Last reviewed commit: "refactor(mock): route shared tools by op..."

Comment thread src/tools/electron-mock.tool.ts Outdated
@Winify

Winify commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

@nthompson-bitwarden Cannot this feature be bundled into a global browser.mock tooling?

Kinda similar to start_session -- based on the context it decides if it inits an appium or webdriver session

I could imagine the same for this mocking as well: If its an electron session then it executes against an electron mock, otherwise uses a browser mock

I may have missed the mark before with the execute_electron_script˙ as it already could have been folded into execute_script with session metadata:

const metadata = state.currentSession ? state.sessionMetadata.get(state.currentSession) : undefined;
if (metadata?.runtime !== 'electron') {
  return { isError: true, content: [{ type: 'text', text: 'Error executing Electron script: no active Electron session.' }] };
}

What do you think? Could the mock tooling and the execute_script be merged (I know the execute_script change could be considered breaking, if it does not sit alright with you, I can defer it till v4)?

  • No need to implement all browser mocking, I can do that (it can throw an error if its not electron runtime) -- Just a holistic approach would be nice

@nthompson-bitwarden

Copy link
Copy Markdown
Contributor Author

@Winify

Agreed, I like the idea of a shared mocking interface. I can consolidate the mock tools and keep the implementation Electron-only for now, with an unsupported error for other runtimes like you suggested.

One thing I’d suggest is an explicit mock kind, since browser.mock() targets network requests while Electron mocks target API functions. That would also leave room for both kinds within an Electron session.

For execute_script: an Electron session still needs access to both the renderer and the main process, so session metadata alone won't tell us which context the caller wants. Maybe could add something like context: 'electron-main', preserve the current behavior by default, and keep execute_electron_script as an alias until v4?

Happy to tackle the shared mock interface in this PR and leave script consolidation for a follow-up if that works for you?

@Winify

Winify commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

@Winify

Agreed, I like the idea of a shared mocking interface. I can consolidate the mock tools and keep the implementation Electron-only for now, with an unsupported error for other runtimes like you suggested.

One thing I’d suggest is an explicit mock kind, since browser.mock() targets network requests while Electron mocks target API functions. That would also leave room for both kinds within an Electron session.

For execute_script: an Electron session still needs access to both the renderer and the main process, so session metadata alone won't tell us which context the caller wants. Maybe could add something like context: 'electron-main', preserve the current behavior by default, and keep execute_electron_script as an alias until v4?

Happy to tackle the shared mock interface in this PR and leave script consolidation for a follow-up if that works for you?

@nthompson-bitwarden Awesome! I really like the explocit "mockType" argument in the mock methods

I would suggest that webdriver runtimes would default to browser, appium session throws an error, and electron should be the one that can effectively use both

So for execute_script there should be a similar distinction?
An electron runtime needs both type of script execution, but the principal between tools are the same
Again, I would introduce a new optional parameter, so electron runtime can differentiate between what it needs

I would not expand the whole pallette of tooling for a localized use-case

But sure, execute_electorn_script cab remain as its already in the code

I just plan on introducing wdi5 (SAP) runtime as well, so I have to think of the branching now 😁

Please tackle the mock consolidation, and I will resolve the rest

@nthompson-bitwarden

Copy link
Copy Markdown
Contributor Author

@Winify thanks for the context! I've pushed that update with your suggestions and PR is ready for review

@Winify
Winify merged commit 11bb1b5 into webdriverio:main Sep 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants