forked from extern/bruno
fix: fixed many bugs (too many to count :) )
This commit is contained in:
parent
8202182074
commit
a0903a5842
@ -6,12 +6,22 @@ const StyledWrapper = styled.div`
|
|||||||
border: solid 1px ${(props) => props.theme.codemirror.border};
|
border: solid 1px ${(props) => props.theme.codemirror.border};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
|
||||||
|
background: #d2d7db;
|
||||||
|
}
|
||||||
|
|
||||||
textarea.cm-editor {
|
textarea.cm-editor {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: dark mode temporary fix
|
// Todo: dark mode temporary fix
|
||||||
// Clean this
|
// Clean this
|
||||||
|
.CodeMirror.cm-s-monokai {
|
||||||
|
.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
|
||||||
|
background: #444444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {
|
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {
|
||||||
color: #9cdcfe !important;
|
color: #9cdcfe !important;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||||
readOnly: this.props.readOnly,
|
readOnly: this.props.readOnly,
|
||||||
|
scrollbarStyle: "overlay",
|
||||||
theme: this.props.theme === 'dark' ? 'monokai' : 'default',
|
theme: this.props.theme === 'dark' ? 'monokai' : 'default',
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
'Cmd-Enter': () => {
|
'Cmd-Enter': () => {
|
||||||
|
@ -6,6 +6,9 @@ const Wrapper = styled.div`
|
|||||||
color: ${(props) => props.theme.textLink};
|
color: ${(props) => props.theme.textLink};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.danger {
|
||||||
|
color: ${(props) => props.theme.colors.text.danger};
|
||||||
|
}
|
||||||
|
|
||||||
.test-summary {
|
.test-summary {
|
||||||
color: ${(props) => props.theme.tabs.active.border};
|
color: ${(props) => props.theme.tabs.active.border};
|
||||||
|
@ -32,17 +32,19 @@ export default function RunnerResults({collection}) {
|
|||||||
item.pathname = info.pathname;
|
item.pathname = info.pathname;
|
||||||
item.relativePath = getRelativePath(collection.pathname, info.pathname);
|
item.relativePath = getRelativePath(collection.pathname, info.pathname);
|
||||||
|
|
||||||
if(item.testResults) {
|
if(item.status !== "error") {
|
||||||
const failed = item.testResults.filter((result) => result.status === 'fail');
|
if(item.testResults) {
|
||||||
|
const failed = item.testResults.filter((result) => result.status === 'fail');
|
||||||
|
|
||||||
item.testStatus = failed.length ? 'fail' : 'pass';
|
item.testStatus = failed.length ? 'fail' : 'pass';
|
||||||
} else {
|
} else {
|
||||||
item.testStatus = 'pass';
|
item.testStatus = 'pass';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const passedRequests = items.filter((item) => item.testStatus === 'pass');
|
const passedRequests = items.filter((item) => item.status !== "error" && item.testStatus === 'pass');
|
||||||
const failedRequests = items.filter((item) => item.testStatus === 'fail');
|
const failedRequests = items.filter((item) => item.status !== "error" && item.testStatus === 'fail');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className='px-4'>
|
<StyledWrapper className='px-4'>
|
||||||
@ -61,14 +63,14 @@ export default function RunnerResults({collection}) {
|
|||||||
<div className="item-path mt-2">
|
<div className="item-path mt-2">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<span>
|
<span>
|
||||||
{item.testStatus === 'pass' ? (
|
{item.status !== "error" && item.testStatus === 'pass' ? (
|
||||||
<IconCircleCheck className="test-success" size={20} strokeWidth={1.5}/>
|
<IconCircleCheck className="test-success" size={20} strokeWidth={1.5}/>
|
||||||
) : (
|
) : (
|
||||||
<IconCircleX className="test-failure" size={20} strokeWidth={1.5}/>
|
<IconCircleX className="test-failure" size={20} strokeWidth={1.5}/>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<span className='mr-1 ml-2'>{item.relativePath}</span>
|
<span className={`mr-1 ml-2 ${(item.status == "error" || item.testStatus == 'fail') ? 'danger' : ''}`}>{item.relativePath}</span>
|
||||||
{item.status !== "completed" ? (
|
{(item.status !== "error" && item.status !== "completed") ? (
|
||||||
<IconRefresh className="animate-spin ml-1" size={18} strokeWidth={1.5}/>
|
<IconRefresh className="animate-spin ml-1" size={18} strokeWidth={1.5}/>
|
||||||
) : (
|
) : (
|
||||||
<span className='text-xs link cursor-pointer' onClick={() => setSelectedItem(item)}>
|
<span className='text-xs link cursor-pointer' onClick={() => setSelectedItem(item)}>
|
||||||
@ -81,6 +83,11 @@ export default function RunnerResults({collection}) {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{item.status == "error" ? (
|
||||||
|
<div className="error-message pl-8 pt-2 text-xs">
|
||||||
|
{item.error}
|
||||||
|
</div>
|
||||||
|
) : null }
|
||||||
|
|
||||||
<ul className="pl-8">
|
<ul className="pl-8">
|
||||||
{item.testResults ? item.testResults.map((result) => (
|
{item.testResults ? item.testResults.map((result) => (
|
||||||
|
@ -6,12 +6,12 @@ const StyledWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
|
|
||||||
.variable-name{
|
.variable-name{
|
||||||
width:100px;
|
min-width:180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variable-value {
|
.variable-value {
|
||||||
max-width: 500px;
|
max-width: 600px;
|
||||||
inline-size: 500px;
|
inline-size: 600px;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import forOwn from 'lodash/forOwn';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import { uuid } from 'utils/common';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const VariablesTable = ({ variables }) => {
|
const VariablesTable = ({ variables, collectionVariables }) => {
|
||||||
|
const collectionVars = [];
|
||||||
|
|
||||||
|
forOwn(cloneDeep(collectionVariables), (value, key) => {
|
||||||
|
collectionVars.push({
|
||||||
|
uid: uuid(),
|
||||||
|
name: key,
|
||||||
|
value: value
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<div className="flex flex-col w-full">
|
<div className="flex flex-col w-full">
|
||||||
|
<div className='mb-2 font-medium'>Environment Variables</div>
|
||||||
{(variables && variables.length) ? variables.map((variable) => {
|
{(variables && variables.length) ? variables.map((variable) => {
|
||||||
return (
|
return (
|
||||||
<div key={variable.uid} className="flex">
|
<div key={variable.uid} className="flex">
|
||||||
@ -13,6 +27,16 @@ const VariablesTable = ({ variables }) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}) : null}
|
}) : null}
|
||||||
|
|
||||||
|
<div className='mt-2 font-medium'>Collection Variables</div>
|
||||||
|
{(collectionVars && collectionVars.length) ? collectionVars.map((variable) => {
|
||||||
|
return (
|
||||||
|
<div key={variable.uid} className="flex">
|
||||||
|
<div className='variable-name text-yellow-600 text-right pr-2'>{variable.name}</div>
|
||||||
|
<div className='variable-value pl-2 whitespace-normal text-left flex-grow'>{variable.value}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}) : null}
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
|
@ -34,7 +34,7 @@ const VariablesView = ({collection}) => {
|
|||||||
handleClose={() => setPopOverOpen(false)}
|
handleClose={() => setPopOverOpen(false)}
|
||||||
>
|
>
|
||||||
<div className="px-2 py-1">
|
<div className="px-2 py-1">
|
||||||
{(enabledVariables && enabledVariables.length) ? <VariablesTable variables={enabledVariables} /> : 'No variables found'}
|
{(enabledVariables && enabledVariables.length) ? <VariablesTable variables={enabledVariables} collectionVariables={collection.collectionVariables}/> : 'No variables found'}
|
||||||
</div>
|
</div>
|
||||||
</PopOver>
|
</PopOver>
|
||||||
)}
|
)}
|
||||||
|
@ -8,11 +8,13 @@ import { useSelector } from 'react-redux';
|
|||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
import 'codemirror/theme/material.css';
|
import 'codemirror/theme/material.css';
|
||||||
import 'codemirror/theme/monokai.css';
|
import 'codemirror/theme/monokai.css';
|
||||||
|
import 'codemirror/addon/scroll/simplescrollbars.css';
|
||||||
|
|
||||||
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
|
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
|
||||||
if (!SERVER_RENDERED) {
|
if (!SERVER_RENDERED) {
|
||||||
require('codemirror/mode/javascript/javascript');
|
require('codemirror/mode/javascript/javascript');
|
||||||
require('codemirror/mode/xml/xml');
|
require('codemirror/mode/xml/xml');
|
||||||
|
require('codemirror/addon/scroll/simplescrollbars');
|
||||||
require('codemirror/addon/edit/matchbrackets');
|
require('codemirror/addon/edit/matchbrackets');
|
||||||
require('codemirror/addon/fold/brace-fold');
|
require('codemirror/addon/fold/brace-fold');
|
||||||
require('codemirror/addon/fold/foldgutter');
|
require('codemirror/addon/fold/foldgutter');
|
||||||
|
@ -82,8 +82,13 @@ const useCollectionTreeSync = () => {
|
|||||||
toast.success('Collection is already opened');
|
toast.success('Collection is already opened');
|
||||||
};
|
};
|
||||||
|
|
||||||
const _displayError = (message) => {
|
const _displayError = (error) => {
|
||||||
toast.error(message || 'Something went wrong!');
|
if(typeof error === "string") {
|
||||||
|
return toast.error(error || 'Something went wrong!');
|
||||||
|
}
|
||||||
|
if(typeof message === "object") {
|
||||||
|
return toast.error(error.message || 'Something went wrong!');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _httpRequestSent = (val) => {
|
const _httpRequestSent = (val) => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import trim from 'lodash/trim';
|
import trim from 'lodash/trim';
|
||||||
|
import get from 'lodash/get';
|
||||||
import filter from 'lodash/filter';
|
import filter from 'lodash/filter';
|
||||||
import { uuid } from 'utils/common';
|
import { uuid } from 'utils/common';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
@ -888,7 +888,7 @@ export const collectionsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
runFolderEvent: (state, action) => {
|
runFolderEvent: (state, action) => {
|
||||||
const { collectionUid, folderUid, itemUid, type } = action.payload;
|
const { collectionUid, folderUid, itemUid, type, error } = action.payload;
|
||||||
const collection = findCollectionByUid(state.collections, collectionUid);
|
const collection = findCollectionByUid(state.collections, collectionUid);
|
||||||
|
|
||||||
if (collection) {
|
if (collection) {
|
||||||
@ -920,6 +920,13 @@ export const collectionsSlice = createSlice({
|
|||||||
const item = collection.runnerResult.items.find((i) => i.uid === request.uid);
|
const item = collection.runnerResult.items.find((i) => i.uid === request.uid);
|
||||||
item.testResults = action.payload.testResults;
|
item.testResults = action.payload.testResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(type === 'error') {
|
||||||
|
const item = collection.runnerResult.items.find((i) => i.uid === request.uid);
|
||||||
|
item.error = action.payload.error;
|
||||||
|
item.responseReceived = action.payload.responseReceived;
|
||||||
|
item.status = "error";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,9 @@ const openCollection = async (win, watcher, collectionPath, options = {}) => {
|
|||||||
ipcMain.emit('main:collection-opened', win, collectionPath, uid);
|
ipcMain.emit('main:collection-opened', win, collectionPath, uid);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if(!options.dontSendDisplayErrors) {
|
if(!options.dontSendDisplayErrors) {
|
||||||
win.webContents.send('main:display-error', err.message || 'An error occured while opening the local collection');
|
win.webContents.send('main:display-error', {
|
||||||
|
error: err.message || 'An error occured while opening the local collection'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -257,6 +257,9 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
|||||||
itemUid
|
itemUid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let timeStart;
|
||||||
|
let timeEnd;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mainWindow.webContents.send('main:run-folder-event', {
|
mainWindow.webContents.send('main:run-folder-event', {
|
||||||
type: 'request-queued',
|
type: 'request-queued',
|
||||||
@ -305,9 +308,9 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
|||||||
...eventData
|
...eventData
|
||||||
});
|
});
|
||||||
|
|
||||||
const timeStart = Date.now();
|
timeStart = Date.now();
|
||||||
const response = await axios(request);
|
const response = await axios(request);
|
||||||
const timeEnd = Date.now();
|
timeEnd = Date.now();
|
||||||
|
|
||||||
if(request.script && request.script.length) {
|
if(request.script && request.script.length) {
|
||||||
let script = request.script + '\n if (typeof onResponse === "function") {onResponse(__brunoResponse);}';
|
let script = request.script + '\n if (typeof onResponse === "function") {onResponse(__brunoResponse);}';
|
||||||
@ -346,9 +349,27 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
let responseReceived = {};
|
||||||
|
let duration = 0;
|
||||||
|
|
||||||
|
if(timeStart && timeEnd) {
|
||||||
|
duration = timeEnd - timeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error && error.response) {
|
||||||
|
responseReceived = {
|
||||||
|
status: error.response.status,
|
||||||
|
statusText: error.response.statusText,
|
||||||
|
headers: Object.entries(error.response.headers),
|
||||||
|
duration: duration,
|
||||||
|
size: error.response.headers['content-length'] || getSize(error.response.data),
|
||||||
|
data: error.response.data,
|
||||||
|
}
|
||||||
|
}
|
||||||
mainWindow.webContents.send('main:run-folder-event', {
|
mainWindow.webContents.send('main:run-folder-event', {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
error,
|
error: error ? error.message : 'An error occurred while running the request',
|
||||||
|
responseReceived: responseReceived,
|
||||||
...eventData
|
...eventData
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -356,8 +377,7 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
mainWindow.webContents.send('main:run-folder-event', {
|
mainWindow.webContents.send('main:run-folder-event', {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
error,
|
error
|
||||||
...eventData
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -27,35 +27,27 @@ const interpolateVars = (request, envVars = {}, collectionVariables ={}) => {
|
|||||||
request.headers[key] = interpolate(value);
|
request.headers[key] = interpolate(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(request.headers["content-type"] === "application/json") {
|
||||||
|
if(typeof request.data === "object") {
|
||||||
|
try {
|
||||||
|
let parsed = JSON.stringify(request.data);
|
||||||
|
parsed = interpolate(parsed);
|
||||||
|
request.data = JSON.parse(parsed);
|
||||||
|
} catch (err) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof request.data === "string") {
|
||||||
|
if(request.data.length) {
|
||||||
|
request.data = interpolate(request.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
each(request.params, (param) => {
|
each(request.params, (param) => {
|
||||||
param.value = interpolate(param.value);
|
param.value = interpolate(param.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Todo: Make interpolation work with body mode json
|
|
||||||
const mode = get(request, 'body.mode');
|
|
||||||
switch (mode) {
|
|
||||||
case 'text': {
|
|
||||||
request.body.text = interpolate(request.body.text);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'xml': {
|
|
||||||
request.body.text = interpolate(request.body.text);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'multipartForm': {
|
|
||||||
each(request.body.multipartForm, (param) => {
|
|
||||||
param.value = interpolate(param.value);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'formUrlEncoded': {
|
|
||||||
each(request.body.formUrlEncoded, (param) => {
|
|
||||||
param.value = interpolate(param.value);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user