Attachments
Methods and techniques for attaching screenshots and plain text results to HTML reports.
Multiple Cucumber HTML Reporter allows you to attach media and data to help debug and review results effectively.
Attach method
To attach any content to the Cucumber JSON report, which will be displayed in the HTML report, you need to use the attach method. The attach method is available in all supported frameworks as shown below:
import { After } from '@wdio/cucumber-framework';
After(async function ({ result }) {
if (result?.status !== 'PASSED') {
const screenshot = await browser.takeScreenshot();
this.attach(Buffer.from(screenshot, 'base64'), 'image/png');
}
});Note
The attach method is available in the anonymous function callback parameter of the hook or step methods. It will not be available in the arrow function callbacks, as this will be undefined in arrow functions.
After(async function ({ pickle, result }) {
const screenshotPath = `./test-results/screenshots/${pickle.id}.png`;
if (result?.status !== Status.PASSED) {
const img = await page.screenshot({ path: screenshotPath, type: 'png', fullPage: true });
this.attach(img, 'image/png');
}
});Note
The attach method is available in the anonymous function callback parameter of the hook or step methods. It will not be available in the arrow function callbacks, as this will be undefined in arrow functions.
import { attach, Before } from '@badeball/cypress-cucumber-preprocessor';
Before({ tags: '@saucedemo' }, (scenario) => {
attach(`Starting scenario: ${scenario.pickle.name}`);
});Note
In Cypress, the attach method is not available by default. You need to install the @badeball/cypress-cucumber-preprocessor package to use it.
The attach method has a couple of variations in different frameworks. Below are the most common ways to use it:
this.attach(data): This is the most common way to use it. It takes one arguments: the string data to attach.this.attach(data, mimeType): This is also common way to use it. It takes two arguments: the string data to attach and the mime type of the data.
Following are the mime types supported by the attach method:
- Image types:
image/pngimage/jpegimage/gifimage/bmpimage/svg+xml
- Text types:
text/plaintext/htmltext/csstext/uri-list
- Structured data types:
application/jsonapplication/xml
- Video types:
video/mp4video/webm
Attaching Screenshots
Screenshots can be added at any time to your Cucumber JSON report. The best way is to use a scenario-hook that automatically captures a screenshot upon failure.
import { After } from '@wdio/cucumber-framework';
After(async function ({ result }) {
if (result?.status !== 'PASSED') {
const screenshot = await browser.takeScreenshot();
this.attach(Buffer.from(screenshot, 'base64'), 'image/png');
}
});After(async function ({ pickle, result }) {
const screenshotPath = `./test-results/screenshots/${pickle.id}.png`;
if (result?.status !== Status.PASSED) {
const img = await page.screenshot({ path: screenshotPath, type: 'png', fullPage: true });
this.attach(img, 'image/png');
}
});import { After } from '@badeball/cypress-cucumber-preprocessor';
After(async function ({ result }) {
cy.screenshot(screenshotName, { capture: 'viewport' });
});Tip
In Cypress, when you call cy.screenshot method, it automatically attaches the screenshot to the Cucumber JSON report. You do not need to use the attach method to attach screenshots in Cypress.
However, you can use the attach method to attach other types of data to the Cucumber JSON report, such as plain text or pretty JSON.
Attaching Plain Text
Attach logs or plain-text / data at any time to help you better understand the failure.
When('I enter username {string} and password {string}', async function (username: string, password: string) {
this.attach(`Perform login for user data: ${username}`);
});When('I click the logout button', async function () {
this.attach('Logging out of the application');
// ...
});import { After, attach } from '@badeball/cypress-cucumber-preprocessor';
After((scenario) => {
attach(`Scenario finished: ${scenario.pickle.name}.`);
});Tip
When attaching data, ensure non-readable binary data is properly encoded (e.g., via Base64).
Attaching Pretty JSON
You can also attach JSON-formatted data for API or configuration tests. This will be formatted for better readability.
When('I enter username {string} and password {string}', async function (username: string, password: string) {
// ...
this.attach(JSON.stringify({ username, password }), 'application/json');
// ...
});Check the specific framework you are using to attach these results directly to the Cucumber JSON file.
Custom Attachment Names
By default every attachment is labelled generically in the report, e.g. Log 1, Screenshot 1, JSON 1 or Attachment 1. You can override these with a meaningful, human-readable name to make large reports easier to scan.
To do this, attach your data with a custom name. In Cucumber.js you can pass an options object with a fileName to the attach method:
When('I call the login API', async function () {
// The name shows up as the attachment label in the report
this.attach(JSON.stringify(response), { mediaType: 'application/json', fileName: 'API Response Payload' });
this.attach(consoleLogs, { mediaType: 'text/plain', fileName: 'Browser Console' });
});The reporter picks up the custom name from the embedding's name or fileName field, either at the top level or nested under media. If no name is provided, it falls back to the default label (Log 1, Screenshot 1, and so on).
If your tooling writes the Cucumber JSON directly, just add a name (or fileName) next to the embedding's data:
{
"embeddings": [
{
"data": "eyJzdGF0dXMiOiJvayJ9",
"name": "API Response Payload",
"media": { "type": "application/json" }
},
{
"data": "Q29uc29sZSBvdXRwdXQ=",
"media": { "type": "text/plain", "fileName": "Browser Console" }
}
]
}Tip
Custom names work for every attachment type — screenshots, logs, JSON, video and other files. Attachments without a name keep the default numbered labels, so you can mix named and unnamed attachments freely.
Attach Video
You can attach video recordings to your test results using the attach method. Below are the most common ways to use it:
After(async function ({ pickle, result }) {
const video = page.video();
const videoPath = await video?.path();
if (videoPath && existsSync(videoPath)) {
this.attach(readFileSync(videoPath), 'video/webm');
}
});Last updated on