WebdriverIO
npm install @tracera/webdriverio
Tested on Node.js 22.19–26.12 and WebdriverIO 9–10.0 (see Autotest adapters). @tracera/webdriverio on npm.
In wdio.conf.ts (Mocha):
export const config = {
reporters: ['spec', ['@tracera/webdriverio/reporter', {}]],
services: [['@tracera/webdriverio/service', {}]],
mochaOpts: {
require: ['@tracera/webdriverio/setup'],
},
};
For Cucumber, register the same reporter and service. Prefer tags on the Scenario @tracera.id:‹id› (optional @tracera.name:…), or call tracera.testCase from a Before hook or step.
Environment variables, run mode, and retries: Autotest adapters.
Retry Env key: WEBDRIVERIO_RETRY.
Bind testCaseId and autotestName
Load @tracera/webdriverio/setup via mochaOpts.require and import tracera and annotations. Mocha annotation names are literal (no {param}).
Mocha — at declaration (preferred):
import { annotations } from '@tracera/webdriverio';
it(
'login',
annotations(42, 'e2e/login', async () => {
await browser.url('https://example.com');
}),
);
Mocha — inside the test (optional if annotations already bind the case):
import { tracera } from '@tracera/webdriverio';
it('login', async () => {
tracera.testCase(42, 'e2e/login');
await browser.url('https://example.com');
});
Cucumber — Scenario tags (preferred):
@tracera.id:42
@tracera.name:e2e%2Flogin
Scenario: login
Given I open the login page
To bind without Scenario tags, call tracera.testCase from a Before hook or step.
Skip
Use stock Mocha skip (this.skip()). Optional: set a result comment with tracera.comment before calling skip.
import { annotations, tracera } from '@tracera/webdriverio';
it(
'login',
annotations(42, 'e2e/login', async function () {
if (!process.env.READY) {
tracera.comment('env not ready');
this.skip();
}
await browser.url('https://example.com/login');
}),
);
Steps
Use tracera.step: the call tracera.step(title, fn), @tracera.step("…") on a class method, or tracera.step("…")(fn). In a decorator title, {name} / {0} are filled from the method arguments; you can also pass a function that returns the title. In the call form, {name} / {0} are not filled in — pass a finished title string (or build it yourself). Async methods and Promises are awaited. With @tracera/webdriverio/setup, stock Mocha beforeEach / afterEach are instrumented — steps inside them go to the result’s Setup / Teardown. Suite-level hooks such as before / after are not reported.
import { tracera } from '@tracera/webdriverio';
beforeEach(async () => {
await tracera.step('open shop', async () => {
await browser.url('/shop');
});
});
it('checkout', async () => {
tracera.testCase(10, 'e2e/checkout');
await tracera.step('add to cart', async () => {
await $('[data-testid=add]').click();
});
});
afterEach(async () => {
await tracera.step('cleanup', async () => {
await browser.url('/cart/clear');
});
});
Decorator on a method:
import { tracera } from '@tracera/webdriverio';
class Cart {
@tracera.step('add {item}')
async addToCart(item: string) {
// …
}
}
Comments, errors, and attachments
Comments, errors, and attachments: Autotest adapters.
import { tracera } from '@tracera/webdriverio';
it('login', async () => {
tracera.testCase(42, 'e2e/login');
tracera.comment('result-level note');
tracera.error('result-level error text');
await tracera.step('open login', async () => {
await browser.url('/login');
tracera.comment('landed on login');
tracera.attachment({
fileName: 'suite-log.txt',
mimeType: 'text/plain',
data: new TextEncoder().encode('finished login flow'),
});
});
});
Parameterized tests
import { annotations } from '@tracera/webdriverio';
const rows = [
{ id: 42, name: 'e2e/login-ok', path: '/login' },
{ id: 43, name: 'e2e/login-sso', path: '/login/sso' },
];
for (const row of rows) {
it(
row.name,
annotations(row.id, row.name, async () => {
await browser.url(`https://example.com${row.path}`);
}),
);
}
Or call tracera.testCase(row.id, row.name) inside the test instead of annotations.