Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ npx @modelcontextprotocol/inspector node dist/index.js --headless --viewport 128
npm run inspector:dev
```

## Testing

```bash
npm run test:run # all tests once (unit + integration)
npm test # watch mode
```

See [docs/testing.md](docs/testing.md) for full details on running specific test suites, the e2e scenario coverage, and known issues.

## Troubleshooting

- Firefox not found: pass `--firefox-path "/Applications/Firefox.app/Contents/MacOS/firefox"` (macOS) or the correct path on your OS.
Expand All @@ -180,7 +189,7 @@ npm run inspector:dev
```

> **The Key Change:** On Windows, running a Node.js package via `npx` often requires the `cmd /c` prefix to be executed correctly from within another process like VSCode's extension host. Therefore, `"command": "npx"` was replaced with `"command": "cmd"`, and the actual `npx` command was moved into the `"args"` array, preceded by `"/c"`. This fix allows Windows to interpret the command correctly and launch the server.

- **Solution 2** Instead of another layer of shell you can write the absolute path to `npx`:

```json
Expand Down
62 changes: 62 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Testing

## Running tests

```bash
# Run all tests once (unit + integration)
npm run test:run

# Run only unit tests (fast, no Firefox needed)
npx vitest run tests/tools tests/firefox tests/utils tests/snapshot tests/cli tests/config tests/smoke.test.ts

# Run only integration tests (launches real Firefox in headless mode)
npx vitest run tests/integration

# Run the e2e scenario suite
npx vitest run tests/integration/e2e-scenario.integration.test.ts

# Watch mode (re-runs on file changes)
npm test
```

## E2E scenario tests

The file `tests/integration/e2e-scenario.integration.test.ts` contains end-to-end
tests that exercise the full `FirefoxClient` API against a realistic multi-page
web application (`tests/fixtures/e2e-app.html`).

The fixture app has three pages (Todo List, Search, Registration Form) plus
always-visible hover/double-click targets. Each `describe` block launches its own
headless Firefox instance and tears it down after the tests.

All tests are self-contained (no ordering dependencies) and use active polling
(`waitFor`) instead of fixed sleeps for async BiDi events.

### Covered scenarios (24 tests)

| Scenario | What it tests |
| --------------------- | ---------------------------------------------------------------------- |
| Todo App Workflow | `takeSnapshot`, `fillByUid`, `clickByUid`, `evaluate` |
| Click Interactions | `clickByUid` (double-click), `hoverByUid` |
| Multi-Page Navigation | SPA page switching via UID clicks |
| Browser History | `navigateBack`, `navigateForward` |
| Viewport Resize | `setViewportSize` + relative dimension verification |
| Search Workflow | fill + click + result verification |
| Form Submission | `fillByUid`, `fillFormByUid` (batch), form submit |
| Console Monitoring | `getConsoleMessages`, `clearConsoleMessages` |
| Network Monitoring | `startNetworkMonitoring`, `getNetworkRequests`, `clearNetworkRequests` |
| Screenshot | `takeScreenshotPage` (base64 output) |
| Tab Management | `createNewPage`, `selectTab`, `closeTab`, `getTabs`, `refreshTabs` |
| Stale UID Detection | navigation invalidates old UIDs, `clearSnapshot` |
| Error Handling | invalid UID format, unknown UID, stale snapshot UID |

### Design principles

- **Self-contained**: each test navigates to its own page, no inter-test dependencies
- **Active polling**: async events (console, network) use `waitFor` instead of fixed sleeps
- **Relative assertions**: viewport tests assert relative change, not exact pixel values (platform-dependent)
- **Isolated Firefox instances**: each `describe` block gets its own headless Firefox

## Known issues

- **Firefox 148 startup crash on macOS ARM64** ([Bug 2027228](https://bugzilla.mozilla.org/show_bug.cgi?id=2027228)): Intermittent SIGSEGV in `RegisterFonts` thread (`RWLockImpl::writeLock()` null pointer) when launching Firefox in headless mode via Selenium. The crash is a race condition in Firefox font initialization and does not affect test results — Selenium recovers automatically. More likely to occur under fast sequential startup/shutdown cycles.
Loading