feat(#334): bru cli support for collection headers, auth, scripts and tests

This commit is contained in:
Anoop M D 2023-10-09 08:26:10 +05:30
parent f9f1ca0640
commit 362289b7cd
8 changed files with 96 additions and 19 deletions

12
package-lock.json generated
View File

@ -16691,7 +16691,7 @@
"license": "MIT",
"dependencies": {
"@usebruno/js": "0.8.0",
"@usebruno/lang": "0.5.0",
"@usebruno/lang": "0.6.0",
"axios": "^1.5.1",
"chai": "^4.3.7",
"chalk": "^3.0.0",
@ -16771,10 +16771,10 @@
},
"packages/bruno-electron": {
"name": "bruno",
"version": "v0.21.1",
"version": "v0.22.0",
"dependencies": {
"@usebruno/js": "0.8.0",
"@usebruno/lang": "0.5.0",
"@usebruno/lang": "0.6.0",
"@usebruno/schema": "0.5.0",
"about-window": "^1.15.2",
"axios": "^1.5.1",
@ -17021,7 +17021,7 @@
},
"packages/bruno-lang": {
"name": "@usebruno/lang",
"version": "0.5.0",
"version": "0.6.0",
"license": "MIT",
"dependencies": {
"arcsecond": "^5.0.0",
@ -20011,7 +20011,7 @@
"version": "file:packages/bruno-cli",
"requires": {
"@usebruno/js": "0.8.0",
"@usebruno/lang": "0.5.0",
"@usebruno/lang": "0.6.0",
"axios": "^1.5.1",
"chai": "^4.3.7",
"chalk": "^3.0.0",
@ -21135,7 +21135,7 @@
"version": "file:packages/bruno-electron",
"requires": {
"@usebruno/js": "0.8.0",
"@usebruno/lang": "0.5.0",
"@usebruno/lang": "0.6.0",
"@usebruno/schema": "0.5.0",
"about-window": "^1.15.2",
"axios": "^1.5.1",

View File

@ -25,7 +25,7 @@
],
"dependencies": {
"@usebruno/js": "0.8.0",
"@usebruno/lang": "0.5.0",
"@usebruno/lang": "0.6.0",
"axios": "^1.5.1",
"chai": "^4.3.7",
"chalk": "^3.0.0",

View File

@ -6,7 +6,7 @@ const { exists, isFile, isDirectory } = require('../utils/filesystem');
const { runSingleRequest } = require('../runner/run-single-request');
const { bruToEnvJson, getEnvVars } = require('../utils/bru');
const { rpad } = require('../utils/common');
const { bruToJson, getOptions } = require('../utils/bru');
const { bruToJson, getOptions, collectionBruToJson } = require('../utils/bru');
const { dotenvToJson } = require('@usebruno/lang');
const command = 'run [filename]';
@ -121,6 +121,9 @@ const getBruFilesRecursively = (dir) => {
const currentDirBruJsons = [];
for (const file of filesInCurrentDir) {
if (['collection.bru', 'folder.bru'].includes(file)) {
continue;
}
const filePath = path.join(currentPath, file);
const stats = fs.lstatSync(filePath);
@ -151,6 +154,19 @@ const getBruFilesRecursively = (dir) => {
return getFilesInOrder(dir);
};
const getCollectionRoot = (dir) => {
const collectionRootPath = path.join(dir, 'collection.bru');
const exists = fs.existsSync(collectionRootPath);
if (!exists) {
return {};
}
const content = fs.readFileSync(collectionRootPath, 'utf8');
const json = collectionBruToJson(content);
return json;
};
const builder = async (yargs) => {
yargs
.option('r', {
@ -210,6 +226,7 @@ const handler = async function (argv) {
const brunoConfigFile = fs.readFileSync(brunoJsonPath, 'utf8');
const brunoConfig = JSON.parse(brunoConfigFile);
const collectionRoot = getCollectionRoot(collectionPath);
if (filename && filename.length) {
const pathExists = await exists(filename);
@ -349,7 +366,8 @@ const handler = async function (argv) {
collectionVariables,
envVars,
processEnvVars,
brunoConfig
brunoConfig,
collectionRoot
);
results.push(result);

View File

@ -1,9 +1,20 @@
const { get, each, filter } = require('lodash');
const decomment = require('decomment');
const prepareRequest = (request) => {
const prepareRequest = (request, collectionRoot) => {
const headers = {};
let contentTypeDefined = false;
// collection headers
each(get(collectionRoot, 'request.headers', []), (h) => {
if (h.enabled) {
headers[h.name] = h.value;
if (h.name.toLowerCase() === 'content-type') {
contentTypeDefined = true;
}
}
});
each(request.headers, (h) => {
if (h.enabled) {
headers[h.name] = h.value;
@ -20,6 +31,23 @@ const prepareRequest = (request) => {
};
// Authentication
// A request can override the collection auth with another auth
// But it cannot override the collection auth with no auth
// We will provide support for disabling the auth via scripting in the future
const collectionAuth = get(collectionRoot, 'request.auth');
if (collectionAuth) {
if (collectionAuth.mode === 'basic') {
axiosRequest.auth = {
username: get(collectionAuth, 'basic.username'),
password: get(collectionAuth, 'basic.password')
};
}
if (collectionAuth.mode === 'bearer') {
axiosRequest.headers['authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`;
}
}
if (request.auth) {
if (request.auth.mode === 'basic') {
axiosRequest.auth = {

View File

@ -1,8 +1,9 @@
const os = require('os');
const qs = require('qs');
const chalk = require('chalk');
const decomment = require('decomment');
const fs = require('fs');
const { forOwn, each, extend, get } = require('lodash');
const { forOwn, each, extend, get, compact } = require('lodash');
const FormData = require('form-data');
const prepareRequest = require('./prepare-request');
const interpolateVars = require('./interpolate-vars');
@ -23,7 +24,8 @@ const runSingleRequest = async function (
collectionVariables,
envVariables,
processEnvVars,
brunoConfig
brunoConfig,
collectionRoot
) {
try {
let request;
@ -58,7 +60,10 @@ const runSingleRequest = async function (
}
// run pre request script
const requestScriptFile = get(bruJson, 'request.script.req');
const requestScriptFile = compact([
get(collectionRoot, 'request.script.req'),
get(bruJson, 'request.script.req')
]).join(os.EOL);
if (requestScriptFile && requestScriptFile.length) {
const scriptRuntime = new ScriptRuntime();
await scriptRuntime.runRequestScript(
@ -208,7 +213,10 @@ const runSingleRequest = async function (
}
// run post response script
const responseScriptFile = get(bruJson, 'request.script.res');
const responseScriptFile = compact([
get(collectionRoot, 'request.script.res'),
get(bruJson, 'request.script.res')
]).join(os.EOL);
if (responseScriptFile && responseScriptFile.length) {
const scriptRuntime = new ScriptRuntime();
await scriptRuntime.runResponseScript(
@ -250,7 +258,7 @@ const runSingleRequest = async function (
// run tests
let testResults = [];
const testFile = get(bruJson, 'request.tests');
const testFile = compact([get(collectionRoot, 'request.tests'), get(bruJson, 'request.tests')]).join(os.EOL);
if (typeof testFile === 'string') {
const testRuntime = new TestRuntime();
const result = await testRuntime.runTests(
@ -296,6 +304,7 @@ const runSingleRequest = async function (
testResults
};
} catch (err) {
console.log(chalk.red(stripExtension(filename)) + chalk.dim(` (${err.message})`));
return {
request: {
method: null,

View File

@ -1,12 +1,33 @@
const _ = require('lodash');
const Mustache = require('mustache');
const { bruToEnvJsonV2, bruToJsonV2 } = require('@usebruno/lang');
const { bruToEnvJsonV2, bruToJsonV2, collectionBruToJson: _collectionBruToJson } = require('@usebruno/lang');
// override the default escape function to prevent escaping
Mustache.escape = function (value) {
return value;
};
const collectionBruToJson = (bru) => {
try {
const json = _collectionBruToJson(bru);
const transformedJson = {
request: {
params: _.get(json, 'query', []),
headers: _.get(json, 'headers', []),
auth: _.get(json, 'auth', {}),
script: _.get(json, 'script', {}),
vars: _.get(json, 'vars', {}),
tests: _.get(json, 'tests', '')
}
};
return transformedJson;
} catch (error) {
return Promise.reject(error);
}
};
/**
* The transformer function for converting a BRU file to JSON.
*
@ -91,5 +112,6 @@ module.exports = {
bruToJson,
bruToEnvJson,
getEnvVars,
getOptions
getOptions,
collectionBruToJson
};

View File

@ -15,7 +15,7 @@
},
"dependencies": {
"@usebruno/js": "0.8.0",
"@usebruno/lang": "0.5.0",
"@usebruno/lang": "0.6.0",
"@usebruno/schema": "0.5.0",
"about-window": "^1.15.2",
"axios": "^1.5.1",

View File

@ -1,6 +1,6 @@
{
"name": "@usebruno/lang",
"version": "0.5.0",
"version": "0.6.0",
"license": "MIT",
"main": "src/index.js",
"files": [