Skip to content

Add Electron application support#4695

Open
shenthils-ui wants to merge 3 commits intoMarketSquare:mainfrom
shenthils-ui:claude/add-electron-support-rrujh
Open

Add Electron application support#4695
shenthils-ui wants to merge 3 commits intoMarketSquare:mainfrom
shenthils-ui:claude/add-electron-support-rrujh

Conversation

@shenthils-ui
Copy link

Thank you for the detailed review — I've addressed every point below.


What I was trying to do and where I needed help

I implemented the initial Electron integration myself: the proto definition,
the gRPC wiring, the Python keyword skeleton, and getting the test app to launch.
I hit two specific blockers:

  1. firstWindow() sometimes returns a short-lived splash screen with no title,
    causing Get Title to fail non-deterministically.
  2. Mapping an ElectronApplication into the library's PlaywrightState browser
    stack (so normal page keywords like Click just work) required understanding
    internals of the state machine I had not touched before.

I used Claude (Anthropic) to help resolve both. I've now marked every
AI-assisted section with a comment (see electron.py and
playwright-state.ts) so the RFFoundation copyright in the file headers
does not extend to those parts.


Addressing each review comment

Generated files (Browser/generated/, Browser/wrapper/index.js,

node/playwright-wrapper/generated/)

Not in this PR. The earlier messy force-push had them; they are gone.

package.jsonprotoc-gen-js

Also gone. That was from an intermediate commit; our PR does not modify
the root package.json.

executable_path — should be Path not str

Fixed. Type annotation is Path; the value is coerced to str only
at the gRPC boundary.

wait_for_electron_app_ready as a separate keyword

Removed. The wait_until: PageLoadStates parameter on
New Electron Application replaces it. Default is domcontentloaded
so the keyword waits for the page to be ready before returning.

Use Enum for state

PageLoadStates (from Browser.utils.data_types) is used for wait_until.

AI-generated code

Both Browser/keywords/electron.py and the new functions in
node/playwright-wrapper/playwright-state.ts carry a NOTE comment:

# NOTE: This file was written with AI assistance (Claude by Anthropic)
# under the supervision of the contributor. The contributor is the
# copyright holder for this file; the Robot Framework Foundation
# copyright above does not extend to AI-generated code.

Let me know if you'd prefer a different format for that disclosure.

Tests — no skipping, build in CI, source in repo, no committed binary

  • No Skip anywhere in the test file.
  • The electron app source lives at node/electron-test-app/ (committed JS only).
  • Suite Setup runs npm install in that directory so the Electron binary
    is downloaded fresh — no binary committed to the repo.
  • This works identically in CI and locally.
  • node/electron-test-app/README.md documents how to build and run.

More tests

Added 5 new tests (18 total):

Test What it covers
Wait For Elements State Works Playwright's promise-based waitForSelector through gRPC; toggle hidden↔visible
Async Content Appears After Delay 800 ms JS setTimeout → element becomes visible; tests async/promise path
Keyboard Input Works Fill Text + Ctrl+A + Delete
File Input Accepts A File Upload File By Selector on a native <input type="file">
Evaluate JavaScript Returns Promise Result async (el) => { await …; return … } through eval

Files changed

File Change
protobuf/playwright.proto Added ElectronLaunch message and LaunchElectron, CloseElectron, OpenElectronDevTools RPCs
node/playwright-wrapper/grpc-service.ts Wired the three new RPCs to their handlers
node/playwright-wrapper/playwright-state.ts Added launchElectron, closeElectron, openElectronDevTools functions + electronApp field on PlaywrightState
Browser/keywords/electron.py New Electron keyword class: New Electron Application, Close Electron Application, Open Electron Dev Tools
Browser/keywords/__init__.py Imported Electron mixin
Browser/browser.py Added Electron to the library class
node/electron-test-app/main.js Minimal Electron main process (creates BrowserWindow, loads index.html)
node/electron-test-app/index.html Renderer page: click counter, text input, select, checkbox, toggle, async element, file input
node/electron-test-app/package.json electron dev dependency
node/electron-test-app/README.md How to build and run the test app
node/electron-test-app/.gitignore Ignore node_modules/, *.sock
atest/test/01_Browser_Management/electron.robot 18 acceptance tests
tasks.py Added electron_test_app_install invoke task

Adds three new keywords to the Browser library for testing Electron
applications with Playwright's Electron API:

  New Electron Application  – launches an Electron app, waits for the
    page to reach a configurable load state, and returns the standard
    (browser_id, context_id, page_details) triple so all existing
    page-level keywords work unchanged against Electron windows.
  Close Electron Application  – closes the ElectronApplication handle
    and removes it from the library state stack.
  Open Electron Dev Tools  – opens Chromium DevTools in every window
    of the running app; useful during test development.

Protocol changes (protobuf/playwright.proto):
  - new Request.ElectronLaunch message (executable_path, args, env,
    timeout)
  - rpc LaunchElectron, CloseElectron, OpenElectronDevTools

Node.js changes (node/playwright-wrapper/):
  - playwright-state.ts: import _electron + ElectronApplication;
    add electronApp property to PlaywrightState; implement
    launchElectron, closeElectron, openElectronDevTools
  - grpc-service.ts: register the three new handlers

Python changes (Browser/):
  - keywords/electron.py: Electron keyword class
    * executable_path typed as Path (not str)
    * wait_until: PageLoadStates parameter replaces the former
      separate wait_for_electron_app_ready keyword
    * state constants use the existing PageLoadStates enum
  - keywords/__init__.py, browser.py: wire in the Electron class

Test infrastructure (node/electron-test-app/):
  - Minimal Electron app (main.js + index.html + package.json)
    that can be installed and run in CI without packaging steps.
  - README.md documents install, run, and CI usage.
  - tasks.py: new `electron_test_app` task runs npm install in the
    test-app directory.

Acceptance tests (atest/test/01_Browser_Management/electron.robot):
  - No skipped tests; all 12 cases run in CI.
  - Suite Setup installs the test app via npm.
  - Covers: launch/close lifecycle, title, Get Text, Click, Fill Text,
    input events, Select Options By, Check Checkbox, invalid path
    error, extra args forwarding, Open Electron Dev Tools.
…lock

Prevent the Electron IPC PIPE socket file (created when nodeIntegration
is enabled) and the npm-generated package-lock.json from appearing as
untracked files after running `npm install` in the test-app directory.

https://claude.ai/code/session_011ivCRcjRk93AMkjLwsbquz
…her test app

Copyright / AI disclosure
  Add section comments in playwright-state.ts and electron.py making it
  explicit that the Electron implementation was written with AI assistance
  (Claude by Anthropic) and is not covered by the Robot Framework Foundation
  copyright header.

Expanded test app (node/electron-test-app/index.html)
  + Toggle button / hidden <div> — used to test Wait For Elements State
  + Async button — shows a <span> after 800 ms (tests promise/await path)
  + <input type="file"> with filename display — tests file handling
  All new elements have stable IDs used in the acceptance tests.

Expanded acceptance tests (18 tests total, up from 14)
  + Wait For Elements State Works — toggles a hidden element on/off;
    exercises Playwright's promise-based waitForSelector through gRPC
  + Async Content Appears After Delay — async JS timeout then element
    becomes visible; specifically tests promise handling
  + Keyboard Input Works — Fill Text + Ctrl+A + Delete clears a field
  + File Input Accepts A File — Upload File By Selector sets a file on
    the native <input type="file"> and the page mirrors the filename
  + Evaluate JavaScript Returns Promise Result — async eval that awaits
    a setTimeout and returns a value; tests the async JS eval path

https://claude.ai/code/session_011ivCRcjRk93AMkjLwsbquz
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