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.

You will learn
  • How to install and configure merv-client / merv-client-playwright
  • How to use automated setup (doctor setup) or configure files manually
  • How to align @playwright/test versions in package.json (TypeScript / local links)
  • 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, and info rows in reports

Installing merv-client

Inside your Playwright project root (where package.json and playwright.config live):

npm install -D merv-client merv-client-playwright @playwright/test

Note: expect @playwright/test ≥ 1.30.0 as a peer dependency. Use Node.js versions supported by your Playwright release. Legacy projects may still install merv-client alone and use merv-client/playwright-reporter re-exports.

Automated setup (doctor)

After install, run the Playwright doctor. It creates or heals MERV wiring (merv.properties, reporter entry, bridge/jsconfig) without wiping unrelated project settings.

# Install first (required on every machine)
npm install -D merv-client-playwright

# Then run doctor
npx merv-client-playwright doctor setup
npx merv-client-playwright doctor setup --typescript

# Windows alternatives if npx bin is not found
npm exec -- merv-client-playwright doctor setup
node node_modules/merv-client-playwright/dist/cli.js doctor setup

Then run tests and open the dashboard with npx merv show-report. Prefer manual setup below if you want every file edited by hand.

Manual setup

Skip doctor and configure MERV yourself: create merv.properties, register the reporter, then optionally Option A / plugin steps.

package.json — align Playwright versions (important)

as merv-client using the same version of Playwright as your project, you need to align the versions in your package.json in order to avoid conflicts. You can do this by pinning @playwright/test at the project root and add npm overrides so nested merv-client dependencies resolve the same packages.

{
  "devDependencies": {
    "@playwright/test": "1.59.1",
    "merv-client": "^4.0.22"
  },
  "overrides": {
    "merv-client": {
      "@playwright/test": "$@playwright/test",
      "playwright": "$playwright",
      "playwright-core": "$playwright-core"
    }
  }
}

After editing, run npm install and confirm with npm ls @playwright/test playwright-core — all entries should show one version. Restart the TypeScript server in your IDE. This will ensure that merv-client uses the same version of Playwright as your project.

What’s installed

Merv does not replace Playwright. After you configure the reporter and run tests, each execution creates a timestamped folder under user defined folder for merv.report.folder key in merv.properties file:

merv-reports/ index.html # Dashboard (all runs) merv-index-data.json # Polled by live dashboard 15-05-2026 14-23-41 Merv-Report/ json/merv-report.json # Suite + testcase data html/merv-report.html # Final suite report html/merv-report-live.html # Live report during run screenshots/ # Step images

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).

Sample Configuration

merv.local=true
merv.regression_suite=Playwright Regression
merv.report.folder=./merv-reports/

Download sample merv.properties

Common properties

Property Role
merv.local true — Merv-Local: write HTML/JSON reports on disk under merv.report.folder (no cloud API).
false — Merv-Server: send suites, cases, and steps to the MERV cloud API (set merv.server, API key, and hierarchy as well).
merv.report.folder Root for timestamped run folders.
merv.regression_suite Suite title in JSON and HTML.
merv.screenshot true — capture a viewport PNG after major Playwright actions and after each expect() matcher (requires wrapped test / expect from merv-client/playwright-test).
false — do not capture step screenshots (smaller report folders; failed tests still show errors without PNGs).
merv.emailable.html true — write interactive emailable-report.html when the suite finishes (doctor defaults to false). Suite Share / Download: guide.
merv.debug=true Include hooks, fixtures, and all test.step categories in the report. Ignored when merv.step.allowed is set.
merv.step.allowed=info,hook,assertion,action Optional allowlist of step categories. Categories not listed are omitted from the report. info — informative / data / custom; hook — before/after hooks & fixtures; assertion — Playwright expect, Chai, and plugin validations; action — click, fill, goto, and other API actions. When set, overrides merv.debug / merv.report.extra_step_types.
merv.report.extra_step_types Surface tagged test.step types when debug is off. Ignored when merv.step.allowed is set.
merv.plugin_assertion_soft=true Record failed plugin validations without failing the Playwright test.
merv.chai=true When the optional chai package is installed, record Chai expect / assert checks as MERV ASSERTION steps (default on). Set merv.chai=false to disable. Requires MERV’s wrapped test from merv-client/playwright-test. See Chai assertions.

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, …
  },
});
Do: ['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
Tips: See the browser: 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://).

Open with a web server

Recommended: from the project root (where merv.properties lives):
npx merv show-report
npx merv-client show-report
npm run show-report

# Explicit folder / options
npx merv show-report ./merv-reports
npx merv show-report --port 6174
npx merv show-report --host 127.0.0.1
npx merv show-report --host 0.0.0.0
npx merv show-report --no-open
npx merv show-report ./merv-reports --port 8080 --no-open

Opens http://127.0.0.1:6174/ (dashboard). Also available: http://127.0.0.1:6174/merv-logs.html (Merv-Logs). Stop with Ctrl+C.

  1. Install the Live Server extension (search Live Server in the Extensions view).
  2. In the Explorer, open your report folder (for example merv-reports/).
  3. Right-click index.html and choose Open with Live Server (or click Go Live in the status bar when that folder is the workspace root).
  4. Your browser opens something like http://127.0.0.1:5500/merv-reports/index.html — use that URL for the dashboard.
  5. For one run: open {runFolder}/html/merv-report.html or merv-report-live.html via the same server (from the dashboard links or by pasting the path after the Live Server host).
Tip: While tests run, keep 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.
Merv-Logs: If you open the report with Live Server, Merv-Logs will not show logs (the logs API is only available with npx merv show-report). Use npx merv show-report and open http://127.0.0.1:6174/merv-logs.html (or the Merv-Logs sidebar link). See the Merv-Logs guide.
No logs on another machine?
  1. After a run, check disk: merv-reports/log/*.ndjson and merv-reports/log/manifest.json (path follows merv.report.folder).
  2. Use merv-client, merv-client-playwright, and merv-client-cucumber at 4.0.22+.
  3. Playwright: the MERV reporter writes step lines by default (merv.logger.reporter.steps). For richer locator lines, import test from merv-client-playwright/test (doctor bridge) and set merv.logger.reporter.steps=false to avoid duplicates.
  4. Do not set merv.logger.file=false unless you intentionally disable file logs.
  5. View logs with npx merv show-report — opening HTML alone does not load the live log stream.

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.

Add Custom Step and Screenshot Types

To add Custom Steps and many other merv feature to make your tests more readable and maintainable. Recommended for large suites: keep Playwright-style imports, but resolve them to Merv’s wrapped test via a one-time bridge, Pick your project language below.

  1. Create tests/support/playwright-test-bridge.js:
    export * from 'merv-client/playwright-test';
  2. Add jsconfig.json at 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"
      ]
    }
  3. Add package.json imports (required for .js at runtime):
    {
      "type": "module",
      "imports": {
        "@playwright/test": "./tests/support/playwright-test-bridge.js"
      }
    }
  4. Import everything from @playwright/test in specs — including MervPlaywrightHandler: (not mandatory as of now, check below in sample code)
    import { expect, test, MervPlaywrightHandler } from '@playwright/test';
  5. Verify: npx playwright test --list, then npm test.
Tip: Do not mix import { test } from '@playwright/test' with import { MervPlaywrightHandler } from 'merv-client' — plugin steps and screenshots need a single import source.

playwright.config still registers merv-client/playwright-reporter in reporter: [] — do not import the reporter from root merv-client in config. For TypeScript, set tsconfig: './tests/tsconfig.json' in config and keep the @playwright/test bridge alias in tests/tsconfig.json only (see TypeScript tab above).

Adding Custom Steps in Reports

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?) to pass test-data to the report
validation(name, expected?, actual?, screenshot?) to pass validation to the report
info(text) to pass info to the report

More Configuration

In order to implement these configurations, we need to implement bridge setup properly as mentioned in the previous section

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

for custom steps — pass true as the last argument:

await merv.data('Order Id', '12349893', true);
await merv.validation('Status', '200', '200', true);

In plaugin manner, in merv.properties, it will add screenshot automatically after each locator/page action and after each expect matcher :

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.

Soft plugin failure

Record a failed validation in the report without failing the Playwright test:

merv.plugin_assertion_soft=true

Chai assertions

If your suite uses Chai (expect / assert) as well as Playwright’s built-in expect, MERV reports both:

Assertion style MERV step type
Playwright expect(…) EXPECT (from the Playwright reporter)
Chai expect / assert ASSERTION (from the Chai hook)

Install Chai in the project (npm i -D chai). With MERV’s wrapped test, leave merv.chai=true (default) so Chai is hooked automatically. Or install manually:

import chai from 'chai';
import { installMervChai } from 'merv-client/chai';

installMervChai(chai);
export const { expect, assert } = chai;

Both step types sit under the assertion category in merv.step.allowed. Do not wrap the same check in both libraries — you would get two rows for one logical assertion. Set merv.chai=false to turn Chai reporting off.

MervReport (explicit)

For a full custom-report guide (no Playwright reporter) with Java, JavaScript, and TypeScript tabs, see Custom report guide.

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

  1. Keep merv.properties at the project root.
  2. import { MervReport } from 'merv-client';
  3. const report = MervReport.open(); — creates a new run folder.

Report object

const report = await MervReport.open();
await report.createTest('Login API', 'POST /auth with valid user');
await report.testdata('Request body', JSON.stringify({ user: 'a@b.com' }));
await report.validation('Status code', '200', '200');
await report.validation('Title', 'Home', 'Home', true); // optional screenshot
await report.info('Using staging tenant');
await report.finalize();

Custom steps on MervReport: info, testdata (string or new MervReportFile(path)), and validation (with optional screenshot flag).

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 (JavaScript); valid jsconfig.json (no comments). For TypeScript, use tests/tsconfig.json + tsconfig in playwright.config.ts.
Page type mismatch / duplicate Playwright types Add package.json overrides (see Playwright overrides); run npm install; verify with npm ls playwright-core.
test.describe() / test() “not expected here” Bridge alias on root tsconfig.json loads MERV shim in config while specs use stock @playwright/test. Move alias to tests/tsconfig.json; set tsconfig: './tests/tsconfig.json' in config.
merv.screenshot=true but no step screenshots Wrapped test / expect not active — check tests/tsconfig.json uses "baseUrl": ".." (not ".") and path tests/support/playwright-test-bridge.ts; set tsconfig: './tests/tsconfig.json' in config.
Cannot find module 'merv-client/playwright-test' in bridge tests/tsconfig.json missing "moduleResolution": "bundler" (often because extends was removed). Add "extends": "../tsconfig.json" or inline bundler in the tests file.
Invalid value for ignoreDeprecations in tests/tsconfig.json Inherited "ignoreDeprecations": "6.0" but IDE uses TypeScript 5.x. Remove that option from tsconfig; optional TS 6-only silencer.
{ page } implicitly any in specs Bridge types not loading — same root cause as expect / merv-client resolution. Use bundler + export type * in bridge; restart TypeScript server.
IDE: expect / test “not exported” (tests still run) "moduleResolution": "bundler" via extends or inline; merv-client ≥ 4.0.22; npm install; restart TypeScript server. Root tsconfig.json (no alias) for pages/.
“Requiring @playwright/test second time” Reporter imported from root merv-client in config. Use merv-client/playwright-reporter in reporter: [] only.

What’s next

← Back to Documentation