mirror of
https://github.com/usebruno/bruno.git
synced 2024-12-22 06:31:18 +01:00
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};
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
|
||||
background: #d2d7db;
|
||||
}
|
||||
|
||||
textarea.cm-editor {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// Todo: dark mode temporary fix
|
||||
// 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 {
|
||||
color: #9cdcfe !important;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ export default class CodeEditor extends React.Component {
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||
readOnly: this.props.readOnly,
|
||||
scrollbarStyle: "overlay",
|
||||
theme: this.props.theme === 'dark' ? 'monokai' : 'default',
|
||||
extraKeys: {
|
||||
'Cmd-Enter': () => {
|
||||
|
@ -6,6 +6,9 @@ const Wrapper = styled.div`
|
||||
color: ${(props) => props.theme.textLink};
|
||||
}
|
||||
}
|
||||
.danger {
|
||||
color: ${(props) => props.theme.colors.text.danger};
|
||||
}
|
||||
|
||||
.test-summary {
|
||||
color: ${(props) => props.theme.tabs.active.border};
|
||||
|
@ -32,17 +32,19 @@ export default function RunnerResults({collection}) {
|
||||
item.pathname = info.pathname;
|
||||
item.relativePath = getRelativePath(collection.pathname, info.pathname);
|
||||
|
||||
if(item.testResults) {
|
||||
const failed = item.testResults.filter((result) => result.status === 'fail');
|
||||
if(item.status !== "error") {
|
||||
if(item.testResults) {
|
||||
const failed = item.testResults.filter((result) => result.status === 'fail');
|
||||
|
||||
item.testStatus = failed.length ? 'fail' : 'pass';
|
||||
} else {
|
||||
item.testStatus = 'pass';
|
||||
item.testStatus = failed.length ? 'fail' : 'pass';
|
||||
} else {
|
||||
item.testStatus = 'pass';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const passedRequests = items.filter((item) => item.testStatus === 'pass');
|
||||
const failedRequests = items.filter((item) => item.testStatus === 'fail');
|
||||
const passedRequests = items.filter((item) => item.status !== "error" && item.testStatus === 'pass');
|
||||
const failedRequests = items.filter((item) => item.status !== "error" && item.testStatus === 'fail');
|
||||
|
||||
return (
|
||||
<StyledWrapper className='px-4'>
|
||||
@ -61,14 +63,14 @@ export default function RunnerResults({collection}) {
|
||||
<div className="item-path mt-2">
|
||||
<div className="flex items-center">
|
||||
<span>
|
||||
{item.testStatus === 'pass' ? (
|
||||
{item.status !== "error" && item.testStatus === 'pass' ? (
|
||||
<IconCircleCheck className="test-success" size={20} strokeWidth={1.5}/>
|
||||
) : (
|
||||
<IconCircleX className="test-failure" size={20} strokeWidth={1.5}/>
|
||||
)}
|
||||
</span>
|
||||
<span className='mr-1 ml-2'>{item.relativePath}</span>
|
||||
{item.status !== "completed" ? (
|
||||
<span className={`mr-1 ml-2 ${(item.status == "error" || item.testStatus == 'fail') ? 'danger' : ''}`}>{item.relativePath}</span>
|
||||
{(item.status !== "error" && item.status !== "completed") ? (
|
||||
<IconRefresh className="animate-spin ml-1" size={18} strokeWidth={1.5}/>
|
||||
) : (
|
||||
<span className='text-xs link cursor-pointer' onClick={() => setSelectedItem(item)}>
|
||||
@ -81,6 +83,11 @@ export default function RunnerResults({collection}) {
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{item.status == "error" ? (
|
||||
<div className="error-message pl-8 pt-2 text-xs">
|
||||
{item.error}
|
||||
</div>
|
||||
) : null }
|
||||
|
||||
<ul className="pl-8">
|
||||
{item.testResults ? item.testResults.map((result) => (
|
||||
|
@ -6,12 +6,12 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.variable-name{
|
||||
width:100px;
|
||||
min-width:180px;
|
||||
}
|
||||
|
||||
.variable-value {
|
||||
max-width: 500px;
|
||||
inline-size: 500px;
|
||||
max-width: 600px;
|
||||
inline-size: 600px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
`
|
||||
|
@ -1,10 +1,24 @@
|
||||
import React from 'react';
|
||||
import forOwn from 'lodash/forOwn';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import { uuid } from 'utils/common';
|
||||
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 (
|
||||
<StyledWrapper>
|
||||
<div className="flex flex-col w-full">
|
||||
<div className='mb-2 font-medium'>Environment Variables</div>
|
||||
{(variables && variables.length) ? variables.map((variable) => {
|
||||
return (
|
||||
<div key={variable.uid} className="flex">
|
||||
@ -13,6 +27,16 @@ const VariablesTable = ({ variables }) => {
|
||||
</div>
|
||||
);
|
||||
}) : 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>
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
@ -34,7 +34,7 @@ const VariablesView = ({collection}) => {
|
||||
handleClose={() => setPopOverOpen(false)}
|
||||
>
|
||||
<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>
|
||||
</PopOver>
|
||||
)}
|
||||
|
@ -8,11 +8,13 @@ import { useSelector } from 'react-redux';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import 'codemirror/theme/material.css';
|
||||
import 'codemirror/theme/monokai.css';
|
||||
import 'codemirror/addon/scroll/simplescrollbars.css';
|
||||
|
||||
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
|
||||
if (!SERVER_RENDERED) {
|
||||
require('codemirror/mode/javascript/javascript');
|
||||
require('codemirror/mode/xml/xml');
|
||||
require('codemirror/addon/scroll/simplescrollbars');
|
||||
require('codemirror/addon/edit/matchbrackets');
|
||||
require('codemirror/addon/fold/brace-fold');
|
||||
require('codemirror/addon/fold/foldgutter');
|
||||
|
@ -82,8 +82,13 @@ const useCollectionTreeSync = () => {
|
||||
toast.success('Collection is already opened');
|
||||
};
|
||||
|
||||
const _displayError = (message) => {
|
||||
toast.error(message || 'Something went wrong!');
|
||||
const _displayError = (error) => {
|
||||
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) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import path from 'path';
|
||||
import toast from 'react-hot-toast';
|
||||
import trim from 'lodash/trim';
|
||||
import get from 'lodash/get';
|
||||
import filter from 'lodash/filter';
|
||||
import { uuid } from 'utils/common';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
@ -888,7 +888,7 @@ export const collectionsSlice = createSlice({
|
||||
}
|
||||
},
|
||||
runFolderEvent: (state, action) => {
|
||||
const { collectionUid, folderUid, itemUid, type } = action.payload;
|
||||
const { collectionUid, folderUid, itemUid, type, error } = action.payload;
|
||||
const collection = findCollectionByUid(state.collections, collectionUid);
|
||||
|
||||
if (collection) {
|
||||
@ -920,6 +920,13 @@ export const collectionsSlice = createSlice({
|
||||
const item = collection.runnerResult.items.find((i) => i.uid === request.uid);
|
||||
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);
|
||||
} catch(err) {
|
||||
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 {
|
||||
|
@ -257,6 +257,9 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
itemUid
|
||||
};
|
||||
|
||||
let timeStart;
|
||||
let timeEnd;
|
||||
|
||||
try {
|
||||
mainWindow.webContents.send('main:run-folder-event', {
|
||||
type: 'request-queued',
|
||||
@ -305,9 +308,9 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
...eventData
|
||||
});
|
||||
|
||||
const timeStart = Date.now();
|
||||
timeStart = Date.now();
|
||||
const response = await axios(request);
|
||||
const timeEnd = Date.now();
|
||||
timeEnd = Date.now();
|
||||
|
||||
if(request.script && request.script.length) {
|
||||
let script = request.script + '\n if (typeof onResponse === "function") {onResponse(__brunoResponse);}';
|
||||
@ -346,9 +349,27 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
}
|
||||
});
|
||||
} 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', {
|
||||
type: 'error',
|
||||
error,
|
||||
error: error ? error.message : 'An error occurred while running the request',
|
||||
responseReceived: responseReceived,
|
||||
...eventData
|
||||
});
|
||||
}
|
||||
@ -356,8 +377,7 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
} catch (error) {
|
||||
mainWindow.webContents.send('main:run-folder-event', {
|
||||
type: 'error',
|
||||
error,
|
||||
...eventData
|
||||
error
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -27,35 +27,27 @@ const interpolateVars = (request, envVars = {}, collectionVariables ={}) => {
|
||||
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) => {
|
||||
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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user