# @lvce-editor/test-with-playwright

## Usage

```json
{
  "scripts": {
    "e2e": "node ./node_modules/@lvce-editor/test-with-playwright/bin/test-with-playwright.js --runtime=browser --only-extension=. --test-path=./e2e"
  }
}
```

```json
{
  "scripts": {
    "e2e:electron": "node ./node_modules/@lvce-editor/test-with-playwright/bin/test-with-playwright.js --electron --test-path=./e2e"
  }
}
```

```js
test('sample.hello-world', async () => {
  const sideBar = Locator('.SideBar')
  await expect(sideBar).toBeVisible()
})
```

## Configuration

Create `e2e.config.js` with a default options object. `defineConfig` is optional and provides editor completion and type checking:

```js
import { defineConfig } from '@lvce-editor/test-with-playwright'

export default defineConfig({
  onlyExtension: '../extension',
  link: ['../extension', '../linked fixture'],
  testPath: '.',
  serverPath: '../../node_modules/@lvce-editor/server/bin/server.js',
  reusePage: true,
  coverageTarget: 'aboutWorkerMain.js',
  coverageInclude: 'packages/about-view/src/',
  coverageThreshold: 75,
})
```

The runner searches the current directory and its parents, using the nearest `e2e.config.js`. Paths in the config resolve relative to that file. CLI and environment paths remain relative to the working directory. Without a config file, existing CLI usage works as before.

All test options below are supported with camelCase names (`onlyExtension`, `testPath`, `traceRendererWorker`, etc.). Use `runtime: 'electron'` for `--electron`, and string arrays for `electronArgs` and `electronEnv`. `help` is CLI-only. The `E2eConfig` type is also exported for JSDoc or TypeScript annotations.

Use `link` to pass one or more extension directories to the browser server. Link paths resolve relative to `e2e.config.js`, and each path is forwarded as an individual `--link` argument, so paths containing spaces are supported.

Precedence, from lowest to highest: built-in defaults, config, environment variables, explicit CLI arguments. CLI arrays replace configured arrays. Use `--no-headless` (or `--headless=false`) to override `headless: true`; the same applies to other boolean test options.

```json
{
  "scripts": {
    "e2e": "test-with-playwright",
    "e2e:headless": "test-with-playwright --headless"
  }
}
```

`npm run e2e -- --headless` also loads the config and overrides only `headless`.

## CLI Flags

- `--runtime`: `browser` (default) or `electron`
- `--electron`: shorthand for `--runtime=electron`; infers the Lvce release from the installed `@lvce-editor/server`
- `--only-extension`: path to the extension under test
- `--test-path`: path to the test root
- `--server-path`: explicit server entry point
- `--filter`: run only matching tests
- `--headless`: run Playwright in headless mode
- `--reuse-page`: run browser tests through `/tests/_all.html` on one page
- `--timeout`: test timeout in milliseconds, defaults to `30000` or `600000` with `--reuse-page`
- `--browser`: browser engine to launch: `chromium`, `firefox`, or `webkit`
- `--coverage`: collect JavaScript coverage with Chromium and write Istanbul reports to `coverage`
- `coverageTarget`: collect coverage from matching Chromium dedicated-worker script URLs (config option)
- `coverageInclude`: restrict worker reports and their threshold to source paths containing this text (config option)
- `coverageThreshold`: require this worker line-coverage percentage from 0 to 100 (config option)
- `--trace-focus`: add `traceFocus=true` to test URLs
- `--trace-renderer-worker`: save renderer-worker command traces in `renderer-worker-traces/`
- `--svg-screenshot-dir`: compare a self-contained SVG screenshot after each passing test with the browser-specific snapshot in this directory
- `--svg-screenshot-selector`: capture only the first matching element, such as `.Explorer`; defaults to the application body
- `--update-svg-screenshots`: create or update locator fixtures and SVG screenshots in `--svg-screenshot-dir`
- `--electron-path`: path to an existing Electron app executable
- `--electron-version`: Lvce release version override; by default Electron uses the installed `@lvce-editor/server` version
- `--electron-cache-dir`: directory for downloaded Electron apps, defaults to `.test-with-playwright/electron`
- `--electron-arg`: extra Electron app argument, can be provided multiple times
- `--electron-env`: Electron environment variable in `NAME=value` form, can be provided multiple times

## Runtime Notes

- `browser` keeps the server-backed HTML test execution flow.
- JavaScript coverage is available for Chromium-based browser and Electron runs. It prints a coverage table and writes `coverage/coverage-final.json`, `coverage/coverage-summary.json`, `coverage/coverage.txt`, and `coverage/lcov.info`.
- `coverageTarget` pauses a matching dedicated worker before its script runs, then writes source-mapped Istanbul reports under `coverage/worker` and applies `coverageThreshold` to line coverage. `coverageInclude` can restrict both the report and threshold to source-map paths for one project. Missing worker coverage fails the run. Firefox and WebKit still run normally; they print a notice and skip worker collection and its threshold because their worker debugging protocols are not supported.
- `--reuse-page` is browser-only. It loads `/tests/_all.html` once and reads JSON results from a hidden `.TestResults` element.
- `electron` downloads or reuses the matching Lvce Electron app, launches it with Playwright and a temporary user data directory, and runs each test module against the first window.
- Chromium uses a fresh temporary disk-backed profile for each run. This avoids a Chromium 153 crash when reading OPFS filesystem handles from in-memory IndexedDB. Playwright removes the profile when the context closes, and teardown awaits that cleanup.
- Electron isolates `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, `XDG_CACHE_HOME` and `XDG_STATE_HOME` beneath its temporary profile, overriding inherited values and `--electron-env` for these paths. The actual home directory is preserved. Profiles are removed after shutdown, including failed or cancelled launches.
- `--electron-path` skips downloading and is useful for custom local builds.
- SVG screenshots are not supported with `--reuse-page`, because that mode exposes only the final application state.

## Renderer Worker Traces

Use a server runtime containing the traced-test URL fix (`@lvce-editor/server` 0.115.5 or newer):

```sh
npm run e2e -- --headless --trace-renderer-worker
npm run e2e -- --headless --reuse-page --trace-renderer-worker
```

Fresh-page runs write one JSON file per test; reused-page runs write `_all.json`. Each file retains the runtime’s `entries` array and adds a `timeline` with message-port and worker traffic, input events and DOM mutations. Timeline entries have a shared sequence number, timestamp and channel ID for RPC traffic, so view render patches can be correlated with input and DOM changes. This is browser observation order; MutationObserver batches changes rather than timestamping each individual mutation. Check that `timeline.entries` includes the scenario’s commands, inputs and render mutations before relying on a capture. The timeline retains its most recent 5,000 events and reports `dropped` events. RPC payloads are bounded text previews (8,192 characters, with individual strings limited to 2,048) and carry a `truncated` flag; DOM records also contain bounded node summaries and original counts. Save needed traces before starting another trace-enabled run, which clears the output directory.

## SVG Screenshot Tests

Add `--svg-screenshot-dir=./snapshots` to compare each passing test's final application state with a committed SVG. Use `--svg-screenshot-selector=.Explorer` for a focused Explorer View snapshot. Snapshot names include the runtime, for example `viewlet.explorer-open.chromium.svg`, so browser-specific output does not conflict.

Create or intentionally update the snapshots with:

```sh
npm run e2e -- --svg-screenshot-dir=./snapshots --update-svg-screenshots
```

The screenshot converts the rendered DOM to SVG shapes with the computed visual properties already applied. Fonts and images are inlined, test result overlays are excluded, animations and carets are frozen, and no page scripts are included. A mismatch writes an adjacent `.actual` file for inspection and fails the test.

## Reuse Page Results

When `--reuse-page` is enabled, `/tests/_all.html` should run the tests and write a JSON array into `.TestResults`:

```json
[
  {
    "name": "sample.hello-world.js",
    "status": "pass",
    "error": "",
    "start": 0,
    "end": 12.5
  }
]
```

`status` must be `pass`, `skip`, or `fail`. `error` is optional and defaults to an empty string.

## Environment Variables

- `ONLY_EXTENSION`
- `TEST_PATH`

### Awaitable locator screenshots

With a screenshot-capable renderer and test-worker, capture an element at a specific point in a test:

```js
await expect(Locator('.DialogContent')).toMatchScreenShot('about/dialog.chromium.png')
```

The URI is a relative `.svg` or `.png` path within the test project's `fixtures` directory (beside `src`). Absolute paths, traversal and symbolic links are rejected. Missing elements, missing baselines and different screenshots fail the awaiting assertion with the locator or fixture path. Run `test-with-playwright --update-screenshots` to create or replace fixtures; ordinary runs preserve baselines and save differing output beside them as `.actual` for SVG or `.actual.png` for PNG. The locator matcher supports both individual and reused pages. The existing post-test `--svg-screenshot-dir` mode still requires individual pages.

SVG capture retains rendered styles and inlines resources, dropping unused font definitions. Wait for stable application content before capturing; use separate fixtures per browser/platform when their rendering differs. Updates should be reviewed as visual changes before committing.

PNG is supported for features that SVG conversion cannot reproduce, including CSS mask icons. PNG comparison is exact and requires a stable browser, viewport and font environment; keep separate baselines when these differ. `--update-svg-screenshots` remains an alias for the update option.
