From 5ec2475f31c9b4e6d7dc0a5d6dfbd7ac0b158c7a Mon Sep 17 00:00:00 2001 From: trusta Date: Sun, 10 Mar 2024 21:43:25 +0100 Subject: [PATCH] feat(#1659): add html reporter for cli (#1660) --- packages/bruno-cli/examples/report.html | 1049 +++++++++++++++++ packages/bruno-cli/src/commands/run.js | 13 +- .../src/reporters/html-template.html | 637 ++++++++++ packages/bruno-cli/src/reporters/html.js | 13 + .../bruno-cli/tests/reporters/html.spec.js | 81 ++ 5 files changed, 1790 insertions(+), 3 deletions(-) create mode 100644 packages/bruno-cli/examples/report.html create mode 100644 packages/bruno-cli/src/reporters/html-template.html create mode 100644 packages/bruno-cli/src/reporters/html.js create mode 100644 packages/bruno-cli/tests/reporters/html.spec.js diff --git a/packages/bruno-cli/examples/report.html b/packages/bruno-cli/examples/report.html new file mode 100644 index 000000000..75bad93fa --- /dev/null +++ b/packages/bruno-cli/examples/report.html @@ -0,0 +1,1049 @@ + + + + + + + + + Bruno + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + diff --git a/packages/bruno-cli/src/commands/run.js b/packages/bruno-cli/src/commands/run.js index 6811bb3cd..1caf610c0 100644 --- a/packages/bruno-cli/src/commands/run.js +++ b/packages/bruno-cli/src/commands/run.js @@ -6,6 +6,7 @@ const { exists, isFile, isDirectory } = require('../utils/filesystem'); const { runSingleRequest } = require('../runner/run-single-request'); const { bruToEnvJson, getEnvVars } = require('../utils/bru'); const makeJUnitOutput = require('../reporters/junit'); +const makeHtmlOutput = require('../reporters/html'); const { rpad } = require('../utils/common'); const { bruToJson, getOptions, collectionBruToJson } = require('../utils/bru'); const { dotenvToJson } = require('@usebruno/lang'); @@ -203,7 +204,7 @@ const builder = async (yargs) => { }) .option('format', { alias: 'f', - describe: 'Format of the file results; available formats are "json" (default) or "junit"', + describe: 'Format of the file results; available formats are "json" (default), "junit" or "html"', default: 'json', type: 'string' }) @@ -235,6 +236,10 @@ const builder = async (yargs) => { '$0 run request.bru --output results.xml --format junit', 'Run a request and write the results to results.xml in junit format in the current directory' ) + .example( + '$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' + ) .example('$0 run request.bru --test-only', 'Run all requests that have a test'); }; @@ -331,8 +336,8 @@ const handler = async function (argv) { } } - if (['json', 'junit'].indexOf(format) === -1) { - console.error(chalk.red(`Format must be one of "json" or "junit"`)); + if (['json', 'junit', 'html'].indexOf(format) === -1) { + console.error(chalk.red(`Format must be one of "json", "junit or "html"`)); return; } @@ -483,6 +488,8 @@ const handler = async function (argv) { fs.writeFileSync(outputPath, JSON.stringify(outputJson, null, 2)); } else if (format === 'junit') { makeJUnitOutput(results, outputPath); + } else if (format === 'html') { + makeHtmlOutput(outputJson, outputPath); } console.log(chalk.dim(chalk.grey(`Wrote results to ${outputPath}`))); diff --git a/packages/bruno-cli/src/reporters/html-template.html b/packages/bruno-cli/src/reporters/html-template.html new file mode 100644 index 000000000..b4cbca0ac --- /dev/null +++ b/packages/bruno-cli/src/reporters/html-template.html @@ -0,0 +1,637 @@ + + + + + + + + + Bruno + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + diff --git a/packages/bruno-cli/src/reporters/html.js b/packages/bruno-cli/src/reporters/html.js new file mode 100644 index 000000000..7fb594224 --- /dev/null +++ b/packages/bruno-cli/src/reporters/html.js @@ -0,0 +1,13 @@ +const fs = require('fs'); +const path = require('path'); + +const makeHtmlOutput = async (results, outputPath) => { + const resultsJson = JSON.stringify(results, null, 2); + + const reportPath = path.join(__dirname, 'html-template.html'); + const template = fs.readFileSync(reportPath, 'utf8'); + + fs.writeFileSync(outputPath, template.replace('__RESULTS_JSON__', resultsJson)); +}; + +module.exports = makeHtmlOutput; diff --git a/packages/bruno-cli/tests/reporters/html.spec.js b/packages/bruno-cli/tests/reporters/html.spec.js new file mode 100644 index 000000000..b45e57f41 --- /dev/null +++ b/packages/bruno-cli/tests/reporters/html.spec.js @@ -0,0 +1,81 @@ +const { describe, it, expect } = require('@jest/globals'); +const fs = require('fs'); + +const makeHtmlOutput = require('../../src/reporters/html'); + +describe('makeHtmlOutput', () => { + beforeEach(() => { + jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should produce an html report', () => { + const outputJson = { + summary: { + totalRequests: 1, + passedRequests: 1, + failedRequests: 1, + totalAssertions: 1, + passedAssertions: 1, + failedAssertions: 1, + totalTests: 1, + passedTests: 1, + failedTests: 1 + }, + results: [ + { + description: 'description provided', + suitename: 'Tests/Suite A', + request: { + method: 'GET', + url: 'https://ima.test' + }, + assertionResults: [ + { + lhsExpr: 'res.status', + rhsExpr: 'eq 200', + status: 'pass' + }, + { + lhsExpr: 'res.status', + rhsExpr: 'neq 200', + status: 'fail', + error: 'expected 200 to not equal 200' + } + ], + runtime: 1.2345678 + }, + { + request: { + method: 'GET', + url: 'https://imanother.test' + }, + suitename: 'Tests/Suite B', + testResults: [ + { + lhsExpr: 'res.status', + rhsExpr: 'eq 200', + description: 'A test that passes', + status: 'pass' + }, + { + description: 'A test that fails', + status: 'fail', + error: 'expected 200 to not equal 200', + status: 'fail' + } + ], + runtime: 2.3456789 + } + ] + }; + + makeHtmlOutput(outputJson, '/tmp/testfile.html'); + + const htmlReport = fs.writeFileSync.mock.calls[0][1]; + expect(htmlReport).toContain(JSON.stringify(outputJson, null, 2)); + }); +});