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
  • 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), add the package inside package.json:

npm install -D merv-client

Note: merv-client expects @playwright/test ≥ 1.40.0 as a peer dependency. Use Node.js versions supported by your Playwright release.

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.0"
  },
  "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.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, …
  },
});
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

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:….

  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.

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

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.0; 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