Merv-Local + Playwright guide
Introduction
Playwright Test
is an end-to-end framework for modern web apps. Merv-Local adds rich HTML/JSON reports,
a run dashboard, and Java-style plugin steps on top of your existing Playwright project via the
merv-client npm package.
- How to install and configure
merv-client - What gets created under your report folder
- How to run tests and open the Merv dashboard
- How to keep
import from '@playwright/test'(Option A) - How to add
data,validation, andinforows in reports
Installing merv-client
From your Playwright project root (where package.json and
playwright.config live), add the package:
npm install -D merv-client
merv-client expects @playwright/test ≥ 1.40.0 as a peer
dependency. Use Node.js versions supported by your Playwright release.
What’s installed
Merv does not replace Playwright. After you configure the reporter and run tests, each execution creates
a timestamped folder under merv.report.folder:
playwright.config stays your central Playwright configuration (browsers, timeouts,
projects). Add one reporter entry for Merv alongside list or the built-in HTML reporter —
use ['merv-client/playwright-reporter', {}] (see Register the reporter).
Testcase tags are filled automatically: any @word in the test title becomes a tag
(e.g. Verify Login @login with @abc → @login, @abc). When the title or
Playwright project name contains chromium, the browser tag chrome is added for
consolidated and KPI filters.
Configure merv.properties
Create merv.properties next to package.json. The reporter and test wrapper read
it from the project root (or an ancestor directory).
Minimal configuration
merv.local=true
merv.regression_suite=Playwright Regression
merv.report.folder=./merv-reports/
Common properties
| Property | Role |
|---|---|
merv.report.folder |
Root for timestamped run folders. |
merv.regression_suite |
Suite title in JSON and HTML. |
merv.screenshot=true |
Viewport PNG after major Playwright actions and after each expect() matcher (requires wrapped test / expect from merv-client/playwright-test). |
merv.debug=true |
Include hooks, fixtures, and all test.step categories in the report. |
merv.report.extra_step_types |
Surface tagged test.step types when debug is off. |
merv.plugin_assertion_soft=true |
Record failed plugin validations without failing the Playwright test. |
Register the reporter
In playwright.config.js or playwright.config.ts, register Merv in the
reporter array using the dedicated subpath
merv-client/playwright-reporter — not the root
merv-client package. Playwright loads config before your tests run; the subpath loads only
the reporter entry point and avoids pulling in the wrapped test shim (which can trigger
“Requiring @playwright/test second time” warnings).
Reporter entry (required)
reporter: [
['list'],
['merv-client/playwright-reporter', {}],
],
Full playwright.config example
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
reporter: [
['list'],
['merv-client/playwright-reporter', {}],
],
use: {
// baseURL, trace, screenshot, …
},
});
['merv-client/playwright-reporter', {}] in reporter: [].Don’t:
import … from 'merv-client' in playwright.config to register the reporter — use the subpath string only.
Running your tests
Run from the directory that contains merv.properties. By default Playwright runs headless;
Merv writes JSON and refreshes reports as tests complete.
npx playwright test
npx playwright test --headed.
Run one file: npx playwright test tests/example.spec.js.
Open UI mode: npx playwright test --ui.
With only the reporter registered, you can keep import { test, expect } from '@playwright/test'
— the report shows Playwright API and expect steps. For plugin steps and screenshots, use
the wrapped test (see below).
Viewing Merv reports
After a run, reports live under {merv.report.folder} (for example
./merv-reports/). Open these paths through a local web server — not by
double-clicking HTML in the file manager (file://).
index.html— dashboard: suite grid, KPI charts, consolidated views{runFolder}/html/merv-report.html— final suite report for one run{runFolder}/html/merv-report-live.html— live suite view while tests run (pollsjson/merv-report.json)
Open with a web server
Merv-Local reports load JSON, charts, and screenshots with fetch. Browsers often block that
on file:// URLs. Use your IDE’s built-in static server (or any local HTTP server) so
the address bar shows http://localhost:….
- Install the Live Server extension (search Live Server in the Extensions view).
-
In the Explorer, open your report folder (for example
merv-reports/). -
Right-click
index.htmland choose Open with Live Server (or click Go Live in the status bar when that folder is the workspace root). -
Your browser opens something like
http://127.0.0.1:5500/merv-reports/index.html— use that URL for the dashboard. -
For one run: open
{runFolder}/html/merv-report.htmlormerv-report-live.htmlvia the same server (from the dashboard links or by pasting the path after the Live Server host).
merv-report-live.html open on Live Server.
Merv blocks Live Server’s full-page reload when JSON changes; the live page and dashboard
update in place instead of flashing a full refresh.
-
In the Project tool window, locate
merv-reports/index.html(or yourmerv.report.folderpath). -
Right-click
index.htmland choose Open in Browser (or Preview in some editions). IntelliJ serves the file from its built-in web server (typicallyhttp://localhost:63342/…). -
Use the browser tab URL as your dashboard link. Open suite reports the same way:
right-click
merv-report.htmlormerv-report-live.htmlunder{runFolder}/html/and Open in Browser. -
If the page is blank or requests fail, confirm the address is
http://…, notfile://…. Use Tools → Web Browsers to pick Chrome, Edge, or Firefox if needed.
The same steps apply in WebStorm and other JetBrains IDEs that include the embedded static server.
Other editors and CI
Any local static server works: for example
npx serve merv-reports or
python3 -m http.server --directory merv-reports, then open
http://localhost:…/index.html. In CI, publish the merv-reports folder as an
artifact and serve it from your pipeline’s report viewer or object storage with HTTP access.
Keep import from '@playwright/test'
Recommended for large suites: keep Playwright-style imports, but resolve them to Merv’s wrapped
test via a one-time bridge (Option A). Pick your project language below.
-
Create
tests/support/playwright-test-bridge.js:export * from 'merv-client/playwright-test'; -
Add
jsconfig.jsonat the project root (strict JSON — no//comments):{ "compilerOptions": { "baseUrl": ".", "allowJs": true, "checkJs": false, "paths": { "@playwright/test": ["./tests/support/playwright-test-bridge.js"] } }, "include": [ "playwright.config.js", "tests/**/*.js", "tests/support/**/*.js" ] } -
Add
package.jsonimports(required for.jsat runtime):{ "type": "module", "imports": { "@playwright/test": "./tests/support/playwright-test-bridge.js" } } -
Import everything from
@playwright/testin specs — includingMervPlaywrightHandler:import { expect, test, MervPlaywrightHandler } from '@playwright/test'; - Verify:
npx playwright test --list, thennpm test.
import { test } from '@playwright/test' with
import { MervPlaywrightHandler } from 'merv-client' — plugin steps and screenshots need a single import source.
-
Create
tests/support/playwright-test-bridge.ts:export * from 'merv-client/playwright-test'; -
Add
tsconfig.jsonat the project root with a path alias to the bridge:{ "compilerOptions": { "baseUrl": ".", "paths": { "@playwright/test": ["./tests/support/playwright-test-bridge.ts"] } }, "include": [ "playwright.config.ts", "tests/**/*.ts", "tests/support/**/*.ts" ] } -
Import everything from
@playwright/testin specs — includingMervPlaywrightHandler:import { expect, test, MervPlaywrightHandler } from '@playwright/test'; - Verify:
npx playwright test --list, thennpm test.
For mixed .js / .ts repos, also add package.json
imports pointing at the bridge (same as the JavaScript tab, step 3).
tsconfig.json paths.
Alternative: import directly from merv-client/playwright-test in every spec (no bridge).
playwright.config still registers merv-client/playwright-reporter in
reporter: [] — do not import the reporter from root merv-client in config.
Writing plugin steps
Use MervPlaywrightHandler with Playwright’s testInfo to add explicit rows
merged into the same testcase as Playwright steps.
import { expect, test, MervPlaywrightHandler } from '@playwright/test';
test('checkout', async ({ page }, testInfo) => {
const merv = new MervPlaywrightHandler(testInfo);
await merv.data('Request', JSON.stringify({ sku: 'SKU-1' }));
await merv.validation('Cart total', '$42.00', '$42.00', true);
await merv.info('Environment: staging');
await page.goto('/cart');
await expect(page.getByRole('heading')).toBeVisible();
});
| Method | Role |
|---|---|
data(name, testdata, screenshot?) |
TEST_DATA row. Pass true last for a viewport PNG. |
validation(name, expected?, actual?, screenshot?) |
ASSERTION row. Pass true last for a viewport PNG. |
info(text) |
Info / prerequisite row. |
Configuration
Debug mode
By default each testcase shows Playwright API actions and expect steps. To include hooks,
fixtures, and every test.step category:
merv.debug=true
Screenshots
Per plugin step — pass true as the last argument:
await merv.data('Order Id', '12349893', true);
await merv.validation('Status', '200', '200', true);
After Playwright actions and expect() — optional, in merv.properties:
merv.screenshot=true
Captures a viewport PNG after each locator/page action and after each expect matcher (pass or fail).
Requires wrapped test and expect from merv-client/playwright-test (Option A or direct import).
Soft plugin failure
Record a failed validation in the report without failing the Playwright test:
merv.plugin_assertion_soft=true
MervReport (explicit)
Use MervReport when you want the same folder layout and JSON contract without
registering the Playwright reporter — for scripts or hand-built testcase rows.
Setup
- Keep
merv.propertiesat the project root. import { MervReport } from 'merv-client';const report = MervReport.open();— creates a new run folder.
Report object
const report = MervReport.open();
report.createTest('Login API', 'POST /auth with valid user');
await report.validation('Status code', '200', '200');
report.finalize();
Step object
Each step row in JSON includes teststepName, stepType, status,
optional expected / actual, testdata, screenshots, and
errorMessage when applicable.
Troubleshooting
| Issue | What to check |
|---|---|
No reports under merv.report.folder |
['merv-client/playwright-reporter', {}] in config; merv.properties on disk; run from project root. |
| Plugin steps missing | Import wrapped test (Option A or merv-client/playwright-test); import MervPlaywrightHandler from the same source. |
data(…, true) has no screenshot |
Rebuild merv-client; use wrapped test; call after page exists. |
| Option A not applied | Add package.json imports; valid jsconfig.json (no comments). |
What’s next
- Run tests in headed mode or UI mode — Running tests
- Read the full integration guide in
merv-client-js/FRAMEWORK_INTEGRATION.md - Merv-Local documentation — dashboard, JSON contract, other frameworks
- API documentation — server mode and REST APIs
MERV