Skip to content

Commit

Permalink
feat(usebruno#1659): Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
trusta committed Apr 15, 2024
1 parent 72f1a98 commit b0f5db5
Show file tree
Hide file tree
Showing 3 changed files with 274 additions and 44 deletions.
48 changes: 4 additions & 44 deletions packages/bruno-cli/src/commands/run.js
@@ -1,14 +1,14 @@
const fs = require('fs');
const chalk = require('chalk');
const path = require('path');
const minimatch = require('minimatch');
const { forOwn } = require('lodash');
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 { cleanResults } = require('../utils/report');
const { bruToJson, getOptions, collectionBruToJson } = require('../utils/bru');
const { dotenvToJson } = require('@usebruno/lang');
const command = 'run [filename]';
Expand Down Expand Up @@ -93,46 +93,6 @@ const printRunSummary = (results) => {
};
};

const cleanResults = (results, opts) => {
if (opts.skipSensitiveData || opts.omitRequestBodies) {
results.filter((res) => !!res.request.data).forEach((res) => (res.request.data = '[REDACTED]'));
}
if (opts.skipSensitiveData || opts.omitResponseBodies) {
results.filter((res) => !!res.response.data).forEach((res) => (res.response.data = '[REDACTED]'));
}
if (opts.hideRequestBody) {
results
.filter((res) => !!res.request.data)
.filter((res) => opts.hideRequestBody.find((path) => minimatch(res.test.filename, path)))
.forEach((res) => (res.request.data = '[REDACTED]'));
}
if (opts.hideResponseBody) {
results
.filter((res) => !!res.response.data)
.filter((res) => opts.hideResponseBody.find((path) => minimatch(res.test.filename, path)))
.forEach((res) => (res.response.data = '[REDACTED]'));
}
if (opts.skipSensitiveData || opts.omitHeaders) {
results.forEach((res) => {
res.request.headers = null;
res.response.headers = null;
});
}
if (opts.skipHeaders) {
results.forEach((res) => {
opts.skipHeaders.forEach((header) => {
if (res.request.headers && res.request.headers[header]) {
res.request.headers[header] = '[REDACTED]';
}
if (res.response.headers && res.response.headers[header]) {
res.response.headers[header] = '[REDACTED]';
}
});
});
}
return results;
};

const getBruFilesRecursively = (dir, testsOnly) => {
const environmentsPath = 'environments';

Expand Down Expand Up @@ -273,13 +233,13 @@ const builder = async (yargs) => {
type: 'array',
default: [],
description:
'Exclude certain Request Bodies from the final report. Enter the minimatch pattern for the request file name you wish to hide'
'Exclude certain Request Bodies from the final report. Enter the minimatch pattern for the suitename you wish to hide'
})
.option('reporter-hideResponseBody', {
type: 'array',
default: [],
description:
'Exclude certain Response Bodies from the final report. Enter the minimatch pattern for the request file name you wish to hide'
'Exclude certain Response Bodies from the final report. Enter the minimatch pattern for the suitename you wish to hide'
})
.option('reporter-omitHeaders', {
type: 'boolean',
Expand Down Expand Up @@ -330,7 +290,7 @@ const builder = async (yargs) => {
'Run a request and write the results to results.html in html format in the current directory'
)
.example(
'$0 run folder --output results.html --format html --reporter-html-title "Any running test" --reporter-skipHeaders Authorization Cookies Set-Cookies --reporter-hideRequestBody **/Login.bru folder1/Secret.bru --reporter-hideResponseBody Login.bru',
'$0 run folder --output results.html --format html --reporter-html-title "Any running test" --reporter-skipHeaders Authorization Cookies Set-Cookies --reporter-hideRequestBody **/Login folder1/Secret --reporter-hideResponseBody Login',
'Run a request and write the results to results.html in html format in the current directory, but customize the output by deleting certain sensitive data.'
)
.example('$0 run request.bru --tests-only', 'Run all requests that have a test');
Expand Down
49 changes: 49 additions & 0 deletions packages/bruno-cli/src/utils/report.js
@@ -0,0 +1,49 @@
const minimatch = require('minimatch');

function cleanResults(results, opts) {
if (opts.skipSensitiveData || opts.omitRequestBodies) {
results.filter((res) => !!res.request?.data).forEach((res) => (res.request.data = '[REDACTED]'));
}
if (opts.skipSensitiveData || opts.omitResponseBodies) {
results.filter((res) => !!res.response?.data).forEach((res) => (res.response.data = '[REDACTED]'));
}
if (opts.hideRequestBody) {
results
.filter((res) => !!res.request?.data)
.filter((res) => opts.hideRequestBody.find((suitename) => minimatch(res.suitename, suitename)))
.forEach((res) => (res.request.data = '[REDACTED]'));
}
if (opts.hideResponseBody) {
results
.filter((res) => !!res.response?.data)
.filter((res) => opts.hideResponseBody.find((suitename) => minimatch(res.suitename, suitename)))
.forEach((res) => (res.response.data = '[REDACTED]'));
}
if (opts.skipSensitiveData || opts.omitHeaders) {
results.forEach((res) => {
if (res.request) {
res.request.headers = null;
}
if (res.response) {
res.response.headers = null;
}
});
}
if (opts.skipHeaders) {
results.forEach((res) => {
opts.skipHeaders.forEach((header) => {
if (res.request?.headers && res.request.headers[header]) {
res.request.headers[header] = '[REDACTED]';
}
if (res.response?.headers && res.response.headers[header]) {
res.response.headers[header] = '[REDACTED]';
}
});
});
}
return results;
}

module.exports = {
cleanResults
};
221 changes: 221 additions & 0 deletions packages/bruno-cli/tests/utils/report.spec.js
@@ -0,0 +1,221 @@
const { describe, it, expect, beforeEach } = require('@jest/globals');

const { cleanResults } = require('../../src/utils/report');

describe('cleanResults', () => {
let results = [];
beforeEach(() => {
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
},
{
suitename: 'Tests/Suite B',
request: {
method: 'POST',
url: 'https://imanother.test',
headers: {
authorization: 'Bearer some token'
},
data: 'Any data'
},
response: {
status: 200,
headers: {
'Set-Cookie': 'any cookie'
},
data: 'Any data'
},
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
}
];
});

it('should do noting', () => {
const cleaned = cleanResults(JSON.parse(JSON.stringify(results)), {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: [],
hideResponseBody: []
});

expect(cleaned).toStrictEqual(results);
});

it('should clean all request bodies', () => {
const cleaned = cleanResults(results, {
omitRequestBodies: true,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: [],
hideResponseBody: []
});

expect(cleaned[0].request.data).toBeUndefined();
expect(cleaned[1].request.data).toBe('[REDACTED]');
});

it('should clean all response bodies', () => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: true,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: [],
hideResponseBody: []
});

expect(cleaned[0].response).toBeUndefined();
expect(cleaned[1].response.data).toBe('[REDACTED]');
});

it('should clean all sensitive data', () => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: true,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: [],
hideResponseBody: []
});

expect(cleaned[0].request.headers).toBeNull();
expect(cleaned[0].request.data).toBeUndefined();
expect(cleaned[0].response).toBeUndefined();

expect(cleaned[1].request.headers).toBeNull();
expect(cleaned[1].request.data).toBe('[REDACTED]');
expect(cleaned[1].response.headers).toBeNull();
expect(cleaned[1].response.data).toBe('[REDACTED]');
});

it('should clean all headers', () => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: true,
skipHeaders: [],
hideRequestBody: [],
hideResponseBody: []
});

expect(cleaned[0].request.headers).toBeNull();
expect(cleaned[0].response).toBeUndefined();

expect(cleaned[1].request.headers).toBeNull();
expect(cleaned[1].response.headers).toBeNull();
});

it('should clean listed headers', () => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: ['authorization', 'Set-Cookie'],
hideRequestBody: [],
hideResponseBody: []
});

expect(cleaned[0].request.headers).toBeUndefined();
expect(cleaned[0].response).toBeUndefined();

expect(cleaned[1].request.headers.authorization).toBe('[REDACTED]');
expect(cleaned[1].response.headers['Set-Cookie']).toBe('[REDACTED]');
});

it('should clean all request bodies', () => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: ['**/*'],
hideResponseBody: []
});

expect(cleaned[0].request.data).toBeUndefined();
expect(cleaned[0].response).toBeUndefined();

expect(cleaned[1].request.data).toBe('[REDACTED]');
expect(cleaned[1].response.data).toBe('Any data');
});

it.each(['**/*', '**/Suite B', 'Tests/Suite B', '**/Suite*'])('should clean matching request bodies', (pattern) => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: [pattern],
hideResponseBody: []
});

expect(cleaned[0].request.data).toBeUndefined();
expect(cleaned[0].response).toBeUndefined();

expect(cleaned[1].request.data).toBe('[REDACTED]');
expect(cleaned[1].response.data).not.toBe('[REDACTED]');
});

it.each(['**/*', '**/Suite B', 'Tests/Suite B', '**/Suite*'])('should clean matching response bodies', (pattern) => {
const cleaned = cleanResults(results, {
omitRequestBodies: false,
omitResponseBodies: false,
skipSensitiveData: false,
omitHeaders: false,
skipHeaders: [],
hideRequestBody: [],
hideResponseBody: [pattern]
});

expect(cleaned[0].request.data).toBeUndefined();
expect(cleaned[0].response).toBeUndefined();

expect(cleaned[1].request.data).not.toBe('[REDACTED]');
expect(cleaned[1].response.data).toBe('[REDACTED]');
});
});

0 comments on commit b0f5db5

Please sign in to comment.