Custom report — hand-built suites, tests & steps
Introduction
Use a custom report when your automation is not wired through Cucumber, Cucumber-js, TestNG, JUnit, or the Playwright reporter — but you still want MERV suites, testcases, plugin-style steps, validation rows, test data, info lines, and screenshots in the same HTML dashboard or Merv App.
- How to open a report session and create testcases manually
- How to add
info,testdata, andvalidationsteps - How to attach screenshots and files
- Java (
MervClient), JavaScript, and TypeScript (MervReport) examples
When to use a custom report
- Standalone scripts, CLI tools, or batch jobs that run checks outside a test framework
- Prototypes and spikes before adopting a full Cucumber / Playwright integration
- Hybrid pipelines that already have pass/fail logic but need MERV HTML or cloud storage
- Microservice or API checks where you control suite/test/step structure in code
npm install merv-client.
Install merv-client-playwright for Playwright Test, or
merv-client-cucumber for Cucumber-js — not for hand-built MervReport scripts.
Automated setup (doctor)
For JavaScript / TypeScript projects, install core and run the core doctor.
It creates or fills missing merv.* keys and a sample custom-report script without wiping unrelated settings.
npm install merv-client
npx merv-client doctor setup
npx merv-client doctor setup --typescript
Then run the generated script (or your own) and open the dashboard with
npx merv show-report. Prefer manual setup below for full control.
Manual setup
Skip doctor and configure by hand: add
merv.properties, then follow the
language examples (Java / JS / TS) to call MervReport.open()
(or Java MervClient) yourself.
merv.properties
Place merv.properties at the project root (directory you run from).
Sample Configuration (Merv-Local)
merv.local=true
merv.report.folder=./merv-reports/
merv.regression_suite=Custom Report Suite
merv.emailable.html=false
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 and index.html dashboard. |
merv.regression_suite |
Suite title in JSON and HTML. |
merv.execution.parallel |
true — parallel workers share one suite folder safely.false — single-threaded run (default for scripts).
|
merv.emailable.html |
true — write interactive emailable-report.html when the suite finishes
(doctor defaults to false). See
Share, Download & emailable.
|
Sample Configuration (Merv-Server)
merv.local=false
merv.server=https://merv.online/api/v1
merv.api_key=merv_your_api_key
merv.parent_hierarchy=your-hierarchy-uuid
merv.regression_suite=Custom Report Suite
Server setup: Merv-Server user guide.
MervReport (npm) reads the same file for local or server mode.
API overview
| Action | JavaScript / TypeScript (MervReport) |
Java (MervClient — server mode) |
|---|---|---|
| Open session / suite | await MervReport.open() |
MervClient.fromConfig() + createTestSuite(...) |
| Start testcase | await report.createTest(name, desc) |
client.createTestCase(...) |
| Info / prerequisite | await report.info(text) |
Step with prereq / information type |
| Test data | await report.testdata(name, data) |
createTestStep with testdata |
| Validation | await report.validation(name, expected, actual) |
createTestStep with expected / actual |
| Screenshot | validation(..., true) or MervExplicitLocalReport |
client.uploadFile(stepId, file, ...) |
| Finish | await report.finalize() |
updateTestCaseStatus(...) + close client |
MervReport in the npm merv-client package (JavaScript or TypeScript tabs below).
From pure Java without a test runner, use Merv-Server with MervClient, or run a small Node script with MervReport for local HTML.
Examples by language
After the JS client split, custom reports use only merv-client
(core). You do not install merv-client-playwright or
merv-client-cucumber for this path. Those packages are for Playwright Test and Cucumber-js adapters.
Each tab shows a full custom-report flow: open suite → create test → add steps → finalize.
Use MervClient from any JVM app (main, Spring job, Gradle task) when
merv.local=false. No Cucumber, TestNG, or JUnit required.
Maven dependency
<dependency>
<groupId>io.github.techelliiptica</groupId>
<artifactId>merv-client-api</artifactId>
<version>4.0.22</version>
</dependency>
Custom report script
import org.teche.merv.client.MervClient;
import org.teche.merv.client.dto.*;
import org.teche.merv.client.exception.MervClientException;
import org.teche.merv.client.utils.MervSuiteBootstrap;
import org.teche.merv.client.utils.TestCaseBuilder;
import org.teche.merv.client.utils.TestStepBuilder;
import java.io.File;
import java.util.Properties;
import java.util.UUID;
public class CustomMervReport {
public static void main(String[] args) throws Exception {
try (MervClient client = MervClient.fromConfig()) {
Properties props = new Properties();
props.load(new java.io.FileInputStream("merv.properties"));
UUID suiteId = MervSuiteBootstrap.resolveSuiteId(
client, props, "Custom Report Suite");
TestCaseResponse testCase = client.createTestCase(
TestCaseBuilder.create()
.testcaseName("Checkout API")
.description("POST /checkout with valid cart")
.testSuiteId(suiteId)
.status(TestCaseStatus.INPROGRESS)
.build());
UUID caseId = testCase.getId();
// Info / prerequisite step
client.createTestStep(TestStepBuilder.create()
.testcaseId(caseId)
.teststepName("Environment")
.stepType("information")
.prereq("Using staging tenant STG-42")
.status("PASSED")
.build());
// Test data step
TestStepResponse dataStep = client.createTestStep(
TestStepBuilder.create()
.testcaseId(caseId)
.teststepName("Request body")
.stepType("testdata")
.testdata("{\"cartId\":\"cart-991\",\"currency\":\"USD\"}")
.status("PASSED")
.build());
// Validation step
TestStepResponse validationStep = client.createTestStep(
TestStepBuilder.create()
.testcaseId(caseId)
.teststepName("HTTP status")
.stepType("assertion")
.expected("200")
.actual("200")
.status("PASSED")
.build());
// Screenshot attachment on a step
client.uploadFile(validationStep.getId(),
new File("screenshots/checkout-response.png"),
"Checkout response UI");
client.updateTestCaseStatus(caseId, TestCaseStatus.PASSED);
}
}
}
Run from the directory that contains merv.properties. Results appear in the Merv App.
Install (core only)
npm install merv-client
# Optional automated setup:
npx merv-client doctor setup
Use ESM ("type": "module" or a .mjs file). No Playwright or Cucumber adapter package is required.
Or skip doctor and keep the manual merv.properties + script below.
Custom report script (scripts/custom-report.mjs)
import { MervReport, MervReportFile } from 'merv-client';
const report = await MervReport.open();
await report.createTest(
'Checkout API',
'POST /checkout with valid cart'
);
await report.info('Using staging tenant STG-42');
await report.testdata(
'Request body',
JSON.stringify({ cartId: 'cart-991', currency: 'USD' })
);
// Optional: attach a file as test data (create fixtures/checkout-payload.json first)
await report.testdata(
'Payload file',
new MervReportFile('./fixtures/checkout-payload.json')
);
await report.validation('HTTP status', '200', '200');
// Optional: viewport PNG when a Playwright page is bound (see Screenshots)
await report.validation('Page title', 'Checkout', 'Checkout', true);
await report.finalize();
console.log('Report written under merv.report.folder');
Run: node scripts/custom-report.mjs from the project root (where merv.properties lives).
Install (core only)
npm install merv-client
npm install -D typescript tsx @types/node
# Optional automated setup:
npx merv-client doctor setup --typescript
Same API as JavaScript. Prefer npx tsx for scripts, or compile with tsc.
Still only merv-client — not the Playwright/Cucumber adapter packages.
Custom report script (scripts/custom-report.ts)
import { MervReport, MervReportFile } from 'merv-client';
async function runCustomReport(): Promise<void> {
const report = await MervReport.open();
await report.createTest(
'Checkout API',
'POST /checkout with valid cart',
);
await report.info('Using staging tenant STG-42');
await report.testdata(
'Request body',
JSON.stringify({ cartId: 'cart-991', currency: 'USD' }),
);
// Optional: create fixtures/checkout-payload.json first, or omit this call
await report.testdata(
'Payload file',
new MervReportFile('./fixtures/checkout-payload.json'),
);
await report.validation('HTTP status', '200', '200');
await report.validation('Page title', 'Checkout', 'Checkout', true);
await report.finalize();
}
runCustomReport().catch((err: unknown) => {
console.error(err);
process.exit(1);
});
Run: npx tsx scripts/custom-report.ts
Step types
| Method | JSON stepType |
Shown in HTML as |
|---|---|---|
info(...) |
PREREQUISITE / information |
Info / prerequisite row |
testdata(...) |
TEST_DATA |
Test data block (inline text or file preview) |
validation(...) |
ASSERTION |
Expected vs actual; fails testcase when values differ |
Call createTest once per logical testcase. Add as many steps as you need before starting the next test
or calling finalize().
Screenshots & file attachments
JavaScript / TypeScript — Playwright page bound
When a Playwright page is bound via
MervPlaywright.setAutomationToolObject(AutomationTool.PLAYWRIGHT, page)
(from merv-client),
validation(step, expected, actual, true) captures a viewport PNG into the run folder (local)
or uploads it (server). You may use the playwright package for the browser without installing
merv-client-playwright.
import { chromium } from 'playwright';
import { AutomationTool, MervPlaywright, MervReport } from 'merv-client';
const browser = await chromium.launch();
const page = await browser.newPage();
MervPlaywright.setAutomationToolObject(AutomationTool.PLAYWRIGHT, page);
const report = await MervReport.open();
await report.createTest('UI check', 'Home');
await page.goto('https://example.com');
await report.validation('Title', 'Example Domain', await page.title(), true);
await report.finalize();
MervPlaywright.clear();
await browser.close();
JavaScript / TypeScript — copy PNG from disk (local)
For scripts without Playwright, use the lower-level MervExplicitLocalReport API:
import { MervExplicitLocalReport } from 'merv-client';
const run = MervExplicitLocalReport.open();
const shot = run.copyScreenshotFromFile('/tmp/checkout.png', 'checkout-step');
run.addTestCase({
testcaseName: 'Checkout flow',
status: 'PASSED',
startTime: new Date().toISOString(),
endTime: new Date().toISOString(),
executionMachine: 'ci-runner-01',
testSteps: [{
teststepName: 'Confirm order',
stepType: 'ASSERTION',
status: 'PASSED',
expected: 'Order confirmed',
actual: 'Order confirmed',
screenshots: shot ? [shot] : [],
}],
});
run.finalize();
Java — server upload
After createTestStep, call client.uploadFile(stepId, file, description) to attach PNG or other files to that step in the Merv App.
View reports
- Merv-Local — run
merv show-report(openshttp://127.0.0.1:6174/) or serve{merv.report.folder}/index.html(see open dashboard) - Merv-Server — browse suites at merv.online/app
Troubleshooting
| Issue | What to check |
|---|---|
Call createTest before adding steps |
Invoke createTest(name, desc) before info / testdata / validation. |
No folder under merv.report.folder |
merv.local=true; run script from project root; call finalize(). |
Live dashboard empty until finalize() |
Use a merv-client build that auto-persists after each step (local JSON + index).
Still call finalize() at the end to mark the run completed and write the final HTML/zip.
For the cloud App, set merv.local=false — suite/cases/steps stream as you call
createTest / info / testdata / validation.
|
Java fromConfig() fails |
merv.local=false, valid merv.server, and merv.api_key (or username/password). |
Screenshot skipped in MervReport |
validation(..., true) needs a bound Playwright page, or use MervExplicitLocalReport.copyScreenshotFromFile. |
What’s next
- Share, Download & emailable — LAN share, offline zip,
merv.emailable.html - Merv-Local documentation — dashboard,
merv.properties, framework picker - Merv-Server guide — account, API key, hierarchy ID
- Playwright guide — install
merv-client+merv-client-playwright - Cucumber-js guide — install
merv-client+merv-client-cucumber - Merv-Logs —
MervLoggerand live log viewer - Merv-Tutor — step debugger for JS/TS
- API documentation — REST endpoints used by
MervClient
MERV