forked from extern/bruno
feat: making request and response scripts work
This commit is contained in:
parent
60c96f7d27
commit
22a14aa67a
@ -89,7 +89,7 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<section className="flex w-full mt-5">{getTabPanel(focusedTab.requestPaneTab)}</section>
|
||||
<section className={`flex w-full ${focusedTab.requestPaneTab === 'script' ? '' : 'mt-5'}`}>{getTabPanel(focusedTab.requestPaneTab)}</section>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
@ -2,8 +2,12 @@ import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
div.CodeMirror {
|
||||
/* todo: find a better way */
|
||||
height: calc(100vh - 220px);
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
div.title {
|
||||
color: rgb(155 155 155);
|
||||
font-weight: 500;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -2,20 +2,21 @@ import React from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import CodeEditor from 'components/CodeEditor';
|
||||
import { updateRequestScript } from 'providers/ReduxStore/slices/collections';
|
||||
import { updateRequestScript, updateResponseScript } from 'providers/ReduxStore/slices/collections';
|
||||
import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const Script = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const script = item.draft ? get(item, 'draft.request.script') : get(item, 'request.script');
|
||||
const requestScript = item.draft ? get(item, 'draft.request.script.req') : get(item, 'request.script.req');
|
||||
const responseScript = item.draft ? get(item, 'draft.request.script.res') : get(item, 'request.script.res');
|
||||
|
||||
const {
|
||||
storedTheme
|
||||
} = useTheme();
|
||||
|
||||
const onEdit = (value) => {
|
||||
const onRequestScriptEdit = (value) => {
|
||||
dispatch(
|
||||
updateRequestScript({
|
||||
script: value,
|
||||
@ -25,19 +26,43 @@ const Script = ({ item, collection }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const onResponseScriptEdit = (value) => {
|
||||
dispatch(
|
||||
updateResponseScript({
|
||||
script: value,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const onRun = () => dispatch(sendRequest(item, collection.uid));
|
||||
const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full">
|
||||
<CodeEditor
|
||||
collection={collection} value={script || ''}
|
||||
theme={storedTheme}
|
||||
onEdit={onEdit}
|
||||
mode='javascript'
|
||||
onRun={onRun}
|
||||
onSave={onSave}
|
||||
/>
|
||||
<StyledWrapper className="w-full flex flex-col">
|
||||
<div className='flex-1'>
|
||||
<div className='mb-1 title'>Request</div>
|
||||
<CodeEditor
|
||||
collection={collection} value={requestScript || ''}
|
||||
theme={storedTheme}
|
||||
onEdit={onRequestScriptEdit}
|
||||
mode='javascript'
|
||||
onRun={onRun}
|
||||
onSave={onSave}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex-1 mt-6'>
|
||||
<div className='mt-1 mb-1 title'>Response</div>
|
||||
<CodeEditor
|
||||
collection={collection} value={responseScript || ''}
|
||||
theme={storedTheme}
|
||||
onEdit={onResponseScriptEdit}
|
||||
mode='javascript'
|
||||
onRun={onRun}
|
||||
onSave={onSave}
|
||||
/>
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
@ -652,7 +652,23 @@ export const collectionsSlice = createSlice({
|
||||
if (!item.draft) {
|
||||
item.draft = cloneDeep(item);
|
||||
}
|
||||
item.draft.request.script = action.payload.script;
|
||||
item.draft.request.script = item.draft.request.script || {};
|
||||
item.draft.request.script.req = action.payload.script;
|
||||
}
|
||||
}
|
||||
},
|
||||
updateResponseScript: (state, action) => {
|
||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||
|
||||
if (collection) {
|
||||
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||
|
||||
if (item && isItemARequest(item)) {
|
||||
if (!item.draft) {
|
||||
item.draft = cloneDeep(item);
|
||||
}
|
||||
item.draft.request.script = item.draft.request.script || {};
|
||||
item.draft.request.script.res = action.payload.script;
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -971,6 +987,7 @@ export const {
|
||||
updateRequestGraphqlQuery,
|
||||
updateRequestGraphqlVariables,
|
||||
updateRequestScript,
|
||||
updateResponseScript,
|
||||
updateRequestTests,
|
||||
updateRequestMethod,
|
||||
collectionAddFileEvent,
|
||||
|
@ -193,9 +193,9 @@ const darkTheme = {
|
||||
|
||||
codemirror: {
|
||||
bg: '#1e1e1e',
|
||||
border: 'transparent',
|
||||
border: '#373737',
|
||||
gutter: {
|
||||
bg: '#1e1e1e'
|
||||
bg: '#262626'
|
||||
},
|
||||
variable: {
|
||||
valid: 'rgb(11 178 126)',
|
||||
|
@ -181,7 +181,6 @@ const add = async (win, pathname, collectionUid, collectionPath) => {
|
||||
try {
|
||||
const bru = fs.readFileSync(pathname, 'utf8');
|
||||
file.data = bruToJson(bru);
|
||||
console.log(JSON.stringify(file.data, null, 2));
|
||||
hydrateRequestWithUuid(file.data, pathname);
|
||||
win.webContents.send('main:collection-tree-updated', 'addFile', file);
|
||||
} catch (err) {
|
||||
|
@ -39,7 +39,7 @@ const bruToJson = (bru) => {
|
||||
"params": _.get(json, "query", []),
|
||||
"headers": _.get(json, "headers", []),
|
||||
"body": _.get(json, "body", {}),
|
||||
"script": _.get(json, "script", ""),
|
||||
"script": _.get(json, "script", {}),
|
||||
"tests": _.get(json, "tests", "")
|
||||
}
|
||||
};
|
||||
@ -84,8 +84,8 @@ const jsonToBru = (json) => {
|
||||
query: _.get(json, 'request.params', []),
|
||||
headers: _.get(json, 'request.headers', []),
|
||||
body: _.get(json, 'request.body', {}),
|
||||
script: _.get(json, 'script', ''),
|
||||
tests: _.get(json, 'tests', ''),
|
||||
script: _.get(json, 'request.script', {}),
|
||||
tests: _.get(json, 'request.tests', ''),
|
||||
};
|
||||
|
||||
return jsonToBruV2(bruJson);
|
||||
|
@ -99,10 +99,10 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
|
||||
const envVars = getEnvVars(environment);
|
||||
|
||||
if(request.script && request.script.length) {
|
||||
let script = request.script + '\n if (typeof onRequest === "function") {onRequest(__brunoRequest);}';
|
||||
const requestScript = get(request, 'script.req');
|
||||
if(requestScript && requestScript.length) {
|
||||
const scriptRuntime = new ScriptRuntime();
|
||||
const result = scriptRuntime.runRequestScript(script, request, envVars, collectionVariables, collectionPath);
|
||||
const result = scriptRuntime.runRequestScript(requestScript, request, envVars, collectionVariables, collectionPath);
|
||||
|
||||
mainWindow.webContents.send('main:script-environment-update', {
|
||||
environment: result.environment,
|
||||
@ -130,10 +130,10 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
|
||||
const response = await axios(request);
|
||||
|
||||
if(request.script && request.script.length) {
|
||||
let script = request.script + '\n if (typeof onResponse === "function") {onResponse(__brunoResponse);}';
|
||||
const responseScript = get(request, 'script.res');
|
||||
if(responseScript && responseScript.length) {
|
||||
const scriptRuntime = new ScriptRuntime();
|
||||
const result = scriptRuntime.runResponseScript(script, response, envVars, collectionVariables, collectionPath);
|
||||
const result = scriptRuntime.runResponseScript(responseScript, response, envVars, collectionVariables, collectionPath);
|
||||
|
||||
mainWindow.webContents.send('main:script-environment-update', {
|
||||
environment: result.environment,
|
||||
@ -280,10 +280,10 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
request.data = form;
|
||||
}
|
||||
|
||||
if(request.script && request.script.length) {
|
||||
let script = request.script + '\n if (typeof onRequest === "function") {onRequest(__brunoRequest);}';
|
||||
const requestScript = get(request, 'script.req');
|
||||
if(requestScript && requestScript.length) {
|
||||
const scriptRuntime = new ScriptRuntime();
|
||||
const result = scriptRuntime.runRequestScript(script, request, envVars, collectionVariables, collectionPath);
|
||||
const result = scriptRuntime.runRequestScript(requestScript, request, envVars, collectionVariables, collectionPath);
|
||||
|
||||
mainWindow.webContents.send('main:script-environment-update', {
|
||||
environment: result.environment,
|
||||
@ -312,10 +312,10 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
const response = await axios(request);
|
||||
timeEnd = Date.now();
|
||||
|
||||
if(request.script && request.script.length) {
|
||||
let script = request.script + '\n if (typeof onResponse === "function") {onResponse(__brunoResponse);}';
|
||||
const responseScript = get(request, 'script.res');
|
||||
if(responseScript && responseScript.length) {
|
||||
const scriptRuntime = new ScriptRuntime();
|
||||
const result = scriptRuntime.runResponseScript(script, response, envVars, collectionVariables, collectionPath);
|
||||
const result = scriptRuntime.runResponseScript(responseScript, response, envVars, collectionVariables, collectionPath);
|
||||
|
||||
mainWindow.webContents.send('main:script-environment-update', {
|
||||
environment: result.environment,
|
||||
|
@ -59,7 +59,7 @@ const prepareRequest = (request) => {
|
||||
axiosRequest.data = graphqlQuery;
|
||||
}
|
||||
|
||||
if (request.script && request.script.length) {
|
||||
if (request.script) {
|
||||
axiosRequest.script = request.script;
|
||||
}
|
||||
|
||||
|
@ -1,40 +1,10 @@
|
||||
|
||||
// Inbuilt Library Support
|
||||
const atob = require('atob');
|
||||
const btoa = require('btoa');
|
||||
const _ = require('lodash');
|
||||
const moment = require('moment');
|
||||
const uuid = require('uuid');
|
||||
const nanoid = require('nanoid');
|
||||
const CryptoJS = require('crypto-js');
|
||||
|
||||
class Bru {
|
||||
constructor(environment, collectionVariables) {
|
||||
this._environment = environment;
|
||||
this._collectionVariables = collectionVariables;
|
||||
}
|
||||
|
||||
require(module) {
|
||||
switch(module) {
|
||||
case 'atob':
|
||||
return atob;
|
||||
case 'btoa':
|
||||
return btoa;
|
||||
case 'lodash':
|
||||
return _;
|
||||
case 'moment':
|
||||
return moment;
|
||||
case 'uuid':
|
||||
return uuid;
|
||||
case 'nanoid':
|
||||
return nanoid;
|
||||
case 'crypto-js':
|
||||
return CryptoJS;
|
||||
default:
|
||||
throw new Error(`Module ${module} is not supported`);
|
||||
}
|
||||
}
|
||||
|
||||
getEnvVar(key) {
|
||||
return this._environment[key];
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ class BrunoRequest {
|
||||
this._request.headers[name] = value;
|
||||
}
|
||||
|
||||
getData() {
|
||||
getBody() {
|
||||
return this._request.data;
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
setBody(data) {
|
||||
this._request.data = data;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
class BrunoResponse {
|
||||
constructor(response) {
|
||||
this._response = response;
|
||||
this.status = response.status;
|
||||
this.statusText = response.statusText;
|
||||
this.headers = response.headers;
|
||||
this.body = response.data;
|
||||
}
|
||||
|
||||
getStatus() {
|
||||
@ -15,7 +19,7 @@ class BrunoResponse {
|
||||
return this._response.headers;
|
||||
}
|
||||
|
||||
getData() {
|
||||
getBody() {
|
||||
return this._response.data;
|
||||
}
|
||||
}
|
||||
|
@ -4,24 +4,42 @@ const Bru = require('./bru');
|
||||
const BrunoRequest = require('./bruno-request');
|
||||
const BrunoResponse = require('./bruno-response');
|
||||
|
||||
// Inbuilt Library Support
|
||||
const atob = require('atob');
|
||||
const btoa = require('btoa');
|
||||
const lodash = require('lodash');
|
||||
const moment = require('moment');
|
||||
const uuid = require('uuid');
|
||||
const nanoid = require('nanoid');
|
||||
const CryptoJS = require('crypto-js');
|
||||
|
||||
class ScriptRuntime {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
runRequestScript(script, request, environment, collectionVariables, collectionPath) {
|
||||
const bru = new Bru(environment, collectionVariables);
|
||||
const __brunoRequest = new BrunoRequest(request);
|
||||
const $bru = new Bru(environment, collectionVariables);
|
||||
const $req = new BrunoRequest(request);
|
||||
|
||||
const context = {
|
||||
bru,
|
||||
__brunoRequest
|
||||
$bru,
|
||||
$req
|
||||
};
|
||||
const vm = new NodeVM({
|
||||
sandbox: context,
|
||||
require: {
|
||||
context: 'sandbox',
|
||||
external: true,
|
||||
root: [collectionPath]
|
||||
root: [collectionPath],
|
||||
mock: {
|
||||
atob,
|
||||
btoa,
|
||||
lodash,
|
||||
moment,
|
||||
uuid,
|
||||
nanoid,
|
||||
'crypto-js': CryptoJS
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -35,19 +53,28 @@ class ScriptRuntime {
|
||||
}
|
||||
|
||||
runResponseScript(script, response, environment, collectionVariables, collectionPath) {
|
||||
const bru = new Bru(environment, collectionVariables);
|
||||
const __brunoResponse = new BrunoResponse(response);
|
||||
const $bru = new Bru(environment, collectionVariables);
|
||||
const $res = new BrunoResponse(response);
|
||||
|
||||
const context = {
|
||||
bru,
|
||||
__brunoResponse
|
||||
$bru,
|
||||
$res
|
||||
};
|
||||
const vm = new NodeVM({
|
||||
sandbox: context,
|
||||
require: {
|
||||
context: 'sandbox',
|
||||
external: true,
|
||||
root: [collectionPath]
|
||||
root: [collectionPath],
|
||||
mock: {
|
||||
atob,
|
||||
btoa,
|
||||
lodash,
|
||||
moment,
|
||||
uuid,
|
||||
nanoid,
|
||||
'crypto-js': CryptoJS
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -7,23 +7,32 @@ const BrunoResponse = require('./bruno-response');
|
||||
const Test = require('./test');
|
||||
const TestResults = require('./test-results');
|
||||
|
||||
// Inbuilt Library Support
|
||||
const atob = require('atob');
|
||||
const btoa = require('btoa');
|
||||
const lodash = require('lodash');
|
||||
const moment = require('moment');
|
||||
const uuid = require('uuid');
|
||||
const nanoid = require('nanoid');
|
||||
const CryptoJS = require('crypto-js');
|
||||
|
||||
class TestRuntime {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
runTests(testsFile, request, response, environment, collectionVariables, collectionPath) {
|
||||
const bru = new Bru(environment, collectionVariables);
|
||||
const req = new BrunoRequest(request);
|
||||
const res = new BrunoResponse(response);
|
||||
const $bru = new Bru(environment, collectionVariables);
|
||||
const $req = new BrunoRequest(request);
|
||||
const $res = new BrunoResponse(response);
|
||||
|
||||
const __brunoTestResults = new TestResults();
|
||||
const test = Test(__brunoTestResults, chai);
|
||||
|
||||
const context = {
|
||||
bru,
|
||||
req,
|
||||
res,
|
||||
test,
|
||||
$bru,
|
||||
$req,
|
||||
$res,
|
||||
expect: chai.expect,
|
||||
assert: chai.assert,
|
||||
__brunoTestResults: __brunoTestResults
|
||||
@ -34,7 +43,16 @@ class TestRuntime {
|
||||
require: {
|
||||
context: 'sandbox',
|
||||
external: true,
|
||||
root: [collectionPath]
|
||||
root: [collectionPath],
|
||||
mock: {
|
||||
atob,
|
||||
btoa,
|
||||
lodash,
|
||||
moment,
|
||||
uuid,
|
||||
nanoid,
|
||||
'crypto-js': CryptoJS
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -53,7 +53,10 @@ const requestSchema = Yup.object({
|
||||
headers: Yup.array().of(keyValueSchema).required('headers are required'),
|
||||
params: Yup.array().of(keyValueSchema).required('params are required'),
|
||||
body: requestBodySchema,
|
||||
script: Yup.string().nullable(),
|
||||
script: Yup.object({
|
||||
req: Yup.string().nullable(),
|
||||
res: Yup.string().nullable()
|
||||
}).noUnknown(true).strict(),
|
||||
tests: Yup.string().nullable()
|
||||
}).noUnknown(true).strict();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user