mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-09 06:55:03 +00:00
feat: folder level scripts and tests
This commit is contained in:
@@ -43,39 +43,6 @@ const isCollectionRootBruFile = (pathname, collectionPath) => {
|
||||
return dirname === collectionPath && basename === 'collection.bru';
|
||||
};
|
||||
|
||||
const isFolderRootBruFile = (pathname, folderPath) => {
|
||||
const dirname = path.dirname(pathname);
|
||||
const basename = path.basename(pathname);
|
||||
return dirname === folderPath && basename === 'folder.bru';
|
||||
};
|
||||
|
||||
const scanDirectory = (directoryPath, callback) => {
|
||||
fs.readdir(directoryPath, (err, files) => {
|
||||
if (err) {
|
||||
console.error(`Error reading directory ${directoryPath}: ${err}`);
|
||||
return;
|
||||
}
|
||||
if (files.includes('folder.bru')) {
|
||||
callback(directoryPath);
|
||||
}
|
||||
// Iterate through each file/folder in the directory
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(directoryPath, file);
|
||||
// Check if it's a directory
|
||||
fs.stat(filePath, (err, stats) => {
|
||||
if (err) {
|
||||
console.error(`Error statting ${filePath}: ${err}`);
|
||||
return;
|
||||
}
|
||||
// If it's a directory, recursively scan it
|
||||
if (stats.isDirectory()) {
|
||||
scanDirectory(filePath, callback);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const hydrateRequestWithUuid = (request, pathname) => {
|
||||
request.uid = getRequestUid(pathname);
|
||||
|
||||
@@ -257,27 +224,38 @@ const add = async (win, pathname, collectionUid, collectionPath) => {
|
||||
collectionRoot: true
|
||||
}
|
||||
};
|
||||
const folderCallback = (filePath) => {
|
||||
const bruContent = fs.readFileSync(`${filePath}/folder.bru`, 'utf8');
|
||||
if (bruContent) {
|
||||
const folder = {
|
||||
meta: {
|
||||
collectionUid,
|
||||
pathname: filePath,
|
||||
name: path.basename(filePath),
|
||||
folderRoot: true
|
||||
}
|
||||
};
|
||||
folder.data = collectionBruToJson(bruContent);
|
||||
hydrateBruCollectionFileWithUuid(folder.data);
|
||||
win.webContents.send('main:collection-tree-updated', 'addFileDir', folder);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
scanDirectory(collectionPath, folderCallback);
|
||||
let bruContent = fs.readFileSync(pathname, 'utf8');
|
||||
|
||||
file.data = collectionBruToJson(bruContent);
|
||||
|
||||
hydrateBruCollectionFileWithUuid(file.data);
|
||||
win.webContents.send('main:collection-tree-updated', 'addFile', file);
|
||||
return;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this a folder.bru file?
|
||||
if (path.basename(pathname) === 'folder.bru') {
|
||||
console.log('folder.bru file detected');
|
||||
const file = {
|
||||
meta: {
|
||||
collectionUid,
|
||||
pathname,
|
||||
name: path.basename(pathname),
|
||||
folderRoot: true
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
let bruContent = fs.readFileSync(pathname, 'utf8');
|
||||
|
||||
file.data = collectionBruToJson(bruContent);
|
||||
|
||||
hydrateBruCollectionFileWithUuid(file.data);
|
||||
win.webContents.send('main:collection-tree-updated', 'addFile', file);
|
||||
return;
|
||||
@@ -402,6 +380,7 @@ const change = async (win, pathname, collectionUid, collectionPath) => {
|
||||
|
||||
const bru = fs.readFileSync(pathname, 'utf8');
|
||||
file.data = bruToJson(bru);
|
||||
|
||||
hydrateRequestWithUuid(file.data, pathname);
|
||||
win.webContents.send('main:collection-tree-updated', 'change', file);
|
||||
} catch (err) {
|
||||
|
||||
@@ -24,6 +24,16 @@ const collectionBruToJson = (bru) => {
|
||||
docs: _.get(json, 'docs', '')
|
||||
};
|
||||
|
||||
// add meta if it exists
|
||||
// this is only for folder bru file
|
||||
// in the future, all of this will be replaced by standard bru lang
|
||||
if (json.meta) {
|
||||
transformedJson.meta = {
|
||||
name: json.meta.name,
|
||||
seq: json.meta.seq
|
||||
};
|
||||
}
|
||||
|
||||
return transformedJson;
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
@@ -48,6 +58,16 @@ const jsonToCollectionBru = (json) => {
|
||||
docs: _.get(json, 'docs', '')
|
||||
};
|
||||
|
||||
// add meta if it exists
|
||||
// this is only for folder bru file
|
||||
// in the future, all of this will be replaced by standard bru lang
|
||||
if (json.meta) {
|
||||
collectionBruJson.meta = {
|
||||
name: json.meta.name,
|
||||
seq: json.meta.seq
|
||||
};
|
||||
}
|
||||
|
||||
return _jsonToCollectionBru(collectionBruJson);
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
|
||||
@@ -152,11 +152,16 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('renderer:save-folder-root', async (event, folderPathname, folderRoot) => {
|
||||
ipcMain.handle('renderer:save-folder-root', async (event, folder) => {
|
||||
try {
|
||||
const { name: folderName, root: folderRoot, pathname: folderPathname } = folder;
|
||||
const folderBruFilePath = path.join(folderPathname, 'folder.bru');
|
||||
|
||||
const content = jsonToBru(folderRoot);
|
||||
folderRoot.meta = {
|
||||
name: folderName
|
||||
};
|
||||
|
||||
const content = jsonToCollectionBru(folderRoot);
|
||||
await writeFile(folderBruFilePath, content);
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
|
||||
@@ -461,8 +461,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
|
||||
const collectionRoot = get(collection, 'root', {});
|
||||
const _request = item.draft ? item.draft.request : item.request;
|
||||
const request = prepareRequest(_request, collectionRoot, collectionPath);
|
||||
const request = prepareRequest(item, collection);
|
||||
const envVars = getEnvVars(environment);
|
||||
const processEnvVars = getProcessEnvVars(collectionUid);
|
||||
const brunoConfig = getBrunoConfig(collectionUid);
|
||||
@@ -900,8 +899,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
...eventData
|
||||
});
|
||||
|
||||
const _request = item.draft ? item.draft.request : item.request;
|
||||
const request = prepareRequest(_request, collectionRoot, collectionPath);
|
||||
const request = prepareRequest(item, collection);
|
||||
const requestUid = uuid();
|
||||
const processEnvVars = getProcessEnvVars(collectionUid);
|
||||
|
||||
|
||||
@@ -1,9 +1,79 @@
|
||||
const { get, each, filter, extend } = require('lodash');
|
||||
const os = require('os');
|
||||
const { get, each, filter, extend, compact } = require('lodash');
|
||||
const decomment = require('decomment');
|
||||
var JSONbig = require('json-bigint');
|
||||
const FormData = require('form-data');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { getTreePathFromCollectionToItem } = require('../../utils/collection');
|
||||
|
||||
const mergeFolderLevelHeaders = (request, requestTreePath) => {
|
||||
let folderHeaders = new Map();
|
||||
|
||||
for (let i of requestTreePath) {
|
||||
if (i.type === 'folder') {
|
||||
let headers = get(i, 'root.request.headers', []);
|
||||
headers.forEach((header) => {
|
||||
if (header.enabled) {
|
||||
folderHeaders.set(header.name, header.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mergedFolderHeaders = Array.from(folderHeaders, ([name, value]) => ({ name, value, enabled: true }));
|
||||
let requestHeaders = request.headers || [];
|
||||
let requestHeadersMap = new Map();
|
||||
|
||||
for (let header of requestHeaders) {
|
||||
if (header.enabled) {
|
||||
requestHeadersMap.set(header.name, header.value);
|
||||
}
|
||||
}
|
||||
|
||||
mergedFolderHeaders.forEach((header) => {
|
||||
requestHeadersMap.set(header.name, header.value);
|
||||
});
|
||||
|
||||
request.headers = Array.from(requestHeadersMap, ([name, value]) => ({ name, value, enabled: true }));
|
||||
};
|
||||
|
||||
const mergeFolderLevelScripts = (request, requestTreePath) => {
|
||||
let folderCombinedPreReqScript = [];
|
||||
let folderCombinedPostResScript = [];
|
||||
let folderCombinedTests = [];
|
||||
for (let i of requestTreePath) {
|
||||
if (i.type === 'folder') {
|
||||
let preReqScript = get(i, 'root.request.script.req', '');
|
||||
if (preReqScript && preReqScript.trim() !== '') {
|
||||
folderCombinedPreReqScript.push(preReqScript);
|
||||
}
|
||||
|
||||
let postResScript = get(i, 'root.request.script.res', '');
|
||||
if (postResScript && postResScript.trim() !== '') {
|
||||
folderCombinedPostResScript.push(postResScript);
|
||||
}
|
||||
|
||||
let tests = get(i, 'root.request.tests', []);
|
||||
if (tests && tests?.trim() !== '') {
|
||||
folderCombinedTests.push(tests);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (folderCombinedPreReqScript.length) {
|
||||
request.script.req = compact([...folderCombinedPreReqScript, request?.script?.req || '']).join(os.EOL);
|
||||
console.log('request.script.req', request.script.req);
|
||||
}
|
||||
|
||||
if (folderCombinedPostResScript.length) {
|
||||
request.script.res = compact([request?.script?.res || '', ...folderCombinedPostResScript.reverse()]).join(os.EOL);
|
||||
}
|
||||
|
||||
if (folderCombinedTests.length) {
|
||||
request.tests = compact([request?.tests || '', ...folderCombinedTests.reverse()]).join(os.EOL);
|
||||
}
|
||||
};
|
||||
|
||||
const parseFormData = (datas, collectionPath) => {
|
||||
// make axios work in node using form data
|
||||
@@ -133,7 +203,10 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
||||
return axiosRequest;
|
||||
};
|
||||
|
||||
const prepareRequest = (request, collectionRoot, collectionPath) => {
|
||||
const prepareRequest = (item, collection) => {
|
||||
const request = item.draft ? item.draft.request : item.request;
|
||||
const collectionRoot = get(collection, 'root', {});
|
||||
const collectionPath = collection.pathname;
|
||||
const headers = {};
|
||||
let contentTypeDefined = false;
|
||||
let url = request.url;
|
||||
@@ -148,6 +221,12 @@ const prepareRequest = (request, collectionRoot, collectionPath) => {
|
||||
}
|
||||
});
|
||||
|
||||
const requestTreePath = getTreePathFromCollectionToItem(collection, item);
|
||||
if (requestTreePath && requestTreePath.length > 0) {
|
||||
mergeFolderLevelHeaders(request, requestTreePath);
|
||||
mergeFolderLevelScripts(request, requestTreePath);
|
||||
}
|
||||
|
||||
each(request.headers, (h) => {
|
||||
if (h.enabled && h.name.length > 0) {
|
||||
headers[h.name] = h.value;
|
||||
|
||||
57
packages/bruno-electron/src/utils/collection.js
Normal file
57
packages/bruno-electron/src/utils/collection.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const each = require('lodash/each');
|
||||
const find = require('lodash/find');
|
||||
|
||||
const flattenItems = (items = []) => {
|
||||
const flattenedItems = [];
|
||||
|
||||
const flatten = (itms, flattened) => {
|
||||
each(itms, (i) => {
|
||||
flattened.push(i);
|
||||
|
||||
if (i.items && i.items.length) {
|
||||
flatten(i.items, flattened);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
flatten(items, flattenedItems);
|
||||
|
||||
return flattenedItems;
|
||||
};
|
||||
|
||||
const findItem = (items = [], itemUid) => {
|
||||
return find(items, (i) => i.uid === itemUid);
|
||||
};
|
||||
|
||||
const findItemInCollection = (collection, itemUid) => {
|
||||
let flattenedItems = flattenItems(collection.items);
|
||||
|
||||
return findItem(flattenedItems, itemUid);
|
||||
};
|
||||
|
||||
const findParentItemInCollection = (collection, itemUid) => {
|
||||
let flattenedItems = flattenItems(collection.items);
|
||||
|
||||
return find(flattenedItems, (item) => {
|
||||
return item.items && find(item.items, (i) => i.uid === itemUid);
|
||||
});
|
||||
};
|
||||
|
||||
const getTreePathFromCollectionToItem = (collection, _item) => {
|
||||
let path = [];
|
||||
let item = findItemInCollection(collection, _item.uid);
|
||||
while (item) {
|
||||
path.unshift(item);
|
||||
item = findParentItemInCollection(collection, item.uid);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
flattenItems,
|
||||
findItem,
|
||||
findItemInCollection,
|
||||
findParentItemInCollection,
|
||||
getTreePathFromCollectionToItem
|
||||
};
|
||||
Reference in New Issue
Block a user