Merge remote-tracking branch 'origin/main' into feat/folder-recursive-rename-win32

This commit is contained in:
Pragadesh-45 2024-12-05 17:33:21 +05:30
commit 52e01935f5
31 changed files with 2791 additions and 4396 deletions

6560
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,12 @@ import Modal from 'components/Modal';
const CreateEnvironment = ({ collection, onClose }) => { const CreateEnvironment = ({ collection, onClose }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const inputRef = useRef(); const inputRef = useRef();
// todo: Add this to global env too.
const validateEnvironmentName = (name) => {
return !collection?.environments?.some((env) => env?.name?.toLowerCase().trim() === name?.toLowerCase().trim());
};
const formik = useFormik({ const formik = useFormik({
enableReinitialize: true, enableReinitialize: true,
initialValues: { initialValues: {
@ -17,9 +23,10 @@ const CreateEnvironment = ({ collection, onClose }) => {
}, },
validationSchema: Yup.object({ validationSchema: Yup.object({
name: Yup.string() name: Yup.string()
.min(1, 'must be at least 1 character') .min(1, 'Must be at least 1 character')
.max(50, 'must be 50 characters or less') .max(50, 'Must be 50 characters or less')
.required('name is required') .required('Name is required')
.test('duplicate-name', 'Environment already exists', validateEnvironmentName)
}), }),
onSubmit: (values) => { onSubmit: (values) => {
dispatch(addEnvironment(values.name, collection.uid)) dispatch(addEnvironment(values.name, collection.uid))

View File

@ -10,6 +10,7 @@ const StyledWrapper = styled.div`
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 10px; width: 10px;
min-width: 10px;
padding: 0; padding: 0;
cursor: col-resize; cursor: col-resize;
background: transparent; background: transparent;

View File

@ -17,7 +17,6 @@ const RenameCollection = ({ collection, onClose }) => {
validationSchema: Yup.object({ validationSchema: Yup.object({
name: Yup.string() name: Yup.string()
.min(1, 'must be at least 1 character') .min(1, 'must be at least 1 character')
.max(50, 'must be 50 characters or less')
.required('name is required') .required('name is required')
}), }),
onSubmit: (values) => { onSubmit: (values) => {

View File

@ -184,7 +184,7 @@ const Sidebar = () => {
Star Star
</GitHubButton> */} </GitHubButton> */}
</div> </div>
<div className="flex flex-grow items-center justify-end text-xs mr-2">v1.34.2</div> <div className="flex flex-grow items-center justify-end text-xs mr-2">v1.36.0</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -60,7 +60,7 @@ const trackStart = () => {
event: 'start', event: 'start',
properties: { properties: {
os: platformLib.os.family, os: platformLib.os.family,
version: '1.34.2' version: '1.36.0'
} }
}); });
}; };

View File

@ -9,6 +9,7 @@ const getReadNotificationIds = () => {
return readNotificationIds; return readNotificationIds;
} catch (err) { } catch (err) {
toast.error('An error occurred while fetching read notifications'); toast.error('An error occurred while fetching read notifications');
return [];
} }
}; };
@ -58,14 +59,16 @@ export const notificationSlice = createSlice({
}); });
}, },
markNotificationAsRead: (state, action) => { markNotificationAsRead: (state, action) => {
if (state.readNotificationIds.includes(action.payload.notificationId)) return; const { notificationId } = action.payload;
if (state.readNotificationIds.includes(notificationId)) return;
const notification = state.notifications.find( const notification = state.notifications.find(
(notification) => notification.id === action.payload.notificationId (notification) => notification.id === notificationId
); );
if (!notification) return; if (!notification) return;
state.readNotificationIds.push(action.payload.notificationId); state.readNotificationIds.push(notificationId);
setReadNotificationsIds(state.readNotificationIds); setReadNotificationsIds(state.readNotificationIds);
notification.read = true; notification.read = true;
}, },

View File

@ -303,7 +303,8 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
script: si.request.script, script: si.request.script,
vars: si.request.vars, vars: si.request.vars,
assertions: si.request.assertions, assertions: si.request.assertions,
tests: si.request.tests tests: si.request.tests,
docs: si.request.docs
}; };
// Handle auth object dynamically // Handle auth object dynamically

View File

@ -151,7 +151,15 @@ export const relativeDate = (dateString) => {
export const humanizeDate = (dateString) => { export const humanizeDate = (dateString) => {
// See this discussion for why .split is necessary // See this discussion for why .split is necessary
// https://stackoverflow.com/questions/7556591/is-the-javascript-date-object-always-one-day-off // https://stackoverflow.com/questions/7556591/is-the-javascript-date-object-always-one-day-off
const date = new Date(dateString.split('-'));
if (!dateString || typeof dateString !== 'string') {
return 'Invalid Date';
}
const date = new Date(dateString);
if (isNaN(date.getTime())) {
return 'Invalid Date';
}
return date.toLocaleDateString('en-US', { return date.toLocaleDateString('en-US', {
year: 'numeric', year: 'numeric',
month: 'long', month: 'long',

View File

@ -58,6 +58,18 @@ describe('common utils', () => {
it('should return invalid date if the date is invalid', () => { it('should return invalid date if the date is invalid', () => {
expect(humanizeDate('9999-99-99')).toBe('Invalid Date'); expect(humanizeDate('9999-99-99')).toBe('Invalid Date');
}); });
it('should return "Invalid Date" if the date is null', () => {
expect(humanizeDate(null)).toBe('Invalid Date');
});
it('should return a humanized date for a valid date in ISO format', () => {
expect(humanizeDate('2024-11-28T00:00:00Z')).toBe('November 28, 2024');
});
it('should return "Invalid Date" for a non-date string', () => {
expect(humanizeDate('some random text')).toBe('Invalid Date');
});
}); });
describe('relativeDate', () => { describe('relativeDate', () => {

View File

@ -57,6 +57,8 @@ function getDataString(request) {
console.error('Failed to parse JSON data:', error); console.error('Failed to parse JSON data:', error);
return { data: request.data.toString() }; return { data: request.data.toString() };
} }
} else if (contentType && contentType.includes('application/xml')) {
return { data: request.data };
} }
const parsedQueryString = querystring.parse(request.data, { sort: false }); const parsedQueryString = querystring.parse(request.data, { sort: false });

View File

@ -60,7 +60,7 @@ export const getRequestFromCurlCommand = (curlCommand, requestType = 'http-reque
} else if (contentType.includes('application/json')) { } else if (contentType.includes('application/json')) {
body.mode = 'json'; body.mode = 'json';
body.json = convertToCodeMirrorJson(parsedBody); body.json = convertToCodeMirrorJson(parsedBody);
} else if (contentType.includes('text/xml')) { } else if (contentType.includes('xml')) {
body.mode = 'xml'; body.mode = 'xml';
body.xml = parsedBody; body.xml = parsedBody;
} else if (contentType.includes('application/x-www-form-urlencoded')) { } else if (contentType.includes('application/x-www-form-urlencoded')) {

View File

@ -93,8 +93,68 @@ const printRunSummary = (results) => {
}; };
}; };
const createCollectionFromPath = (collectionPath) => {
const environmentsPath = `${collectionPath}/environments`;
const getFilesInOrder = (collectionPath) => {
let collection = {
pathname: collectionPath
};
const traverse = (currentPath) => {
const filesInCurrentDir = fs.readdirSync(currentPath);
if (currentPath.includes('node_modules')) {
return;
}
const currentDirItems = [];
for (const file of filesInCurrentDir) {
const filePath = path.join(currentPath, file);
const stats = fs.lstatSync(filePath);
if (
stats.isDirectory() &&
filePath !== environmentsPath &&
!filePath.startsWith('.git') &&
!filePath.startsWith('node_modules')
) {
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) {
const folderBruContent = fs.readFileSync(folderBruFilePath, 'utf8');
let folderBruJson = collectionBruToJson(folderBruContent);
folderItem.root = folderBruJson;
}
currentDirItems.push(folderItem);
}
}
for (const file of filesInCurrentDir) {
if (['collection.bru', 'folder.bru'].includes(file)) {
continue;
}
const filePath = path.join(currentPath, file);
const stats = fs.lstatSync(filePath);
if (!stats.isDirectory() && path.extname(filePath) === '.bru') {
const bruContent = fs.readFileSync(filePath, 'utf8');
const bruJson = bruToJson(bruContent);
currentDirItems.push({
name: file,
pathname: filePath,
...bruJson
});
}
}
return currentDirItems
};
collection.items = traverse(collectionPath);
return collection;
};
return getFilesInOrder(collectionPath);
};
const getBruFilesRecursively = (dir, testsOnly) => { const getBruFilesRecursively = (dir, testsOnly) => {
const environmentsPath = 'environments'; const environmentsPath = 'environments';
const collection = {};
const getFilesInOrder = (dir) => { const getFilesInOrder = (dir) => {
let bruJsons = []; let bruJsons = [];
@ -359,6 +419,12 @@ const handler = async function (argv) {
const brunoConfigFile = fs.readFileSync(brunoJsonPath, 'utf8'); const brunoConfigFile = fs.readFileSync(brunoJsonPath, 'utf8');
const brunoConfig = JSON.parse(brunoConfigFile); const brunoConfig = JSON.parse(brunoConfigFile);
const collectionRoot = getCollectionRoot(collectionPath); const collectionRoot = getCollectionRoot(collectionPath);
let collection = createCollectionFromPath(collectionPath);
collection = {
brunoConfig,
root: collectionRoot,
...collection
}
if (clientCertConfig) { if (clientCertConfig) {
try { try {
@ -584,7 +650,8 @@ const handler = async function (argv) {
processEnvVars, processEnvVars,
brunoConfig, brunoConfig,
collectionRoot, collectionRoot,
runtime runtime,
collection
); );
results.push({ results.push({

View File

@ -13,14 +13,17 @@ const getContentType = (headers = {}) => {
return contentType; return contentType;
}; };
const interpolateVars = (request, envVars = {}, runtimeVariables = {}, processEnvVars = {}) => { const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, processEnvVars = {}) => {
const collectionVariables = request?.collectionVariables || {};
const folderVariables = request?.folderVariables || {};
const requestVariables = request?.requestVariables || {};
// we clone envVars because we don't want to modify the original object // we clone envVars because we don't want to modify the original object
envVars = cloneDeep(envVars); envVariables = cloneDeep(envVariables);
// envVars can inturn have values as {{process.env.VAR_NAME}} // envVars can inturn have values as {{process.env.VAR_NAME}}
// so we need to interpolate envVars first with processEnvVars // so we need to interpolate envVars first with processEnvVars
forOwn(envVars, (value, key) => { forOwn(envVariables, (value, key) => {
envVars[key] = interpolate(value, { envVariables[key] = interpolate(value, {
process: { process: {
env: { env: {
...processEnvVars ...processEnvVars
@ -36,7 +39,10 @@ const interpolateVars = (request, envVars = {}, runtimeVariables = {}, processEn
// runtimeVariables take precedence over envVars // runtimeVariables take precedence over envVars
const combinedVars = { const combinedVars = {
...envVars, ...collectionVariables,
...envVariables,
...folderVariables,
...requestVariables,
...runtimeVariables, ...runtimeVariables,
process: { process: {
env: { env: {

View File

@ -1,24 +1,230 @@
const { get, each, filter } = require('lodash'); const { get, each, filter, find, compact } = require('lodash');
const fs = require('fs'); const fs = require('fs');
const os = require('os');
var JSONbig = require('json-bigint'); var JSONbig = require('json-bigint');
const decomment = require('decomment'); const decomment = require('decomment');
const crypto = require('node:crypto'); const crypto = require('node:crypto');
const prepareRequest = (request, collectionRoot) => { const mergeHeaders = (collection, request, requestTreePath) => {
const headers = {}; let headers = new Map();
let contentTypeDefined = false;
// collection headers let collectionHeaders = get(collection, 'root.request.headers', []);
each(get(collectionRoot, 'request.headers', []), (h) => { collectionHeaders.forEach((header) => {
if (h.enabled) { if (header.enabled) {
headers[h.name] = h.value; headers.set(header.name, header.value);
if (h.name.toLowerCase() === 'content-type') {
contentTypeDefined = true;
}
} }
}); });
each(request.headers, (h) => { for (let i of requestTreePath) {
if (i.type === 'folder') {
let _headers = get(i, 'root.request.headers', []);
_headers.forEach((header) => {
if (header.enabled) {
headers.set(header.name, header.value);
}
});
} else {
const _headers = i?.draft ? get(i, 'draft.request.headers', []) : get(i, 'request.headers', []);
_headers.forEach((header) => {
if (header.enabled) {
headers.set(header.name, header.value);
}
});
}
}
request.headers = Array.from(headers, ([name, value]) => ({ name, value, enabled: true }));
};
const mergeVars = (collection, request, requestTreePath) => {
let reqVars = new Map();
let collectionRequestVars = get(collection, 'root.request.vars.req', []);
let collectionVariables = {};
collectionRequestVars.forEach((_var) => {
if (_var.enabled) {
reqVars.set(_var.name, _var.value);
collectionVariables[_var.name] = _var.value;
}
});
let folderVariables = {};
let requestVariables = {};
for (let i of requestTreePath) {
if (i.type === 'folder') {
let vars = get(i, 'root.request.vars.req', []);
vars.forEach((_var) => {
if (_var.enabled) {
reqVars.set(_var.name, _var.value);
folderVariables[_var.name] = _var.value;
}
});
} else {
const vars = i?.draft ? get(i, 'draft.request.vars.req', []) : get(i, 'request.vars.req', []);
vars.forEach((_var) => {
if (_var.enabled) {
reqVars.set(_var.name, _var.value);
requestVariables[_var.name] = _var.value;
}
});
}
}
request.collectionVariables = collectionVariables;
request.folderVariables = folderVariables;
request.requestVariables = requestVariables;
if(request?.vars) {
request.vars.req = Array.from(reqVars, ([name, value]) => ({
name,
value,
enabled: true,
type: 'request'
}));
}
let resVars = new Map();
let collectionResponseVars = get(collection, 'root.request.vars.res', []);
collectionResponseVars.forEach((_var) => {
if (_var.enabled) {
resVars.set(_var.name, _var.value);
}
});
for (let i of requestTreePath) {
if (i.type === 'folder') {
let vars = get(i, 'root.request.vars.res', []);
vars.forEach((_var) => {
if (_var.enabled) {
resVars.set(_var.name, _var.value);
}
});
} else {
const vars = i?.draft ? get(i, 'draft.request.vars.res', []) : get(i, 'request.vars.res', []);
vars.forEach((_var) => {
if (_var.enabled) {
resVars.set(_var.name, _var.value);
}
});
}
}
if(request?.vars) {
request.vars.res = Array.from(resVars, ([name, value]) => ({
name,
value,
enabled: true,
type: 'response'
}));
}
};
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() !== '') {
combinedPreReqScript.push(preReqScript);
}
let postResScript = get(i, 'root.request.script.res', '');
if (postResScript && postResScript.trim() !== '') {
combinedPostResScript.push(postResScript);
}
let tests = get(i, 'root.request.tests', '');
if (tests && tests?.trim?.() !== '') {
combinedTests.push(tests);
}
}
}
if (combinedPreReqScript.length) {
request.script.req = compact([collectionPreReqScript, ...combinedPreReqScript, request?.script?.req || '']).join(os.EOL);
}
if (combinedPostResScript.length) {
if (scriptFlow === 'sequential') {
request.script.res = compact([collectionPostResScript, ...combinedPostResScript, request?.script?.res || '']).join(os.EOL);
} else {
request.script.res = compact([request?.script?.res || '', ...combinedPostResScript.reverse(), collectionPostResScript]).join(os.EOL);
}
}
if (combinedTests.length) {
if (scriptFlow === 'sequential') {
request.tests = compact([collectionTests, ...combinedTests, request?.tests || '']).join(os.EOL);
} else {
request.tests = compact([request?.tests || '', ...combinedTests.reverse(), collectionTests]).join(os.EOL);
}
}
};
const findItem = (items = [], pathname) => {
return find(items, (i) => i.pathname === pathname);
};
const findItemInCollection = (collection, pathname) => {
let flattenedItems = flattenItems(collection.items);
return findItem(flattenedItems, pathname);
};
const findParentItemInCollection = (collection, pathname) => {
let flattenedItems = flattenItems(collection.items);
return find(flattenedItems, (item) => {
return item.items && find(item.items, (i) => i.pathname === pathname);
});
};
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 getTreePathFromCollectionToItem = (collection, _item) => {
let path = [];
let item = findItemInCollection(collection, _item.pathname);
while (item) {
path.unshift(item);
item = findParentItemInCollection(collection, item.pathname);
}
return path;
};
const prepareRequest = (item = {}, collection = {}) => {
const request = item?.request;
const brunoConfig = get(collection, 'brunoConfig', {});
const headers = {};
let contentTypeDefined = false;
const scriptFlow = brunoConfig?.scripts?.flow ?? 'sandwich';
const requestTreePath = getTreePathFromCollectionToItem(collection, item);
if (requestTreePath && requestTreePath.length > 0) {
mergeHeaders(collection, request, requestTreePath);
mergeScripts(collection, request, requestTreePath, scriptFlow);
mergeVars(collection, request, requestTreePath);
}
each(get(request, 'headers', []), (h) => {
if (h.enabled) { if (h.enabled) {
headers[h.name] = h.value; headers[h.name] = h.value;
if (h.name.toLowerCase() === 'content-type') { if (h.name.toLowerCase() === 'content-type') {
@ -34,7 +240,7 @@ const prepareRequest = (request, collectionRoot) => {
pathParams: request?.params?.filter((param) => param.type === 'path') pathParams: request?.params?.filter((param) => param.type === 'path')
}; };
const collectionAuth = get(collectionRoot, 'request.auth'); const collectionAuth = get(collection, 'root.request.auth');
if (collectionAuth && request.auth.mode === 'inherit') { if (collectionAuth && request.auth.mode === 'inherit') {
if (collectionAuth.mode === 'basic') { if (collectionAuth.mode === 'basic') {
axiosRequest.auth = { axiosRequest.auth = {
@ -157,10 +363,19 @@ const prepareRequest = (request, collectionRoot) => {
axiosRequest.data = graphqlQuery; axiosRequest.data = graphqlQuery;
} }
if (request.script && request.script.length) { if (request.script) {
axiosRequest.script = request.script; axiosRequest.script = request.script;
} }
if (request.tests) {
axiosRequest.tests = request.tests;
}
axiosRequest.vars = request.vars;
axiosRequest.collectionVariables = request.collectionVariables;
axiosRequest.folderVariables = request.folderVariables;
axiosRequest.requestVariables = request.requestVariables;
return axiosRequest; return axiosRequest;
}; };

View File

@ -36,13 +36,17 @@ const runSingleRequest = async function (
processEnvVars, processEnvVars,
brunoConfig, brunoConfig,
collectionRoot, collectionRoot,
runtime runtime,
collection
) { ) {
try { try {
let request; let request;
let nextRequestName; let nextRequestName;
let item = {
request = prepareRequest(bruJson.request, collectionRoot); pathname: path.join(collectionPath, filename),
...bruJson
}
request = prepareRequest(item, collection);
request.__bruno__executionMode = 'cli'; request.__bruno__executionMode = 'cli';
@ -50,10 +54,7 @@ const runSingleRequest = async function (
scriptingConfig.runtime = runtime; scriptingConfig.runtime = runtime;
// run pre request script // run pre request script
const requestScriptFile = compact([ const requestScriptFile = get(request, 'script.req');
get(collectionRoot, 'request.script.req'),
get(bruJson, 'request.script.req')
]).join(os.EOL);
if (requestScriptFile?.length) { if (requestScriptFile?.length) {
const scriptRuntime = new ScriptRuntime({ runtime: scriptingConfig?.runtime }); const scriptRuntime = new ScriptRuntime({ runtime: scriptingConfig?.runtime });
const result = await scriptRuntime.runRequestScript( const result = await scriptRuntime.runRequestScript(
@ -291,10 +292,7 @@ const runSingleRequest = async function (
} }
// run post response script // run post response script
const responseScriptFile = compact([ const responseScriptFile = get(request, 'script.res');
get(collectionRoot, 'request.script.res'),
get(bruJson, 'request.script.res')
]).join(os.EOL);
if (responseScriptFile?.length) { if (responseScriptFile?.length) {
const scriptRuntime = new ScriptRuntime({ runtime: scriptingConfig?.runtime }); const scriptRuntime = new ScriptRuntime({ runtime: scriptingConfig?.runtime });
const result = await scriptRuntime.runResponseScript( const result = await scriptRuntime.runResponseScript(
@ -339,7 +337,7 @@ const runSingleRequest = async function (
// run tests // run tests
let testResults = []; 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') { if (typeof testFile === 'string') {
const testRuntime = new TestRuntime({ runtime: scriptingConfig?.runtime }); const testRuntime = new TestRuntime({ runtime: scriptingConfig?.runtime });
const result = await testRuntime.runTests( const result = await testRuntime.runTests(

View File

@ -7,14 +7,14 @@ describe('prepare-request: prepareRequest', () => {
it('If request body is valid JSON', async () => { it('If request body is valid JSON', async () => {
const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' }; const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' };
const expected = { test: '{{someVar}}' }; const expected = { test: '{{someVar}}' };
const result = prepareRequest({ body }); const result = prepareRequest({ request: { body } });
expect(result.data).toEqual(expected); expect(result.data).toEqual(expected);
}); });
it('If request body is not valid JSON', async () => { it('If request body is not valid JSON', async () => {
const body = { mode: 'json', json: '{\n"test": {{someVar}} // comment\n}' }; const body = { mode: 'json', json: '{\n"test": {{someVar}} // comment\n}' };
const expected = '{\n"test": {{someVar}} \n}'; const expected = '{\n"test": {{someVar}} \n}';
const result = prepareRequest({ body }); const result = prepareRequest({ request: { body } });
expect(result.data).toEqual(expected); expect(result.data).toEqual(expected);
}); });
}); });

View File

@ -1,5 +1,5 @@
{ {
"version": "v1.34.2", "version": "v1.36.0",
"name": "bruno", "name": "bruno",
"description": "Opensource API Client for Exploring and Testing APIs", "description": "Opensource API Client for Exploring and Testing APIs",
"homepage": "https://www.usebruno.com", "homepage": "https://www.usebruno.com",

View File

@ -14,6 +14,7 @@ auth:bearer {
vars:pre-request { vars:pre-request {
collection_pre_var: collection_pre_var_value collection_pre_var: collection_pre_var_value
collection_pre_var_token: {{request_pre_var_token}} collection_pre_var_token: {{request_pre_var_token}}
collection-var: collection-var-value
} }
docs { docs {

View File

@ -0,0 +1,7 @@
meta {
name: bru
}
vars:pre-request {
folder-var: folder-var-value
}

View File

@ -0,0 +1,18 @@
meta {
name: getCollectionVar
type: http
seq: 9
}
get {
url: {{host}}/ping
body: none
auth: none
}
tests {
test("should get collection var in scripts", function() {
const testVar = bru.getCollectionVar("collection-var");
expect(testVar).to.equal("collection-var-value");
});
}

View File

@ -0,0 +1,18 @@
meta {
name: getFolderVar
type: http
seq: 8
}
get {
url: {{host}}/ping
body: none
auth: none
}
tests {
test("should get folder var in scripts", function() {
const testVar = bru.getFolderVar("folder-var");
expect(testVar).to.equal("folder-var-value");
});
}

View File

@ -0,0 +1,22 @@
meta {
name: getRequestVar
type: http
seq: 7
}
get {
url: {{host}}/ping
body: none
auth: none
}
vars:pre-request {
request-var: request-var-value
}
tests {
test("should get request var in scripts", function() {
const testVar = bru.getRequestVar("request-var");
expect(testVar).to.equal("request-var-value");
});
}

View File

@ -0,0 +1,12 @@
{
"version": "1",
"name": "sandwich_exec",
"type": "collection",
"ignore": [
"node_modules",
".git"
],
"scripts": {
"flow": "sandwich"
}
}

View File

@ -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'));
}
}

View File

@ -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");
}

View File

@ -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());
});
}

View File

@ -0,0 +1,12 @@
{
"version": "1",
"name": "sequential_exec",
"type": "collection",
"ignore": [
"node_modules",
".git"
],
"scripts": {
"flow": "sequential"
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
});
}