feat: Feature/cli support multiple reporters (#2911)

* Support multiple reporters at once in the CLI

* Typos

* Better logging string after writing file

* Remove double blank line

* More double blank lines

* Switch reporter schema to one from discussion

* Typo

* Add comment
This commit is contained in:
David Francis 2024-09-16 04:03:18 -07:00 committed by GitHub
parent 4419634db7
commit 5e4a96792e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -235,6 +235,18 @@ const builder = async (yargs) => {
default: 'json', default: 'json',
type: 'string' type: 'string'
}) })
.option('reporter-json', {
describe: 'Path to write json file results to',
type: 'string'
})
.option('reporter-junit', {
describe: 'Path to write junit file results to',
type: 'string'
})
.option('reporter-html', {
describe: 'Path to write html file results to',
type: 'string'
})
.option('insecure', { .option('insecure', {
type: 'boolean', type: 'boolean',
description: 'Allow insecure server connections' description: 'Allow insecure server connections'
@ -267,6 +279,10 @@ const builder = async (yargs) => {
'$0 run request.bru --output results.html --format html', '$0 run request.bru --output results.html --format html',
'Run a request and write the results to results.html in html format in the current directory' 'Run a request and write the results to results.html in html format in the current directory'
) )
.example(
'$0 run request.bru --reporter-junit results.xml --reporter-html results.html',
'Run a request and write the results to results.html in html format and results.xml in junit format in the current directory'
)
.example('$0 run request.bru --tests-only', 'Run all requests that have a test') .example('$0 run request.bru --tests-only', 'Run all requests that have a test')
.example( .example(
@ -291,6 +307,9 @@ const handler = async function (argv) {
r: recursive, r: recursive,
output: outputPath, output: outputPath,
format, format,
reporterJson,
reporterJunit,
reporterHtml,
sandbox, sandbox,
testsOnly, testsOnly,
bail bail
@ -392,6 +411,25 @@ const handler = async function (argv) {
process.exit(constants.EXIT_STATUS.ERROR_INCORRECT_OUTPUT_FORMAT); process.exit(constants.EXIT_STATUS.ERROR_INCORRECT_OUTPUT_FORMAT);
} }
let formats = {};
// Maintains back compat with --format and --output
if (outputPath && outputPath.length) {
formats[format] = outputPath;
}
if (reporterHtml && reporterHtml.length) {
formats['html'] = reporterHtml;
}
if (reporterJson && reporterJson.length) {
formats['json'] = reporterJson;
}
if (reporterJunit && reporterJunit.length) {
formats['junit'] = reporterJunit;
}
// load .env file at root of collection if it exists // load .env file at root of collection if it exists
const dotEnvPath = path.join(collectionPath, '.env'); const dotEnvPath = path.join(collectionPath, '.env');
const dotEnvExists = await exists(dotEnvPath); const dotEnvExists = await exists(dotEnvPath);
@ -524,28 +562,45 @@ const handler = async function (argv) {
const totalTime = results.reduce((acc, res) => acc + res.response.responseTime, 0); const totalTime = results.reduce((acc, res) => acc + res.response.responseTime, 0);
console.log(chalk.dim(chalk.grey(`Ran all requests - ${totalTime} ms`))); console.log(chalk.dim(chalk.grey(`Ran all requests - ${totalTime} ms`)));
if (outputPath && outputPath.length) { const formatKeys = Object.keys(formats);
const outputDir = path.dirname(outputPath); if (formatKeys && formatKeys.length > 0) {
const outputDirExists = await exists(outputDir);
if (!outputDirExists) {
console.error(chalk.red(`Output directory ${outputDir} does not exist`));
process.exit(constants.EXIT_STATUS.ERROR_MISSING_OUTPUT_DIR);
}
const outputJson = { const outputJson = {
summary, summary,
results results
}; };
if (format === 'json') { const reporters = {
fs.writeFileSync(outputPath, JSON.stringify(outputJson, null, 2)); 'json': (path) => fs.writeFileSync(path, JSON.stringify(outputJson, null, 2)),
} else if (format === 'junit') { 'junit': (path) => makeJUnitOutput(results, path),
makeJUnitOutput(results, outputPath); 'html': (path) => makeHtmlOutput(outputJson, path),
} else if (format === 'html') {
makeHtmlOutput(outputJson, outputPath);
} }
console.log(chalk.dim(chalk.grey(`Wrote results to ${outputPath}`))); for (const formatter of Object.keys(formats))
{
const reportPath = formats[formatter];
const reporter = reporters[formatter];
// Skip formatters lacking an output path.
if (!reportPath || reportPath.length === 0) {
continue;
}
const outputDir = path.dirname(reportPath);
const outputDirExists = await exists(outputDir);
if (!outputDirExists) {
console.error(chalk.red(`Output directory ${outputDir} does not exist`));
process.exit(constants.EXIT_STATUS.ERROR_MISSING_OUTPUT_DIR);
}
if (!reporter) {
console.error(chalk.red(`Reporter ${formatter} does not exist`));
process.exit(constants.EXIT_STATUS.ERROR_INCORRECT_OUTPUT_FORMAT);
}
reporter(reportPath);
console.log(chalk.dim(chalk.grey(`Wrote ${formatter} results to ${reportPath}`)));
}
} }
if (summary.failedAssertions + summary.failedTests + summary.failedRequests > 0) { if (summary.failedAssertions + summary.failedTests + summary.failedRequests > 0) {