Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli - add support for the bru runner util fns and the bru runRequest fn #3785

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions packages/bruno-cli/src/commands/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ const { rpad } = require('../utils/common');
const { bruToJson, getOptions, collectionBruToJson } = require('../utils/bru');
const { dotenvToJson } = require('@usebruno/lang');
const constants = require('../constants');
const { findItemInCollection } = require('../utils/collection');
const command = 'run [filename]';
const desc = 'Run a request';

const printRunSummary = (results) => {
let totalRequests = 0;
let passedRequests = 0;
let failedRequests = 0;
let skippedRequests = 0;
let totalAssertions = 0;
let passedAssertions = 0;
let failedAssertions = 0;
Expand Down Expand Up @@ -49,7 +51,10 @@ const printRunSummary = (results) => {
failedAssertions += 1;
}
}
if (!hasAnyTestsOrAssertions && result.error) {
if (!hasAnyTestsOrAssertions && result.skipped) {
skippedRequests += 1;
}
else if (!hasAnyTestsOrAssertions && result.error) {
failedRequests += 1;
} else {
passedRequests += 1;
Expand All @@ -62,6 +67,9 @@ const printRunSummary = (results) => {
if (failedRequests > 0) {
requestSummary += `, ${chalk.red(`${failedRequests} failed`)}`;
}
if (skippedRequests > 0) {
requestSummary += `, ${chalk.magenta(`${skippedRequests} skipped`)}`;
}
requestSummary += `, ${totalRequests} total`;

let assertSummary = `${rpad('Tests:', maxLength)} ${chalk.green(`${passedTests} passed`)}`;
Expand All @@ -84,6 +92,7 @@ const printRunSummary = (results) => {
totalRequests,
passedRequests,
failedRequests,
skippedRequests,
totalAssertions,
passedAssertions,
failedAssertions,
Expand Down Expand Up @@ -144,7 +153,7 @@ const createCollectionFromPath = (collectionPath) => {
});
}
}
return currentDirItems
return currentDirItems;
};
collection.items = traverse(collectionPath);
return collection;
Expand Down Expand Up @@ -634,6 +643,34 @@ const handler = async function (argv) {
}

const runtime = getJsSandboxRuntime(sandbox);

const runSingleRequestByPathname = async (relativeItemPathname) => {
return new Promise(async (resolve, reject) => {
let itemPathname = path.join(collectionPath, relativeItemPathname);
if (itemPathname && !itemPathname?.endsWith('.bru')) {
itemPathname = `${itemPathname}.bru`;
}
const bruJson = cloneDeep(findItemInCollection(collection, itemPathname));
if (bruJson) {
const res = await runSingleRequest(
itemPathname,
bruJson,
collectionPath,
runtimeVariables,
envVars,
processEnvVars,
brunoConfig,
collectionRoot,
runtime,
collection,
runSingleRequestByPathname
);
resolve(res?.response);
}
reject(`bru.runRequest: invalid request path - ${itemPathname}`);
});
}

let currentRequestIndex = 0;
let nJumps = 0; // count the number of jumps to avoid infinite loops
while (currentRequestIndex < bruJsons.length) {
Expand All @@ -651,7 +688,8 @@ const handler = async function (argv) {
brunoConfig,
collectionRoot,
runtime,
collection
collection,
runSingleRequestByPathname
);

results.push({
Expand Down Expand Up @@ -701,6 +739,11 @@ const handler = async function (argv) {

// determine next request
const nextRequestName = result?.nextRequestName;

if (result?.shouldStopRunnerExecution) {
break;
}

if (nextRequestName !== undefined) {
nJumps++;
if (nJumps > 10000) {
Expand Down
56 changes: 50 additions & 6 deletions packages/bruno-cli/src/runner/run-single-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ const runSingleRequest = async function (
brunoConfig,
collectionRoot,
runtime,
collection
collection,
runSingleRequestByPathname
) {
try {
let request;
let nextRequestName;
let shouldStopRunnerExecution = false;
let item = {
pathname: path.join(collectionPath, filename),
...bruJson
Expand All @@ -66,11 +68,41 @@ const runSingleRequest = async function (
collectionPath,
onConsoleLog,
processEnvVars,
scriptingConfig
scriptingConfig,
runSingleRequestByPathname
);
if (result?.nextRequestName !== undefined) {
nextRequestName = result.nextRequestName;
}

if (result?.stopExecution) {
shouldStopRunnerExecution = true;
}

if (result?.skipRequest) {
return {
test: {
filename: filename
},
request: {
method: request.method,
url: request.url,
headers: request.headers,
data: request.data
},
response: {
status: 'skipped',
statusText: 'request skipped via pre-request script',
data: null,
responseTime: 0
},
error: 'Request has been skipped from pre-request script',
skipped: true,
assertionResults: [],
testResults: [],
shouldStopRunnerExecution
};
}
}

// interpolate variables inside request
Expand Down Expand Up @@ -316,7 +348,8 @@ const runSingleRequest = async function (
error: err?.message || err?.errors?.map(e => e?.message)?.at(0) || err?.code || 'Request Failed!',
assertionResults: [],
testResults: [],
nextRequestName: nextRequestName
nextRequestName: nextRequestName,
shouldStopRunnerExecution
};
}
}
Expand Down Expand Up @@ -356,11 +389,16 @@ const runSingleRequest = async function (
collectionPath,
null,
processEnvVars,
scriptingConfig
scriptingConfig,
runSingleRequestByPathname
);
if (result?.nextRequestName !== undefined) {
nextRequestName = result.nextRequestName;
}

if (result?.stopExecution) {
shouldStopRunnerExecution = true;
}
}

// run assertions
Expand Down Expand Up @@ -401,13 +439,18 @@ const runSingleRequest = async function (
collectionPath,
null,
processEnvVars,
scriptingConfig
scriptingConfig,
runSingleRequestByPathname
);
testResults = get(result, 'results', []);

if (result?.nextRequestName !== undefined) {
nextRequestName = result.nextRequestName;
}

if (result?.stopExecution) {
shouldStopRunnerExecution = true;
}
}

if (testResults?.length) {
Expand Down Expand Up @@ -440,7 +483,8 @@ const runSingleRequest = async function (
error: null,
assertionResults,
testResults,
nextRequestName: nextRequestName
nextRequestName: nextRequestName,
shouldStopRunnerExecution
};
} catch (err) {
console.log(chalk.red(stripExtension(filename)) + chalk.dim(` (${err.message})`));
Expand Down
1 change: 1 addition & 0 deletions packages/bruno-cli/src/utils/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,6 @@ module.exports = {
mergeHeaders,
mergeVars,
mergeScripts,
findItemInCollection,
getTreePathFromCollectionToItem
}
4 changes: 2 additions & 2 deletions packages/bruno-electron/src/ipc/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ const registerNetworkIpc = (mainWindow) => {
if (itemPathname && !itemPathname?.endsWith('.bru')) {
itemPathname = `${itemPathname}.bru`;
}
const _item = findItemInCollectionByPathname(collection, itemPathname);
const _item = cloneDeep(findItemInCollectionByPathname(collection, itemPathname));
if(_item) {
const res = await runRequest({ item: _item, collection, environment, runtimeVariables, runInBackground: true });
resolve(res);
Expand Down Expand Up @@ -952,7 +952,7 @@ const registerNetworkIpc = (mainWindow) => {
if (itemPathname && !itemPathname?.endsWith('.bru')) {
itemPathname = `${itemPathname}.bru`;
}
const _item = findItemInCollectionByPathname(collection, itemPathname);
const _item = cloneDeep(findItemInCollectionByPathname(collection, itemPathname));
if(_item) {
const res = await runRequest({ item: _item, collection, environment, runtimeVariables, runInBackground: true });
resolve(res);
Expand Down
15 changes: 15 additions & 0 deletions packages/bruno-tests/collection/ping-another-one.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
meta {
name: ping-another-one
type: http
seq: 2
}

get {
url: {{host}}/ping
body: none
auth: none
}

script:pre-request {
throw new Error('this should not execute in a collection run');
}
4 changes: 4 additions & 0 deletions packages/bruno-tests/collection/ping.bru
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ get {
body: none
auth: none
}

script:pre-request {
bru.runner.stopExecution();
}
96 changes: 96 additions & 0 deletions packages/bruno-tests/collection/scripting/api/bru/runRequest.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
meta {
name: runRequest
type: http
seq: 2
}

post {
url: {{host}}/api/echo/json
body: json
auth: none
}

headers {
foo: bar
}

auth:basic {
username: asd
password: j
}

auth:bearer {
token:
}

body:json {
{
"hello": "bruno"
}
}

assert {
res.status: eq 200
}

script:pre-request {
bru.setVar("runRequest-ping-res-1", null);
bru.setVar("runRequest-ping-res-2", null);
bru.setVar("runRequest-ping-res-3", null);

let pingRes = await bru.runRequest('ping');
bru.setVar('runRequest-ping-res-1', {
data: pingRes?.data,
statusText: pingRes?.statusText,
status: pingRes?.status
});
}

script:post-response {
let pingRes = await bru.runRequest('ping');
bru.setVar('runRequest-ping-res-2', {
data: pingRes?.data,
statusText: pingRes?.statusText,
status: pingRes?.status
});
}

tests {
const pingRes = await bru.runRequest('ping');
bru.setVar('runRequest-ping-res-3', {
data: pingRes?.data,
statusText: pingRes?.statusText,
status: pingRes?.status
});

test("should run request and return valid response in pre-request script", function() {
const expectedPingRes = {
data: "pong",
statusText: "OK",
status: 200
};
const pingRes = bru.getVar('runRequest-ping-res-1');
expect(pingRes).to.eql(expectedPingRes);
});

test("should run request and return valid response in post-response script", function() {
const expectedPingRes = {
data: "pong",
statusText: "OK",
status: 200
};
const pingRes = bru.getVar('runRequest-ping-res-2');
expect(pingRes).to.eql(expectedPingRes);
});

test("should run request and return valid response in tests script", function() {
const expectedPingRes = {
data: "pong",
statusText: "OK",
status: 200
};
const pingRes = bru.getVar('runRequest-ping-res-3');
expect(pingRes).to.eql(expectedPingRes);
});

}
19 changes: 19 additions & 0 deletions packages/bruno-tests/collection/scripting/api/bru/runner/1.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: 1
type: http
seq: 1
}

post {
url: https://echo.usebruno.com
body: none
auth: none
}

script:pre-request {
bru.setVar('bru-runner-req', 1);
}

script:post-response {
bru.setVar('bru.runner.skipRequest', true);
}
Loading
Loading