import { getTestName } from '@vitest/runner/utils';
import { server } from 'vitest/browser';
import * as allure from 'allure-js-commons';
// In vite.config.ts
// commands: {
// hostFileExists(_, path) {
// return fs.existsSync(path);
// },
// }
const sanitize = (str: string): string => str.replaceAll(/[^a-z0-9]/gi, '-');
beforeEach(ctx => {
ctx.onTestFailed(async ({ task }) => {
const prefix = `Attempt ${(task.result?.retryCount ?? 0) + 1} - `;
await Promise.all([
// Link the trace to allure (mostly based on internal sources of vitest cause functions not exposed and traces does not come in artifacts/attachments)
(async (): Promise<void> => {
const { retryCount = 0, repeatCount = 0 } = task.result ?? {};
const testPath = task.file.filepath;
const path = testPath.split('/');
const fileName = path.pop();
const tracePath = [
...path,
'__traces__',
fileName,
`${sanitize(task.file.projectName ?? '')}-${sanitize(getTestName(task, '-'))}-${repeatCount}-${retryCount}.trace.zip`,
].join('/');
// Validate trace exists before
if (server.commands.hostFileExists(tracePath)) {
console.info('Attaching', `${prefix}Trace.zip`, tracePath);
await allure.attachmentPath(`${prefix}Trace.zip`, tracePath, 'application/zip');
} else {
console.log('No file for trace', tracePath);
}
})(),
// All other vitest artifacts that we can support linking to allure
...task.artifacts.map(async artifact => {
console.info('Artifact', artifact.type, artifact.attachments?.map(a => a.path));
const artifactPrefix = `${prefix}${artifact.type.split(':').pop()} -`;
if (artifact.type === 'internal:failureScreenshot') {
for (const attachment of artifact.attachments) {
const filename = artifactPrefix + (attachment.path.split('/').pop() ?? '');
console.info('Attaching', filename, attachment.path);
await allure.attachmentPath(filename, attachment.path, attachment.contentType as string);
}
}
if (artifact.type === 'internal:toMatchScreenshot') {
for (const attachment of artifact.attachments) {
if (attachment.path) {
const filename = artifactPrefix + (attachment.path.split('/').pop() ?? '');
console.info('Attaching', filename, attachment.path);
await allure.attachmentPath(filename, attachment.path, attachment.contentType as string);
} else if (attachment.body) {
const filename = `${prefix}${artifact.message} ${attachment.name}`;
console.info('Attaching', filename, attachment.path);
await allure.attachment(filename, attachment.body, attachment.contentType as string);
}
}
}
}),
]);
// Clear artifacts after added to allure to avoid adding them twice after a retry
task.artifacts.length = 0;
});
});
Currently there is no retry support in browser mode it seem. We see the failure of the test but not the retry, only the last result somehow.
Note: On this subject I havent found yet how to bind the retryCount from test ctx to allure.
Additionally, it would be nice to have automatic attachment on tests failure.
EDIT: (1st version, check later one): Here is my current implementation as a starting point for built-in support: