Skip to content
Testing
Skill

/e2e-test

Write a new Playwright E2E test for Vortex. Accepts a plain-text description of what to test, or a Linear issue ID to fetch the description automatically. Uses Chrome DevTools MCP to inspect the live app and source code to produce a well-structured spec.

From plugin
vortex
1.5k2 skills1 MCP
Install
$ npx -y skills add Nexus-Mods/Vortex --skill e2e-test --agent claude-code

How 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.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/e2e-test

Context preview

The summary Claude sees to decide when to auto-load this skill.

Write a new Playwright E2E test for Vortex. Accepts a plain-text description of what to test, or a Linear issue ID to fetch the description automatically. Uses Chrome DevTools MCP to inspect the live app and source code to produce a well-structured spec.

SKILL.md

e2e-test.SKILL.md
name: e2e-test
description: Write a new Playwright E2E test for Vortex. Accepts a plain-text description of what to test, or a Linear issue ID to fetch the description automatically. Uses Chrome DevTools MCP to inspect the live app and source code to produce a well-structured spec.
when_to_use: When the user wants to add, scaffold, or write a new E2E test for Vortex.
user-invocable: true
allowed-tools: mcp__linear-server__list_issues mcp__chrome-devtools__click mcp__chrome-devtools__take_snapshot

E2E Test Writing Skill

You help developers write Playwright E2E tests for Vortex, an Electron desktop app. Tests live in `packages/e2e/src/tests/` and MUST follow `packages/e2e/E2E-BEST-PRACTICES.md`.

Step 1 — Gather scope

If `$ARGUMENTS` contains a Linear issue ID (pattern: `LAZ-\d+` or similar `[A-Z]+-\d+`):

  • Fetch the issue using the `mcp__linear-server__get_issue` tool
  • Extract the title and description to understand what needs to be tested

If `$ARGUMENTS` is a plain-text description, use it directly.

If no arguments were provided, ask the user: "What should the test cover? Provide a description or a Linear issue ID."

Before proceeding, **confirm the scope** with the user in one or two sentences: what flows will be tested, which Vortex pages are involved, and whether auth (freeUser/premiumUser) is needed.

Step 2 — Understand the existing code

Read the relevant existing files to understand patterns and available building blocks:

  • `packages/e2e/E2E-BEST-PRACTICES.md` — rules you must follow
  • `packages/e2e/src/selectors/` — existing POMs (check if a relevant one already exists)
  • `packages/e2e/src/helpers/` — shared utilities (navigation, timeouts, users, etc.)
  • `packages/e2e/src/fixtures/vortex-app.ts` — available fixtures
  • `packages/e2e/src/tests/` — existing specs; skim them for flows you'll need

(download a mod, log in, manage a game, navigate to a page). If another test already does what you're about to write, that's a signal to reuse or extract it — see "Reuse over duplication" in Step 3.

  • Source code under `src/renderer/` for UI component structure and text strings

Step 3 — Write a first draft

Follow ALL rules from `E2E-BEST-PRACTICES.md`. It is fine for selectors and intermediate steps to be uncertain at this point: the inspector loop in Step 4 exists to discover and correct them against the live app.

At each step whose selector or behavior you are unsure about, insert a breakpoint so the loop can pause there:

import { llmBreakpoint } from "../helpers/inspect";
// ...
await llmBreakpoint(vortexWindow, "after manage game");

`llmBreakpoint` is a no-op unless `VORTEX_E2E_INSPECT` is set, so the calls are safe to leave in the spec while iterating. Strip them once the test is green.

Reuse over duplication (DRY)

Before writing a block of logic, check whether an existing spec already does the same thing (a download flow, a login sequence, a multi-step navigation). If so, don't copy it — follow the **Helpers** guidance in `E2E-BEST-PRACTICES.md`: extract it into a `packages/e2e/src/helpers/` function, call it from your test, and update the other spec(s) to use the same helper.

Step 4 — Inspector loop (run, walk, fix, repeat)

The dev inspector runs **the real test** (fixtures: login snapshot, managed game, image stubs) headed and single-worker, and launches the app with a fixed CDP endpoint on `127.0.0.1:9222` that Chrome DevTools MCP attaches to.

Resolve the shared tmp paths the same way `llmBreakpoint` does (running `node` guarantees the shell and the test agree on `os.tmpdir()` on every platform), clear any stale files from a prior run, then start the single test you are authoring. Redirect its output to a log file, and write a **done sentinel** the moment the runner exits (in a subshell, so it fires on pass, fail, or crash) so the poll below can tell a pause apart from an early exit. Run this with `run_in_background` so the terminal stays free:

TMP="$(node -e 'console.log(require("os").tmpdir())')"
PAUSE_FILE="$TMP/vortex-e2e-pause"
LOG_FILE="$TMP/vortex-e2e-dev.log"
DONE_FILE="$TMP/vortex-e2e-dev.done"
rm -f "$PAUSE_FILE" "$LOG_FILE" "$DONE_FILE"
( VORTEX_E2E_GREP="<test name>" pnpm nx run @vortex/e2e:dev > "$LOG_FILE" 2>&1; echo $? > "$DONE_FILE" )

`VORTEX_E2E_GREP` is read by `playwright.config.ts` as the test grep, so it must match exactly one test. Passing it as an env var (rather than a trailing CLI arg) survives forwarding through pnpm and nx cleanly.

When the run reaches an `llmBreakpoint` it creates `$PAUSE_FILE` (containing the label) and blocks indefinitely. But the test can also **fail before reaching the breakpoint** (wrong selector, assertion error, launch failure), in which case `$PAUSE_FILE` is never created and the runner exits, writing `$DONE_FILE`. So the wait must poll for **either** outcome: pause-file appears, **or** done-file appears. Never poll for the pause file alone, it would hang forever on a pre-breakpoint failure.

TMP="$(node -e 'console.log(require("os").tmpdir())')"
PAUSE_FILE="$TMP/vortex-e2e-pause"
LOG_FILE="$TMP/vortex-e2e-dev.log"
DONE_FILE="$TMP/vortex-e2e-dev.done"
while [ ! -f "$PAUSE_FILE" ] && [ ! -f "$DONE_FILE" ]; do sleep 0.5; done
if [ -f "$PAUSE_FILE" ]; then
  echo "[PAUSED] $(cat "$PAUSE_FILE")"
else
  echo "[RUNNER EXITED before breakpoint, code $(cat "$DONE_FILE")] read the log to see why it failed:"
  tail -n 80 "$LOG_FILE"
fi

Uses only `[ -f ]`, `cat`, and `sleep` (no PIDs or signals), so it works on Linux, macOS, and Git Bash on Windows. If it prints `[RUNNER EXITED ...]`, the test failed: read the log tail, fix the spec, and re-run from the launch step. Only drive the MCP when it prints `[PAUSED]`. (A `[E2E-PAUSE] <label>` console line is also emitted but is not guaranteed to reach stdout, so do not grep for it.)

While paused, drive the live app via the MCP:

  • `list_pages` → `select_page` for the `index.html` window
  • `take_snapshot` for t
Read more
Ships withvortex

Vortex Development

Get the whole plugin
Stats
1,460
Stars
219
Forks
Active
Maintenance
TypeScript
Language
GPL-3.0
License
3d ago
Last commit
9y ago
Created

Repo: Nexus-Mods/Vortex