/desktop-testing-electron
E2E testing with Playwright, main process unit testing, IPC testing, dialog/menu mocking, CI headless setup
$ npx -y skills add agents-inc/skills --skill desktop-testing-electron --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/desktop-testing-electron
Context preview
The summary Claude sees to decide when to auto-load this skill.
E2E testing with Playwright, main process unit testing, IPC testing, dialog/menu mocking, CI headless setup
SKILL.md
desktop-testing-electron.SKILL.mdname: desktop-testing-electron
description: E2E testing with Playwright, main process unit testing, IPC testing, dialog/menu mocking, CI headless setup
Electron Testing Patterns
> **Quick Guide:** Use Playwright's `_electron.launch()` for E2E tests -- it controls the full app via CDP. Unit test main process code (IPC handlers, business logic) with your test runner by mocking the `electron` module. Test preload scripts by mocking `contextBridge` and `ipcRenderer`. Spectron is dead since Electron 24 -- Playwright and WebDriverIO are the replacements. Run Electron tests on headless Linux CI with `xvfb-run` or the `xvfb-maybe` wrapper.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST `await electronApp.close()` in test teardown -- leaked Electron processes break CI and consume resources)**
**(You MUST mock the `electron` module in unit tests -- Electron APIs are only available inside the Electron runtime)**
**(You MUST use `xvfb-run` or `xvfb-maybe` for headless Linux CI -- Electron requires a display server)**
**(You MUST stub native dialogs in E2E tests -- `showOpenDialog`/`showSaveDialog` block the process and cannot be interacted with by Playwright)**
</critical_requirements>
---
**Auto-detection:** Electron testing, _electron.launch, electronApp, electronApplication, firstWindow, Playwright Electron, electron-mock-ipc, electron-playwright-helpers, stubDialog, xvfb, xvfb-run, xvfb-maybe, Spectron migration, ipcMain.handle test, ipcRenderer mock, contextBridge mock, BrowserWindow mock, Electron E2E, Electron unit test
**When to use:**
- Writing E2E tests for an Electron application with Playwright
- Unit testing main process code (IPC handlers, lifecycle logic)
- Mocking Electron modules (`dialog`, `BrowserWindow`, `ipcMain`, `ipcRenderer`)
- Testing preload scripts and `contextBridge` APIs
- Setting up headless CI for Electron tests (Linux xvfb)
- Migrating from Spectron to Playwright
- Screenshot/visual regression testing of Electron windows
- Testing auto-update flows
**When NOT to use:**
- Testing renderer UI in isolation (use your web testing skill -- renderer is standard web)
- Writing tests unrelated to Electron-specific APIs
- Performance profiling or benchmarking Electron apps
- Packaging or distributing Electron apps (use the Electron framework skill)
**Key patterns covered:**
- Playwright E2E: `_electron.launch()`, `firstWindow()`, `evaluate()`, assertions
- Main process unit testing with mocked Electron modules
- IPC handler testing (`ipcMain.handle` / `ipcRenderer.invoke`)
- Preload script testing (mock `contextBridge.exposeInMainWorld`)
- Dialog and menu stubbing in E2E tests
- Auto-updater test strategies
- Headless CI configuration (xvfb, GitHub Actions)
- Screenshot and visual regression testing
- Spectron migration path
---
<philosophy>
Philosophy
Electron testing splits along the same boundaries as the Electron process model:
1. **E2E tests** launch the full application with Playwright and exercise the complete flow -- main process, preload, renderer, and IPC together. These are slow but high-confidence. 2. **Main process unit tests** mock the `electron` module and test IPC handlers, lifecycle logic, and business logic in isolation. These are fast and catch logic bugs early. 3. **Renderer tests** are standard web tests -- the renderer is Chromium. Use your existing web testing approach.
**Guiding principle:** Test main process logic with unit tests, test integration through IPC with E2E, and test renderer UI with standard web tools. Don't try to unit test IPC communication itself -- the framework handles message passing. Test that your handlers produce the correct results given inputs.
**When to use E2E (Playwright):**
- Full user workflows (open file, edit, save)
- IPC round-trips that span main and renderer
- Window management (multi-window, modals, frameless)
- Visual regression / screenshot comparison
- Auto-update UI flow
**When to use unit tests:**
- IPC handler logic (validate input, produce output)
- Main process business logic (file operations, data processing)
- Preload API shape (correct channels exposed)
- Configuration and startup logic
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Playwright E2E -- Launch and Basic Assertions
Launch the Electron app, get the first window, and run assertions. Always close in teardown.
import { test, expect, _electron as electron } from "@playwright/test";
import type { ElectronApplication, Page } from "@playwright/test";
let electronApp: ElectronApplication;
let window: Page;
test.beforeEach(async () => {
electronApp = await electron.launch({ args: ["dist/main.js"] });
window = await electronApp.firstWindow();
});
test.afterEach(async () => {
await electronApp.close();
});
test("shows main window with title", async () => {
const title = await window.title();
expect(title).toBe("My App");
await expect(window.locator("h1")).toHaveText("Welcome");
});**Why good:** `afterEach` guarantees cleanup, `firstWindow()` waits for the window to load, standard Playwright assertions work on the Page object
See [examples/core.md](examples/core.md) for evaluate(), multi-window, and environment variable patterns.
---
Pattern 2: Main Process Evaluation
Use `electronApp.evaluate()` to execute code in the main process context and access Electron APIs.
test("returns correct app version", async () => {
const version = await electronApp.evaluate(async ({ app }) => {
return app.getVersion();
});
expect(version).toMatch(/^\d+\.\d+\.\d+$/);
});
test("app path is set correctly", async () => {
const appPath = await electronApp.evaluate(async ({ app }) => {
return app.getAppPath();
});
expect(appPath).toContain("dist");
});**Why good:** `evalua
Read more
name: desktop-testing-electron description: E2E testing with Playwright, main process unit testing, IPC testing, dialog/menu mocking, CI headless setup
Electron Testing Patterns
> **Quick Guide:** Use Playwright's `_electron.launch()` for E2E tests -- it controls the full app via CDP. Unit test main process code (IPC handlers, business logic) with your test runner by mocking the `electron` module. Test preload scripts by mocking `contextBridge` and `ipcRenderer`. Spectron is dead since Electron 24 -- Playwright and WebDriverIO are the replacements. Run Electron tests on headless Linux CI with `xvfb-run` or the `xvfb-maybe` wrapper.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST `await electronApp.close()` in test teardown -- leaked Electron processes break CI and consume resources)**
**(You MUST mock the `electron` module in unit tests -- Electron APIs are only available inside the Electron runtime)**
**(You MUST use `xvfb-run` or `xvfb-maybe` for headless Linux CI -- Electron requires a display server)**
**(You MUST stub native dialogs in E2E tests -- `showOpenDialog`/`showSaveDialog` block the process and cannot be interacted with by Playwright)**
</critical_requirements>
---
**Auto-detection:** Electron testing, _electron.launch, electronApp, electronApplication, firstWindow, Playwright Electron, electron-mock-ipc, electron-playwright-helpers, stubDialog, xvfb, xvfb-run, xvfb-maybe, Spectron migration, ipcMain.handle test, ipcRenderer mock, contextBridge mock, BrowserWindow mock, Electron E2E, Electron unit test
**When to use:**
- Writing E2E tests for an Electron application with Playwright
- Unit testing main process code (IPC handlers, lifecycle logic)
- Mocking Electron modules (`dialog`, `BrowserWindow`, `ipcMain`, `ipcRenderer`)
- Testing preload scripts and `contextBridge` APIs
- Setting up headless CI for Electron tests (Linux xvfb)
- Migrating from Spectron to Playwright
- Screenshot/visual regression testing of Electron windows
- Testing auto-update flows
**When NOT to use:**
- Testing renderer UI in isolation (use your web testing skill -- renderer is standard web)
- Writing tests unrelated to Electron-specific APIs
- Performance profiling or benchmarking Electron apps
- Packaging or distributing Electron apps (use the Electron framework skill)
**Key patterns covered:**
- Playwright E2E: `_electron.launch()`, `firstWindow()`, `evaluate()`, assertions
- Main process unit testing with mocked Electron modules
- IPC handler testing (`ipcMain.handle` / `ipcRenderer.invoke`)
- Preload script testing (mock `contextBridge.exposeInMainWorld`)
- Dialog and menu stubbing in E2E tests
- Auto-updater test strategies
- Headless CI configuration (xvfb, GitHub Actions)
- Screenshot and visual regression testing
- Spectron migration path
---
<philosophy>
Philosophy
Electron testing splits along the same boundaries as the Electron process model:
1. **E2E tests** launch the full application with Playwright and exercise the complete flow -- main process, preload, renderer, and IPC together. These are slow but high-confidence. 2. **Main process unit tests** mock the `electron` module and test IPC handlers, lifecycle logic, and business logic in isolation. These are fast and catch logic bugs early. 3. **Renderer tests** are standard web tests -- the renderer is Chromium. Use your existing web testing approach.
**Guiding principle:** Test main process logic with unit tests, test integration through IPC with E2E, and test renderer UI with standard web tools. Don't try to unit test IPC communication itself -- the framework handles message passing. Test that your handlers produce the correct results given inputs.
**When to use E2E (Playwright):**
- Full user workflows (open file, edit, save)
- IPC round-trips that span main and renderer
- Window management (multi-window, modals, frameless)
- Visual regression / screenshot comparison
- Auto-update UI flow
**When to use unit tests:**
- IPC handler logic (validate input, produce output)
- Main process business logic (file operations, data processing)
- Preload API shape (correct channels exposed)
- Configuration and startup logic
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Playwright E2E -- Launch and Basic Assertions
Launch the Electron app, get the first window, and run assertions. Always close in teardown.
import { test, expect, _electron as electron } from "@playwright/test";
import type { ElectronApplication, Page } from "@playwright/test";
let electronApp: ElectronApplication;
let window: Page;
test.beforeEach(async () => {
electronApp = await electron.launch({ args: ["dist/main.js"] });
window = await electronApp.firstWindow();
});
test.afterEach(async () => {
await electronApp.close();
});
test("shows main window with title", async () => {
const title = await window.title();
expect(title).toBe("My App");
await expect(window.locator("h1")).toHaveText("Welcome");
});**Why good:** `afterEach` guarantees cleanup, `firstWindow()` waits for the window to load, standard Playwright assertions work on the Page object
See [examples/core.md](examples/core.md) for evaluate(), multi-window, and environment variable patterns.
---
Pattern 2: Main Process Evaluation
Use `electronApp.evaluate()` to execute code in the main process context and access Electron APIs.
test("returns correct app version", async () => {
const version = await electronApp.evaluate(async ({ app }) => {
return app.getVersion();
});
expect(version).toMatch(/^\d+\.\d+\.\d+$/);
});
test("app path is set correctly", async () => {
const appPath = await electronApp.evaluate(async ({ app }) => {
return app.getAppPath();
});
expect(appPath).toContain("dist");
});**Why good:** `evalua
Showing the first part of this file.
The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?
Repo: agents-inc/skills
Other skills on agents-inc-skills.
- /ai-infrastructure-huggingface-inference
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints
Open skill - /ai-infrastructure-litellm
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment
Open skill - /ai-infrastructure-modal
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Open skill - /ai-infrastructure-ollama
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
Open skill - /ai-infrastructure-replicate
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Open skill - /ai-infrastructure-together-ai
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints
Open skill

