From 5fd6773f431db281a981c4a7d27527db664448ce Mon Sep 17 00:00:00 2001 From: lohxt1 Date: Tue, 24 Sep 2024 21:49:49 +0530 Subject: [PATCH] feat: added support for collection/folder/request scripts --- packages/bruno-cli/src/commands/run.js | 58 +++++++------------ .../bruno-cli/src/runner/prepare-request.js | 41 +++++++------ .../src/runner/run-single-request.js | 24 +++----- packages/bruno-cli/src/utils/common.js | 13 +---- packages/bruno-tests/sandwich_exec/bruno.json | 12 ++++ .../bruno-tests/sandwich_exec/collection.bru | 13 +++++ .../sandwich_exec/folder/folder.bru | 16 +++++ .../sandwich_exec/folder/request.bru | 33 +++++++++++ .../bruno-tests/sequential_exec/bruno.json | 12 ++++ .../sequential_exec/collection.bru | 12 ++++ .../sequential_exec/folder/folder.bru | 16 +++++ .../sequential_exec/folder/request.bru | 34 +++++++++++ 12 files changed, 202 insertions(+), 82 deletions(-) create mode 100644 packages/bruno-tests/sandwich_exec/bruno.json create mode 100644 packages/bruno-tests/sandwich_exec/collection.bru create mode 100644 packages/bruno-tests/sandwich_exec/folder/folder.bru create mode 100644 packages/bruno-tests/sandwich_exec/folder/request.bru create mode 100644 packages/bruno-tests/sequential_exec/bruno.json create mode 100644 packages/bruno-tests/sequential_exec/collection.bru create mode 100644 packages/bruno-tests/sequential_exec/folder/folder.bru create mode 100644 packages/bruno-tests/sequential_exec/folder/request.bru diff --git a/packages/bruno-cli/src/commands/run.js b/packages/bruno-cli/src/commands/run.js index bd717ab3e..fde83b681 100644 --- a/packages/bruno-cli/src/commands/run.js +++ b/packages/bruno-cli/src/commands/run.js @@ -7,7 +7,7 @@ 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, uuid } = require('../utils/common'); +const { rpad } = require('../utils/common'); const { bruToJson, getOptions, collectionBruToJson } = require('../utils/bru'); const { dotenvToJson } = require('@usebruno/lang'); const constants = require('../constants'); @@ -93,22 +93,19 @@ const printRunSummary = (results) => { }; }; -const getCollection = (dir, testsOnly) => { - const environmentsPath = `${dir}/environments`; - const getFilesInOrder = (dir) => { +const createCollectionFromPath = (collectionPath) => { + const environmentsPath = `${collectionPath}/environments`; + const getFilesInOrder = (collectionPath) => { let collection = { - pathname: dir + pathname: collectionPath }; - const traverse = (currentPath) => { const filesInCurrentDir = fs.readdirSync(currentPath); if (currentPath.includes('node_modules')) { return; } - - const currentDirBruJsons = []; - + const currentDirItems = []; for (const file of filesInCurrentDir) { const filePath = path.join(currentPath, file); const stats = fs.lstatSync(filePath); @@ -118,7 +115,7 @@ const getCollection = (dir, testsOnly) => { !filePath.startsWith('.git') && !filePath.startsWith('node_modules') ) { - let folderItem = { uid: uuid(), name: file, pathname: filePath, type: 'folder', items: traverse(filePath) } + let folderItem = { name: file, pathname: filePath, type: 'folder', items: traverse(filePath) } const folderBruFilePath = path.join(filePath, 'folder.bru'); const folderBruFileExists = fs.existsSync(folderBruFilePath); if(folderBruFileExists) { @@ -126,7 +123,7 @@ const getCollection = (dir, testsOnly) => { let folderBruJson = collectionBruToJson(folderBruContent); folderItem.root = folderBruJson; } - currentDirBruJsons.push(folderItem); + currentDirItems.push(folderItem); } } @@ -140,35 +137,19 @@ const getCollection = (dir, testsOnly) => { if (!stats.isDirectory() && path.extname(filePath) === '.bru') { const bruContent = fs.readFileSync(filePath, 'utf8'); const bruJson = bruToJson(bruContent); - const requestHasTests = bruJson.request?.tests; - const requestHasActiveAsserts = bruJson.request?.assertions.some((x) => x.enabled) || false; - - if (testsOnly) { - if (requestHasTests || requestHasActiveAsserts) { - currentDirBruJsons.push({ - bruFilepath: filePath, - bruJson - }); - } - } else { - currentDirBruJsons.push({ - uid: uuid(), - name: file, - pathname: filePath, - ...bruJson - }); - } + currentDirItems.push({ + name: file, + pathname: filePath, + ...bruJson + }); } } - - return currentDirBruJsons + return currentDirItems }; - - collection.items = traverse(dir); + collection.items = traverse(collectionPath); return collection; }; - - return getFilesInOrder(dir); + return getFilesInOrder(collectionPath); }; const getBruFilesRecursively = (dir, testsOnly) => { @@ -409,7 +390,12 @@ const handler = async function (argv) { const brunoConfigFile = fs.readFileSync(brunoJsonPath, 'utf8'); const brunoConfig = JSON.parse(brunoConfigFile); const collectionRoot = getCollectionRoot(collectionPath); - const collection = getCollection(collectionPath); + let collection = createCollectionFromPath(collectionPath); + collection = { + brunoConfig, + root: collectionRoot, + ...collection + } if (filename && filename.length) { const pathExists = await exists(filename); diff --git a/packages/bruno-cli/src/runner/prepare-request.js b/packages/bruno-cli/src/runner/prepare-request.js index c9bad240c..db2f6a5b7 100644 --- a/packages/bruno-cli/src/runner/prepare-request.js +++ b/packages/bruno-cli/src/runner/prepare-request.js @@ -1,5 +1,6 @@ -const { get, each, filter, find } = require('lodash'); +const { get, each, filter, find, compact } = require('lodash'); const fs = require('fs'); +const os = require('os'); var JSONbig = require('json-bigint'); const decomment = require('decomment'); @@ -114,46 +115,50 @@ const mergeVars = (collection, request, requestTreePath) => { } }; -const mergeFolderLevelScripts = (request, requestTreePath, scriptFlow) => { - let folderCombinedPreReqScript = []; - let folderCombinedPostResScript = []; - let folderCombinedTests = []; +const mergeScripts = (collection, request, requestTreePath, scriptFlow) => { + let collectionPreReqScript = get(collection, 'root.request.script.req', ''); + let collectionPostResScript = get(collection, 'root.request.script.res', ''); + let collectionTests = get(collection, 'root.request.tests', ''); + + let combinedPreReqScript = []; + let combinedPostResScript = []; + let combinedTests = []; for (let i of requestTreePath) { if (i.type === 'folder') { let preReqScript = get(i, 'root.request.script.req', ''); if (preReqScript && preReqScript.trim() !== '') { - folderCombinedPreReqScript.push(preReqScript); + combinedPreReqScript.push(preReqScript); } let postResScript = get(i, 'root.request.script.res', ''); if (postResScript && postResScript.trim() !== '') { - folderCombinedPostResScript.push(postResScript); + combinedPostResScript.push(postResScript); } let tests = get(i, 'root.request.tests', ''); if (tests && tests?.trim?.() !== '') { - folderCombinedTests.push(tests); + combinedTests.push(tests); } } } - if (folderCombinedPreReqScript.length) { - request.script.req = compact([...folderCombinedPreReqScript, request?.script?.req || '']).join(os.EOL); + if (combinedPreReqScript.length) { + request.script.req = compact([collectionPreReqScript, ...combinedPreReqScript, request?.script?.req || '']).join(os.EOL); } - if (folderCombinedPostResScript.length) { + if (combinedPostResScript.length) { if (scriptFlow === 'sequential') { - request.script.res = compact([...folderCombinedPostResScript, request?.script?.res || '']).join(os.EOL); + request.script.res = compact([collectionPostResScript, ...combinedPostResScript, request?.script?.res || '']).join(os.EOL); } else { - request.script.res = compact([request?.script?.res || '', ...folderCombinedPostResScript.reverse()]).join(os.EOL); + request.script.res = compact([request?.script?.res || '', ...combinedPostResScript.reverse(), collectionPostResScript]).join(os.EOL); } } - if (folderCombinedTests.length) { + if (combinedTests.length) { if (scriptFlow === 'sequential') { - request.tests = compact([...folderCombinedTests, request?.tests || '']).join(os.EOL); + request.tests = compact([collectionTests, ...combinedTests, request?.tests || '']).join(os.EOL); } else { - request.tests = compact([request?.tests || '', ...folderCombinedTests.reverse()]).join(os.EOL); + request.tests = compact([request?.tests || '', ...combinedTests.reverse(), collectionTests]).join(os.EOL); } } }; @@ -245,7 +250,7 @@ const prepareRequest = (item = {}, collection = {}) => { const requestTreePath = getTreePathFromCollectionToItem(collection, item); if (requestTreePath && requestTreePath.length > 0) { mergeHeaders(collection, request, requestTreePath); - mergeFolderLevelScripts(request, requestTreePath, scriptFlow); + mergeScripts(collection, request, requestTreePath, scriptFlow); mergeVars(collection, request, requestTreePath); } @@ -376,7 +381,7 @@ const prepareRequest = (item = {}, collection = {}) => { axiosRequest.data = graphqlQuery; } - if (request.script && request.script.length) { + if (request.script) { axiosRequest.script = request.script; } diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index 95f028808..7efeadb9d 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -40,14 +40,12 @@ const runSingleRequest = async function ( try { let request; let nextRequestName; + let item = { + pathname: `${collectionPath}/${filename}`, + ...bruJson + } - collection = { - root: collectionRoot, - brunoConfig, - ...collection - }; - - request = prepareRequest({ pathname: `${collectionPath}/${filename}`, ...bruJson }, collection); + request = prepareRequest(item, collection); const scriptingConfig = get(brunoConfig, 'scripts', {}); scriptingConfig.runtime = runtime; @@ -68,10 +66,7 @@ const runSingleRequest = async function ( } // run pre request script - const requestScriptFile = compact([ - get(collectionRoot, 'request.script.req'), - get(bruJson, 'request.script.req') - ]).join(os.EOL); + const requestScriptFile = get(request, 'script.req'); if (requestScriptFile?.length) { const scriptRuntime = new ScriptRuntime({ runtime: scriptingConfig?.runtime }); const result = await scriptRuntime.runRequestScript( @@ -288,10 +283,7 @@ const runSingleRequest = async function ( } // run post response script - const responseScriptFile = compact([ - get(collectionRoot, 'request.script.res'), - get(bruJson, 'request.script.res') - ]).join(os.EOL); + const responseScriptFile = get(request, 'script.res'); if (responseScriptFile?.length) { const scriptRuntime = new ScriptRuntime({ runtime: scriptingConfig?.runtime }); const result = await scriptRuntime.runResponseScript( @@ -336,7 +328,7 @@ const runSingleRequest = async function ( // run tests let testResults = []; - const testFile = compact([get(collectionRoot, 'request.tests'), get(bruJson, 'request.tests')]).join(os.EOL); + const testFile = get(request, 'tests'); if (typeof testFile === 'string') { const testRuntime = new TestRuntime({ runtime: scriptingConfig?.runtime }); const result = await testRuntime.runTests( diff --git a/packages/bruno-cli/src/utils/common.js b/packages/bruno-cli/src/utils/common.js index cf300825d..704928022 100644 --- a/packages/bruno-cli/src/utils/common.js +++ b/packages/bruno-cli/src/utils/common.js @@ -1,5 +1,3 @@ -const { customAlphabet } = require('nanoid'); - const lpad = (str, width) => { let paddedStr = str; while (paddedStr.length < width) { @@ -16,16 +14,7 @@ const rpad = (str, width) => { return paddedStr; }; -const uuid = () => { - // https://github.com/ai/nanoid/blob/main/url-alphabet/index.js - const urlAlphabet = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict'; - const customNanoId = customAlphabet(urlAlphabet, 21); - - return customNanoId(); -}; - module.exports = { lpad, - rpad, - uuid + rpad }; diff --git a/packages/bruno-tests/sandwich_exec/bruno.json b/packages/bruno-tests/sandwich_exec/bruno.json new file mode 100644 index 000000000..07f81bd1e --- /dev/null +++ b/packages/bruno-tests/sandwich_exec/bruno.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "name": "sandwich_exec", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ], + "scripts": { + "flow": "sandwich" + } +} \ No newline at end of file diff --git a/packages/bruno-tests/sandwich_exec/collection.bru b/packages/bruno-tests/sandwich_exec/collection.bru new file mode 100644 index 000000000..5dd99c114 --- /dev/null +++ b/packages/bruno-tests/sandwich_exec/collection.bru @@ -0,0 +1,13 @@ +script:pre-request { + console.log("collection pre"); +} + +script:post-response { + { + console.log("collection post"); + const sequence = bru.getVar('sequence') || []; + sequence.push(1); + bru.setVar('sequence', sequence); + console.log("sequence", bru.getVar('sequence')); + } +} diff --git a/packages/bruno-tests/sandwich_exec/folder/folder.bru b/packages/bruno-tests/sandwich_exec/folder/folder.bru new file mode 100644 index 000000000..d2f5aedaa --- /dev/null +++ b/packages/bruno-tests/sandwich_exec/folder/folder.bru @@ -0,0 +1,16 @@ +meta { + name: folder +} + +script:pre-request { + console.log("folder pre"); +} + +script:post-response { + { + const sequence = bru.getVar('sequence') || []; + sequence.push(2); + bru.setVar('sequence', sequence); + } + console.log("folder post"); +} diff --git a/packages/bruno-tests/sandwich_exec/folder/request.bru b/packages/bruno-tests/sandwich_exec/folder/request.bru new file mode 100644 index 000000000..59c20fb99 --- /dev/null +++ b/packages/bruno-tests/sandwich_exec/folder/request.bru @@ -0,0 +1,33 @@ +meta { + name: request + type: http + seq: 1 +} + +get { + url: https://www.example.com + body: none + auth: none +} + +script:pre-request { + console.log("request pre"); +} + +script:post-response { + { + console.log("request post"); + + const sequence = bru.getVar('sequence') || []; + sequence.push(3); + bru.setVar('sequence', sequence); + } +} + +tests { + test("sandwich script execution is proper", function() { + const sequence = bru.getVar('sequence'); + bru.setVar('sequence', null); + expect(sequence.toString()).to.equal([3,2,1].toString()); + }); +} diff --git a/packages/bruno-tests/sequential_exec/bruno.json b/packages/bruno-tests/sequential_exec/bruno.json new file mode 100644 index 000000000..dd2870831 --- /dev/null +++ b/packages/bruno-tests/sequential_exec/bruno.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "name": "sequential_exec", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ], + "scripts": { + "flow": "sequential" + } +} \ No newline at end of file diff --git a/packages/bruno-tests/sequential_exec/collection.bru b/packages/bruno-tests/sequential_exec/collection.bru new file mode 100644 index 000000000..76c9c2289 --- /dev/null +++ b/packages/bruno-tests/sequential_exec/collection.bru @@ -0,0 +1,12 @@ +script:pre-request { + console.log("collection pre"); +} + +script:post-response { + { + console.log("collection post"); + const sequence = bru.getVar('sequence') || []; + sequence.push(1); + bru.setVar('sequence', sequence); + } +} diff --git a/packages/bruno-tests/sequential_exec/folder/folder.bru b/packages/bruno-tests/sequential_exec/folder/folder.bru new file mode 100644 index 000000000..50abd3032 --- /dev/null +++ b/packages/bruno-tests/sequential_exec/folder/folder.bru @@ -0,0 +1,16 @@ +meta { + name: folder +} + +script:pre-request { + console.log("folder pre"); +} + +script:post-response { + { + console.log("folder post"); + const sequence = bru.getVar('sequence') || []; + sequence.push(2); + bru.setVar('sequence', sequence); + } +} diff --git a/packages/bruno-tests/sequential_exec/folder/request.bru b/packages/bruno-tests/sequential_exec/folder/request.bru new file mode 100644 index 000000000..1d9a0c528 --- /dev/null +++ b/packages/bruno-tests/sequential_exec/folder/request.bru @@ -0,0 +1,34 @@ +meta { + name: request + type: http + seq: 1 +} + +get { + url: https://www.example.com + body: none + auth: none +} + +script:pre-request { + console.log("request pre"); +} + +script:post-response { + { + console.log("request post"); + const sequence = bru.getVar('sequence') || []; + sequence.push(3); + bru.setVar('sequence', sequence); + + console.log("sequence", bru.getVar('sequence')); + } +} + +tests { + test("sequential script execution is proper", function() { + const sequence = bru.getVar('sequence'); + bru.setVar('sequence', null); + expect(sequence.toString()).to.equal([1,2,3].toString()); + }); +}