Files
bruno/packages/bruno-js/src/runtime/test-runtime.js
lohit bafb235e72 feat: add certs and proxy config to bru.sendRequest API (#6988)
* feat: add certs and proxy config to bru.sendRequest API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: handle URL string argument in bru.sendRequest

When bru.sendRequest is called with a plain URL string instead of a
config object, the function now normalizes it to { url: string } before
processing. This fixes the case where spreading a string created an
invalid config object.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add variable interpolation to bru.sendRequest certs and proxy config

Interpolate environment variables in clientCertificates and proxy
configuration for bru.sendRequest API, enabling use of variables like
{{CERT_PATH}} or {{PROXY_HOST}} in certificate paths and proxy settings.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: use interpolateObject for certs and proxy config interpolation

- Add interpolateObject to electron's interpolate-string.js using
  buildCombinedVars pattern (matches CLI implementation)
- Simplify cert-utils.js by using interpolateObject instead of
  manual field-by-field interpolation
- Add interpolation for clientCertificates and proxy config in CLI's
  run-single-request.js for bru.sendRequest

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: add all variable types to sendRequest interpolation options

- Add globalEnvVars, collectionVariables, folderVariables, requestVariables
  to sendRequestInterpolationOptions for complete variable support
- Use cached system proxy instead of redundant getSystemProxy() call
- Remove duplicate getOptions() call

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: skip CA cert loading when TLS verification is disabled

Only load CA certificates when shouldVerifyTls is true, since they
are not used for validation when TLS verification is disabled.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 17:59:46 +05:30

126 lines
3.6 KiB
JavaScript

const chai = require('chai');
const Bru = require('../bru');
const BrunoRequest = require('../bruno-request');
const BrunoResponse = require('../bruno-response');
const { cleanJson } = require('../utils');
const { createBruTestResultMethods } = require('../utils/results');
const { runScriptInNodeVm } = require('../sandbox/node-vm');
const jsonwebtoken = require('jsonwebtoken');
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
class TestRuntime {
constructor(props) {
this.runtime = props?.runtime || 'quickjs';
}
async runTests(
testsFile,
request,
response,
envVariables,
runtimeVariables,
collectionPath,
onConsoleLog,
processEnvVars,
scriptingConfig,
runRequestByItemPathname,
collectionName
) {
const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
const collectionVariables = request?.collectionVariables || {};
const folderVariables = request?.folderVariables || {};
const requestVariables = request?.requestVariables || {};
const promptVariables = request?.promptVariables || {};
const assertionResults = request?.assertionResults || [];
const certsAndProxyConfig = request?.certsAndProxyConfig;
const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, {}, collectionName, promptVariables, certsAndProxyConfig);
const req = new BrunoRequest(request);
const res = new BrunoResponse(response);
// extend bru with result getter methods
const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
if (!testsFile || !testsFile.length) {
return {
request,
envVariables,
runtimeVariables,
globalEnvironmentVariables,
results: __brunoTestResults.getResults(),
nextRequestName: bru.nextRequest
};
}
const context = {
test,
bru,
req,
res,
expect: chai.expect,
assert: chai.assert,
__brunoTestResults: __brunoTestResults,
jwt: jsonwebtoken
};
if (onConsoleLog && typeof onConsoleLog === 'function') {
const customLogger = (type) => {
return (...args) => {
onConsoleLog(type, cleanJson(args));
};
};
context.console = {
log: customLogger('log'),
info: customLogger('info'),
warn: customLogger('warn'),
debug: customLogger('debug'),
error: customLogger('error')
};
}
if (runRequestByItemPathname) {
context.bru.runRequest = runRequestByItemPathname;
}
let scriptError = null;
try {
if (this.runtime === 'nodevm') {
await runScriptInNodeVm({
script: testsFile,
context,
collectionPath,
scriptingConfig
});
} else {
// default runtime is `quickjs`
await executeQuickJsVmAsync({
script: testsFile,
context: context,
collectionPath
});
}
} catch (error) {
scriptError = error;
}
const result = {
request,
envVariables: cleanJson(envVariables),
runtimeVariables: cleanJson(runtimeVariables),
globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
persistentEnvVariables: cleanJson(bru.persistentEnvVariables),
results: cleanJson(__brunoTestResults.getResults()),
nextRequestName: bru.nextRequest
};
if (scriptError) {
scriptError.partialResults = result;
throw scriptError;
}
return result;
}
}
module.exports = TestRuntime;