From abb0a7b0db91e902ddf42c3690f9e69bf7cedf9e Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Wed, 15 Jan 2025 13:08:44 +0530 Subject: [PATCH 01/18] chore: version bump --- package-lock.json | 2 +- packages/bruno-app/src/providers/App/useTelemetry.js | 2 +- packages/bruno-electron/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d7ee4064d..98b220863 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24199,7 +24199,7 @@ }, "packages/bruno-electron": { "name": "bruno", - "version": "v1.36.0", + "version": "v1.38.1", "dependencies": { "@aws-sdk/credential-providers": "3.658.1", "@usebruno/common": "0.1.0", diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js index f89b1343e..3692ba734 100644 --- a/packages/bruno-app/src/providers/App/useTelemetry.js +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -58,7 +58,7 @@ const trackStart = () => { event: 'start', properties: { os: platformLib.os.family, - version: '1.36.0' + version: 'v1.38.1' } }); }; diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index c7a6b369a..16a032b3a 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v1.36.0", + "version": "v1.38.1", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com", From 27ef28ae9b6c23dbc2828021d4e6551c802027d0 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Wed, 15 Jan 2025 13:15:21 +0530 Subject: [PATCH 02/18] chore: version bump --- packages/bruno-app/src/providers/App/useTelemetry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js index 3692ba734..6b64e1279 100644 --- a/packages/bruno-app/src/providers/App/useTelemetry.js +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -58,7 +58,7 @@ const trackStart = () => { event: 'start', properties: { os: platformLib.os.family, - version: 'v1.38.1' + version: '1.38.1' } }); }; From dbf1cad124211945638c264c50a0ca86cdcbe735 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Wed, 15 Jan 2025 19:57:06 +0530 Subject: [PATCH 03/18] fix: remove `removeQuotes()` --- packages/bruno-js/src/sandbox/quickjs/index.js | 18 ++++++++++-------- packages/bruno-js/src/utils.js | 14 ++++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/bruno-js/src/sandbox/quickjs/index.js b/packages/bruno-js/src/sandbox/quickjs/index.js index d5fe5e8f3..35a4ee28b 100644 --- a/packages/bruno-js/src/sandbox/quickjs/index.js +++ b/packages/bruno-js/src/sandbox/quickjs/index.js @@ -22,12 +22,12 @@ const toNumber = (value) => { return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value); }; -const removeQuotes = (str) => { - if ((str.startsWith('"') && str.endsWith('"')) || (str.startsWith("'") && str.endsWith("'"))) { - return str.slice(1, -1); - } - return str; -}; +// const removeQuotes = (str) => { +// if ((str.startsWith('"') && str.endsWith('"')) || (str.startsWith("'") && str.endsWith("'"))) { +// return str.slice(1, -1); +// } +// return str; +// }; const executeQuickJsVm = ({ script: externalScript, context: externalContext, scriptType = 'template-literal' }) => { if (!externalScript?.length || typeof externalScript !== 'string') { @@ -44,7 +44,8 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc if (externalScript === 'null') return null; if (externalScript === 'undefined') return undefined; - externalScript = removeQuotes(externalScript); + // This is commented out as part of the fix for #3758 + // externalScript = removeQuotes(externalScript); const vm = QuickJSSyncContext; @@ -94,7 +95,8 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external if (externalScript === 'null') return null; if (externalScript === 'undefined') return undefined; - externalScript = removeQuotes(externalScript); + // This is commented out as part of the fix for #3758 + // externalScript = removeQuotes(externalScript); try { const module = await newQuickJSWASMModule(); diff --git a/packages/bruno-js/src/utils.js b/packages/bruno-js/src/utils.js index 55b454d02..32fa9d9be 100644 --- a/packages/bruno-js/src/utils.js +++ b/packages/bruno-js/src/utils.js @@ -85,13 +85,15 @@ const evaluateJsTemplateLiteral = (templateLiteral, context) => { return undefined; } - if (templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) { - return templateLiteral.slice(1, -1); - } + // This is commented out as part of the fix for #3758 + // if (templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) { + // return templateLiteral.slice(1, -1); + // } - if (templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) { - return templateLiteral.slice(1, -1); - } + // This is commented out as part of the fix for #3758 + // if (templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) { + // return templateLiteral.slice(1, -1); + // } if (!isNaN(templateLiteral)) { const number = Number(templateLiteral); From cf2cb0736ed5d77c1505a04d13c965c0be8aef47 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Wed, 15 Jan 2025 20:42:02 +0530 Subject: [PATCH 04/18] fix: remove commented-out `removeQuotes()` function --- packages/bruno-js/src/sandbox/quickjs/index.js | 10 ---------- packages/bruno-js/src/utils.js | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/packages/bruno-js/src/sandbox/quickjs/index.js b/packages/bruno-js/src/sandbox/quickjs/index.js index 35a4ee28b..58ccd885d 100644 --- a/packages/bruno-js/src/sandbox/quickjs/index.js +++ b/packages/bruno-js/src/sandbox/quickjs/index.js @@ -22,12 +22,6 @@ const toNumber = (value) => { return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value); }; -// const removeQuotes = (str) => { -// if ((str.startsWith('"') && str.endsWith('"')) || (str.startsWith("'") && str.endsWith("'"))) { -// return str.slice(1, -1); -// } -// return str; -// }; const executeQuickJsVm = ({ script: externalScript, context: externalContext, scriptType = 'template-literal' }) => { if (!externalScript?.length || typeof externalScript !== 'string') { @@ -44,8 +38,6 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc if (externalScript === 'null') return null; if (externalScript === 'undefined') return undefined; - // This is commented out as part of the fix for #3758 - // externalScript = removeQuotes(externalScript); const vm = QuickJSSyncContext; @@ -95,8 +87,6 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external if (externalScript === 'null') return null; if (externalScript === 'undefined') return undefined; - // This is commented out as part of the fix for #3758 - // externalScript = removeQuotes(externalScript); try { const module = await newQuickJSWASMModule(); diff --git a/packages/bruno-js/src/utils.js b/packages/bruno-js/src/utils.js index 32fa9d9be..6b5ecacb5 100644 --- a/packages/bruno-js/src/utils.js +++ b/packages/bruno-js/src/utils.js @@ -85,16 +85,6 @@ const evaluateJsTemplateLiteral = (templateLiteral, context) => { return undefined; } - // This is commented out as part of the fix for #3758 - // if (templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) { - // return templateLiteral.slice(1, -1); - // } - - // This is commented out as part of the fix for #3758 - // if (templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) { - // return templateLiteral.slice(1, -1); - // } - if (!isNaN(templateLiteral)) { const number = Number(templateLiteral); // Check if the number is too high. Too high number might get altered, see #1000 From a73d2a02cfe420ba054fa7716624ee13952a4393 Mon Sep 17 00:00:00 2001 From: naman-bruno Date: Thu, 16 Jan 2025 19:59:14 +0530 Subject: [PATCH 05/18] fix: Request vars displayed in red color in body even if they are valid (#3812) * fix: Request vars displayed in red color in body * chore: removing index import --------- Co-authored-by: Anoop M D --- packages/bruno-app/src/components/CodeEditor/index.js | 6 +++--- .../src/components/RequestPane/RequestBody/index.js | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 168a3b02b..398007a4a 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -7,12 +7,12 @@ import React from 'react'; import { isEqual, escapeRegExp } from 'lodash'; -import { getEnvironmentVariables } from 'utils/collections'; import { defineCodeMirrorBrunoVariablesMode } from 'utils/common/codemirror'; import StyledWrapper from './StyledWrapper'; import * as jsonlint from '@prantlf/jsonlint'; import { JSHINT } from 'jshint'; import stripJsonComments from 'strip-json-comments'; +import { getAllVariables } from 'utils/collections'; let CodeMirror; const SERVER_RENDERED = typeof window === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true; @@ -293,7 +293,7 @@ export default class CodeEditor extends React.Component { } if (this.editor) { - let variables = getEnvironmentVariables(this.props.collection); + let variables = getAllVariables(this.props.collection, this.props.item); if (!isEqual(variables, this.variables)) { this.addOverlay(); } @@ -333,7 +333,7 @@ export default class CodeEditor extends React.Component { addOverlay = () => { const mode = this.props.mode || 'application/ld+json'; - let variables = getEnvironmentVariables(this.props.collection); + let variables = getAllVariables(this.props.collection, this.props.item); this.variables = variables; defineCodeMirrorBrunoVariablesMode(variables, mode); diff --git a/packages/bruno-app/src/components/RequestPane/RequestBody/index.js b/packages/bruno-app/src/components/RequestPane/RequestBody/index.js index 5fde52ea0..ca60c8662 100644 --- a/packages/bruno-app/src/components/RequestPane/RequestBody/index.js +++ b/packages/bruno-app/src/components/RequestPane/RequestBody/index.js @@ -48,6 +48,7 @@ const RequestBody = ({ item, collection }) => { Date: Thu, 16 Jan 2025 20:01:48 +0530 Subject: [PATCH 06/18] fix: body formurl value disappearing (#3803) --- .../src/components/MultiLineEditor/StyledWrapper.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/MultiLineEditor/StyledWrapper.js b/packages/bruno-app/src/components/MultiLineEditor/StyledWrapper.js index 2473463db..b449ffce6 100644 --- a/packages/bruno-app/src/components/MultiLineEditor/StyledWrapper.js +++ b/packages/bruno-app/src/components/MultiLineEditor/StyledWrapper.js @@ -19,9 +19,8 @@ const StyledWrapper = styled.div` opacity: 0.5; } - .CodeMirror-scroll { - overflow: hidden !important; - ${'' /* padding-bottom: 50px !important; */} + .CodeMirror-scroll { + overflow: visible !important; position: relative; display: block; margin: 0px; From 5b04e0c189957f0ecc5117d0e1a94a42d1897bf3 Mon Sep 17 00:00:00 2001 From: pooja-bruno Date: Thu, 16 Jan 2025 20:04:34 +0530 Subject: [PATCH 07/18] fix: renaming first collection env (#3735) --- .../EnvironmentSettings/EnvironmentList/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js index 079b57891..48f341f26 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js @@ -9,6 +9,7 @@ import ManageSecrets from '../ManageSecrets'; import StyledWrapper from './StyledWrapper'; import ConfirmSwitchEnv from './ConfirmSwitchEnv'; import ToolHint from 'components/ToolHint'; +import { isEqual } from 'lodash'; const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collection, isModified, setIsModified }) => { const { environments } = collection; @@ -24,6 +25,11 @@ const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collecti useEffect(() => { if (selectedEnvironment) { + const _selectedEnvironment = environments?.find(env => env?.uid === selectedEnvironment?.uid); + const hasSelectedEnvironmentChanged = !isEqual(selectedEnvironment, _selectedEnvironment); + if (hasSelectedEnvironmentChanged) { + setSelectedEnvironment(_selectedEnvironment); + } setOriginalEnvironmentVariables(selectedEnvironment.variables); return; } From 472b5452f73a1ffbc9af8f03cec749a5bfabd6ed Mon Sep 17 00:00:00 2001 From: naman-bruno Date: Thu, 16 Jan 2025 20:06:53 +0530 Subject: [PATCH 08/18] =?UTF-8?q?Allow=20rearrangement=20of=20table=20item?= =?UTF-8?q?s=20in=20params,=20body,=20vars,=20headers,=20etc=E2=80=A6=20(#?= =?UTF-8?q?3801)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow rearrangement of table items in params, body, vars, headers, and assert * updated drag function name --- .../Assertions/AssertionRow/index.js | 17 +- .../RequestPane/Assertions/StyledWrapper.js | 15 +- .../RequestPane/Assertions/index.js | 56 +++-- .../FormUrlEncodedParams/StyledWrapper.js | 8 - .../RequestPane/FormUrlEncodedParams/index.js | 138 ++++++------ .../MultipartFormParams/StyledWrapper.js | 16 -- .../RequestPane/MultipartFormParams/index.js | 196 ++++++++++-------- .../RequestPane/QueryParams/index.js | 4 +- .../RequestHeaders/StyledWrapper.js | 8 - .../RequestPane/RequestHeaders/index.js | 41 ++-- .../Vars/VarsTable/StyledWrapper.js | 11 +- .../RequestPane/Vars/VarsTable/index.js | 64 +++--- .../ReduxStore/slices/collections/index.js | 124 +++++++++++ 13 files changed, 417 insertions(+), 281 deletions(-) diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js index ea9484780..e56e3c398 100644 --- a/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js @@ -146,19 +146,8 @@ const AssertionRow = ({ const { operator, value } = parseAssertionOperator(assertion.value); return ( - - - handleAssertionChange(e, assertion, 'name')} - /> - + <> + - + ); }; diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js index 14e21e1c6..efb860893 100644 --- a/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js @@ -4,6 +4,7 @@ const Wrapper = styled.div` table { width: 100%; border-collapse: collapse; + font-weight: 600; table-layout: fixed; thead, @@ -15,24 +16,15 @@ const Wrapper = styled.div` color: ${(props) => props.theme.table.thead.color}; font-size: 0.8125rem; user-select: none; - font-weight: 600; } td { padding: 6px 10px; - - &:nth-child(2) { - width: 130px; } - &:nth-child(4) { - width: 70px; - } - - select { + select { background-color: transparent; } } - } .btn-add-assertion { font-size: 0.8125rem; @@ -42,7 +34,8 @@ const Wrapper = styled.div` width: 100%; border: solid 1px transparent; outline: none !important; - background-color: inherit; + color: ${(props) => props.theme.table.input.color}; + background: transparent; &:focus { outline: none !important; diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/index.js index 1805a632e..7d173f3c5 100644 --- a/packages/bruno-app/src/components/RequestPane/Assertions/index.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/index.js @@ -6,6 +6,9 @@ import { addAssertion, updateAssertion, deleteAssertion } from 'providers/ReduxS import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import AssertionRow from './AssertionRow'; import StyledWrapper from './StyledWrapper'; +import Table from 'components/Table/index'; +import ReorderTable from 'components/ReorderTable/index'; +import { moveAssertion } from 'providers/ReduxStore/slices/collections/index'; const Assertions = ({ item, collection }) => { const dispatch = useDispatch(); @@ -57,21 +60,43 @@ const Assertions = ({ item, collection }) => { ); }; + const handleAssertionDrag = ({ updateReorderedItem }) => { + dispatch( + moveAssertion({ + collectionUid: collection.uid, + itemUid: item.uid, + updateReorderedItem + }) + ); + }; + return ( - - - - - - - - - - +
ExprOperatorValue
+ {assertions && assertions.length ? assertions.map((assertion) => { - return ( + return ( + + { onSave={onSave} handleRun={handleRun} /> - ); - }) + + ); + }) : null} - -
+ handleAssertionChange(e, assertion, 'name')} + /> +
+ + diff --git a/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/StyledWrapper.js index f04a30be0..517415935 100644 --- a/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/StyledWrapper.js @@ -19,16 +19,8 @@ const Wrapper = styled.div` } td { padding: 6px 10px; - - &:nth-child(1) { - width: 30%; - } - - &:nth-child(3) { - width: 70px; } } - } .btn-add-param { font-size: 0.8125rem; diff --git a/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js b/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js index 22de4735b..c8eeda531 100644 --- a/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js +++ b/packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js @@ -7,11 +7,14 @@ import { useTheme } from 'providers/Theme'; import { addFormUrlEncodedParam, updateFormUrlEncodedParam, - deleteFormUrlEncodedParam + deleteFormUrlEncodedParam, + moveFormUrlEncodedParam } from 'providers/ReduxStore/slices/collections'; import MultiLineEditor from 'components/MultiLineEditor'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; +import ReorderTable from 'components/ReorderTable/index'; +import Table from 'components/Table/index'; const FormUrlEncodedParams = ({ item, collection }) => { const dispatch = useDispatch(); @@ -64,75 +67,84 @@ const FormUrlEncodedParams = ({ item, collection }) => { ); }; + const handleParamDrag = ({ updateReorderedItem }) => { + dispatch( + moveFormUrlEncodedParam({ + collectionUid: collection.uid, + itemUid: item.uid, + updateReorderedItem + }) + ); + }; + return ( - - - - - - - - - +
KeyValue
+ {params && params.length ? params.map((param, index) => { - return ( - - + + + - - - - ); - }) + + + + + ); + }) : null} - -
+ return ( +
+ handleParamChange(e, param, 'name')} + /> + + + handleParamChange( + { + target: { + value: newValue + } + }, + param, + 'value' + ) + } + allowNewlines={true} + onRun={handleRun} + collection={collection} + item={item} + /> + +
handleParamChange(e, param, 'name')} + type="checkbox" + checked={param.enabled} + tabIndex="-1" + className="mr-3 mousetrap" + onChange={(e) => handleParamChange(e, param, 'enabled')} /> -
- - handleParamChange( - { - target: { - value: newValue - } - }, - param, - 'value' - ) - } - allowNewlines={true} - onRun={handleRun} - collection={collection} - item={item} - /> - -
- handleParamChange(e, param, 'enabled')} - /> - -
-
+ + diff --git a/packages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js index 49c45f21d..f7b6e5d13 100644 --- a/packages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js @@ -19,23 +19,7 @@ const Wrapper = styled.div` } td { padding: 6px 10px; - - &:nth-child(1) { - width: 30%; } - - &:nth-child(2) { - width: 45%; - } - - &:nth-child(3) { - width: 25%; - } - - &:nth-child(4) { - width: 70px; - } - } } .btn-add-param { diff --git a/packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js b/packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js index af23a645e..790f7d5fa 100644 --- a/packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js +++ b/packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js @@ -7,12 +7,15 @@ import { useTheme } from 'providers/Theme'; import { addMultipartFormParam, updateMultipartFormParam, - deleteMultipartFormParam + deleteMultipartFormParam, + moveMultipartFormParam } from 'providers/ReduxStore/slices/collections'; import MultiLineEditor from 'components/MultiLineEditor'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; import FilePickerEditor from 'components/FilePickerEditor'; +import Table from 'components/Table/index'; +import ReorderTable from 'components/ReorderTable/index'; const MultipartFormParams = ({ item, collection }) => { const dispatch = useDispatch(); @@ -82,80 +85,47 @@ const MultipartFormParams = ({ item, collection }) => { ); }; + const handleParamDrag = ({ updateReorderedItem }) => { + dispatch( + moveMultipartFormParam({ + collectionUid: collection.uid, + itemUid: item.uid, + updateReorderedItem + }) + ); + }; + return ( - - - - - - - - - - +
KeyValueContent-Type
+ {params && params.length ? params.map((param, index) => { - return ( - - - - + - - - ); - }) + )} + + + + + ); + }) : null} - -
- handleParamChange(e, param, 'name')} - /> - - {param.type === 'file' ? ( - - handleParamChange( - { - target: { - value: newValue - } - }, - param, - 'value' - ) - } - collection={collection} - /> - ) : ( - - handleParamChange( - { - target: { - value: newValue - } - }, - param, - 'value' - ) - } - onRun={handleRun} - allowNewlines={true} - collection={collection} - item={item} - /> - )} - - + + handleParamChange(e, param, 'name')} + /> + + {param.type === 'file' ? ( + handleParamChange( { @@ -164,33 +134,75 @@ const MultipartFormParams = ({ item, collection }) => { } }, param, - 'contentType' + 'value' + ) + } + collection={collection} + /> + ) : ( + + handleParamChange( + { + target: { + value: newValue + } + }, + param, + 'value' ) } onRun={handleRun} + allowNewlines={true} collection={collection} + item={item} /> - -
- handleParamChange(e, param, 'enabled')} - /> - -
-
+ + handleParamChange( + { + target: { + value: newValue + } + }, + param, + 'contentType' + ) + } + onRun={handleRun} + collection={collection} + /> + +
+ handleParamChange(e, param, 'enabled')} + /> + +
+
+ +
diff --git a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/StyledWrapper.js index efacc8288..c8ec78387 100644 --- a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/StyledWrapper.js @@ -19,16 +19,8 @@ const Wrapper = styled.div` } td { padding: 6px 10px; - - &:nth-child(1) { - width: 30%; - } - - &:nth-child(3) { - width: 70px; } } - } .btn-add-var { font-size: 0.8125rem; @@ -38,7 +30,8 @@ const Wrapper = styled.div` width: 100%; border: solid 1px transparent; outline: none !important; - background-color: inherit; + color: ${(props) => props.theme.table.input.color}; + background: transparent; &:focus { outline: none !important; diff --git a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js index 0f94f35bb..c073135d3 100644 --- a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js +++ b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js @@ -3,13 +3,15 @@ import cloneDeep from 'lodash/cloneDeep'; import { IconTrash } from '@tabler/icons'; import { useDispatch } from 'react-redux'; import { useTheme } from 'providers/Theme'; -import { addVar, updateVar, deleteVar } from 'providers/ReduxStore/slices/collections'; +import { addVar, updateVar, deleteVar, moveVar } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import SingleLineEditor from 'components/SingleLineEditor'; import InfoTip from 'components/InfoTip'; import StyledWrapper from './StyledWrapper'; import toast from 'react-hot-toast'; import { variableNameRegex } from 'utils/common/regex'; +import Table from 'components/Table/index'; +import ReorderTable from 'components/ReorderTable/index'; const VarsTable = ({ item, collection, vars, varType }) => { const dispatch = useDispatch(); @@ -73,35 +75,41 @@ const VarsTable = ({ item, collection, vars, varType }) => { ); }; + const handleVarDrag = ({ updateReorderedItem }) => { + dispatch( + moveVar({ + type: varType, + collectionUid: collection.uid, + itemUid: item.uid, + updateReorderedItem + }) + ); + }; + return ( - - - - - {varType === 'request' ? ( - - ) : ( - - )} - - - - - {vars && vars.length +
Name -
- Value -
-
-
- Expr - -
-
+ Value + + ) : ( +
+ Expr + +
+ ), accessor: 'value', width: '46%' }, + { name: '', accessor: '', width: '14%' } + ]} + > + + {vars && vars.length ? vars.map((_var) => { return ( - - + -
+
{ ); }) : null} -
+ + diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index d4ad48921..7f40600f6 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -694,6 +694,28 @@ export const collectionsSlice = createSlice({ } } }, + moveRequestHeader: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && isItemARequest(item)) { + // Ensure item.draft is a deep clone of item if not already present + if (!item.draft) { + item.draft = cloneDeep(item); + } + + // Extract payload data + const { updateReorderedItem } = action.payload; + const params = item.draft.request.headers; + + item.draft.request.headers = updateReorderedItem.map((uid) => { + return params.find((param) => param.uid === uid); + }); + } + } + }, addFormUrlEncodedParam: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -752,6 +774,28 @@ export const collectionsSlice = createSlice({ } } }, + moveFormUrlEncodedParam: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && isItemARequest(item)) { + // Ensure item.draft is a deep clone of item if not already present + if (!item.draft) { + item.draft = cloneDeep(item); + } + + // Extract payload data + const { updateReorderedItem } = action.payload; + const params = item.draft.request.body.formUrlEncoded; + + item.draft.request.body.formUrlEncoded = updateReorderedItem.map((uid) => { + return params.find((param) => param.uid === uid); + }); + } + } + }, addMultipartFormParam: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -814,6 +858,28 @@ export const collectionsSlice = createSlice({ } } }, + moveMultipartFormParam: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && isItemARequest(item)) { + // Ensure item.draft is a deep clone of item if not already present + if (!item.draft) { + item.draft = cloneDeep(item); + } + + // Extract payload data + const { updateReorderedItem } = action.payload; + const params = item.draft.request.body.multipartForm; + + item.draft.request.body.multipartForm = updateReorderedItem.map((uid) => { + return params.find((param) => param.uid === uid); + }); + } + } + }, updateRequestAuthMode: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -1027,6 +1093,28 @@ export const collectionsSlice = createSlice({ } } }, + moveAssertion: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && isItemARequest(item)) { + // Ensure item.draft is a deep clone of item if not already present + if (!item.draft) { + item.draft = cloneDeep(item); + } + + // Extract payload data + const { updateReorderedItem } = action.payload; + const params = item.draft.request.assertions; + + item.draft.request.assertions = updateReorderedItem.map((uid) => { + return params.find((param) => param.uid === uid); + }); + } + } + }, addVar: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); const type = action.payload.type; @@ -1121,6 +1209,37 @@ export const collectionsSlice = createSlice({ } } }, + moveVar: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + const type = action.payload.type; + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && isItemARequest(item)) { + // Ensure item.draft is a deep clone of item if not already present + if (!item.draft) { + item.draft = cloneDeep(item); + } + + // Extract payload data + const { updateReorderedItem } = action.payload; + if(type == "request"){ + const params = item.draft.request.vars.req; + + item.draft.request.vars.req = updateReorderedItem.map((uid) => { + return params.find((param) => param.uid === uid); + }); + } else if (type === 'response') { + const params = item.draft.request.vars.res; + + item.draft.request.vars.res = updateReorderedItem.map((uid) => { + return params.find((param) => param.uid === uid); + }); + } + } + } + }, updateCollectionAuthMode: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -1801,12 +1920,15 @@ export const { addRequestHeader, updateRequestHeader, deleteRequestHeader, + moveRequestHeader, addFormUrlEncodedParam, updateFormUrlEncodedParam, deleteFormUrlEncodedParam, + moveFormUrlEncodedParam, addMultipartFormParam, updateMultipartFormParam, deleteMultipartFormParam, + moveMultipartFormParam, updateRequestAuthMode, updateRequestBodyMode, updateRequestBody, @@ -1819,9 +1941,11 @@ export const { addAssertion, updateAssertion, deleteAssertion, + moveAssertion, addVar, updateVar, deleteVar, + moveVar, addFolderHeader, updateFolderHeader, deleteFolderHeader, From 5bfcc9b6e760feaba103afc8befeb2172722247f Mon Sep 17 00:00:00 2001 From: naman-bruno Date: Thu, 16 Jan 2025 20:08:30 +0530 Subject: [PATCH 09/18] Fix: Path table is removed when we rearrange items (#3804) --- .../ReduxStore/slices/collections/index.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index 7f40600f6..11f12026f 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -532,11 +532,16 @@ export const collectionsSlice = createSlice({ const { updateReorderedItem } = action.payload; const params = item.draft.request.params; - item.draft.request.params = updateReorderedItem.map((uid) => { - return params.find((param) => param.uid === uid); + const queryParams = params.filter((param) => param.type === 'query'); + const pathParams = params.filter((param) => param.type === 'path'); + + // Reorder only query params based on updateReorderedItem + const reorderedQueryParams = updateReorderedItem.map((uid) => { + return queryParams.find((param) => param.uid === uid); }); - - // update request url + item.draft.request.params = [...reorderedQueryParams, ...pathParams]; + + // Update request URL const parts = splitOnFirst(item.draft.request.url, '?'); const query = stringifyQueryParams(filter(item.draft.request.params, (p) => p.enabled && p.type === 'query')); if (query && query.length) { From 2bce9b3716a64eb23847859a2df736a21285a2c0 Mon Sep 17 00:00:00 2001 From: pooja-bruno Date: Thu, 16 Jan 2025 20:09:51 +0530 Subject: [PATCH 10/18] add: document save button for folder and collection settings (#3742) --- .../CollectionSettings/Docs/StyledWrapper.js | 3 -- .../CollectionSettings/Docs/index.js | 29 +++++++++++-------- .../FolderSettings/Documentation/index.js | 27 +++++++++-------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/packages/bruno-app/src/components/CollectionSettings/Docs/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Docs/StyledWrapper.js index f0ffee808..262f068e7 100644 --- a/packages/bruno-app/src/components/CollectionSettings/Docs/StyledWrapper.js +++ b/packages/bruno-app/src/components/CollectionSettings/Docs/StyledWrapper.js @@ -2,9 +2,6 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` div.CodeMirror { - /* todo: find a better way */ - height: calc(100vh - 240px); - .CodeMirror-scroll { padding-bottom: 0px; } diff --git a/packages/bruno-app/src/components/CollectionSettings/Docs/index.js b/packages/bruno-app/src/components/CollectionSettings/Docs/index.js index 18a1aca1d..23dbe9e70 100644 --- a/packages/bruno-app/src/components/CollectionSettings/Docs/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/Docs/index.js @@ -32,22 +32,27 @@ const Docs = ({ collection }) => { const onSave = () => dispatch(saveCollectionRoot(collection.uid)); return ( - -
+ +
{isEditing ? 'Preview' : 'Edit'}
{isEditing ? ( - +
+ + +
) : ( )} diff --git a/packages/bruno-app/src/components/FolderSettings/Documentation/index.js b/packages/bruno-app/src/components/FolderSettings/Documentation/index.js index 81a3ccd01..964afdece 100644 --- a/packages/bruno-app/src/components/FolderSettings/Documentation/index.js +++ b/packages/bruno-app/src/components/FolderSettings/Documentation/index.js @@ -37,22 +37,25 @@ const Documentation = ({ collection, folder }) => { } return ( - -
+ +
{isEditing ? 'Preview' : 'Edit'}
{isEditing ? ( - +
+ + +
) : ( )} From e5d7cd1be907d717c9c643c0cf06d7a1f152ad58 Mon Sep 17 00:00:00 2001 From: Sanjai Kumar <161328623+sanjaikumar-bruno@users.noreply.github.com> Date: Thu, 16 Jan 2025 20:11:49 +0530 Subject: [PATCH 11/18] feat: add rspack dynamic import configuration to rsbuild (#3819) --- packages/bruno-app/rsbuild.config.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/bruno-app/rsbuild.config.mjs b/packages/bruno-app/rsbuild.config.mjs index 704ea4d09..25f5b7ae7 100644 --- a/packages/bruno-app/rsbuild.config.mjs +++ b/packages/bruno-app/rsbuild.config.mjs @@ -24,4 +24,16 @@ export default defineConfig({ html: { title: 'Bruno' }, + tools: { + rspack: { + module: { + parser: { + javascript: { + // This loads the JavaScript contents from a library along with the main JavaScript bundle. + dynamicImportMode: "eager", + }, + }, + }, + }, + } }); From 2df7fd6588e642fb4a019a74c61b5e91c75c60f7 Mon Sep 17 00:00:00 2001 From: Hadi <159121162+Exxetler@users.noreply.github.com> Date: Thu, 16 Jan 2025 21:42:33 +0100 Subject: [PATCH 12/18] Added activate button to environment window. (#1531) Co-authored-by: Anoop M D --- .../EnvironmentVariables/index.js | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index 20ac3ee92..b9fe61eb7 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -3,6 +3,7 @@ import cloneDeep from 'lodash/cloneDeep'; import { IconTrash, IconAlertCircle } from '@tabler/icons'; import { useTheme } from 'providers/Theme'; import { useDispatch } from 'react-redux'; +import { selectEnvironment } from 'providers/ReduxStore/slices/collections/actions'; import SingleLineEditor from 'components/SingleLineEditor'; import StyledWrapper from './StyledWrapper'; import { uuid } from 'utils/common'; @@ -84,6 +85,18 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original formik.setFieldValue(formik.values.length, newVariable, false); }; + const onActivate = () => { + dispatch(selectEnvironment(environment ? environment.uid : null, collection.uid)) + .then(() => { + if (environment) { + toast.success(`Environment changed to ${environment.name}`); + } else { + toast.success(`No Environments are active now`); + } + }) + .catch((err) => console.log(err) && toast.error('An error occurred while selecting the environment')); + }; + const handleRemoveVar = (id) => { formik.setValues(formik.values.filter((variable) => variable.uid !== id)); }; @@ -184,12 +197,19 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
- + + + + + +
); From 3c8cb702f51a229fcef700dbc99c748610c01061 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 17 Jan 2025 02:46:06 +0530 Subject: [PATCH 13/18] feat: added icons to env modal buttons --- .../EnvironmentVariables/index.js | 28 +++++++++---------- .../EnvironmentDetails/index.js | 4 +-- .../EnvironmentList/index.js | 3 +- .../Environments/EnvironmentSettings/index.js | 1 + 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index b9fe61eb7..ab2ea7691 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -1,6 +1,6 @@ import React, { useRef, useEffect } from 'react'; import cloneDeep from 'lodash/cloneDeep'; -import { IconTrash, IconAlertCircle } from '@tabler/icons'; +import { IconTrash, IconAlertCircle, IconDeviceFloppy, IconRefresh, IconCircleCheck } from '@tabler/icons'; import { useTheme } from 'providers/Theme'; import { useDispatch } from 'react-redux'; import { selectEnvironment } from 'providers/ReduxStore/slices/collections/actions'; @@ -14,7 +14,7 @@ import { saveEnvironment } from 'providers/ReduxStore/slices/collections/actions import toast from 'react-hot-toast'; import { Tooltip } from 'react-tooltip'; -const EnvironmentVariables = ({ environment, collection, setIsModified, originalEnvironmentVariables }) => { +const EnvironmentVariables = ({ environment, collection, setIsModified, originalEnvironmentVariables, onClose }) => { const dispatch = useDispatch(); const { storedTheme } = useTheme(); const addButtonRef = useRef(null); @@ -90,6 +90,7 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original .then(() => { if (environment) { toast.success(`Environment changed to ${environment.name}`); + onClose(); } else { toast.success(`No Environments are active now`); } @@ -196,20 +197,19 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
-
- - - - + - - - +
); diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js index f9fca74ec..17c0bbcf0 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js @@ -5,7 +5,7 @@ import DeleteEnvironment from '../../DeleteEnvironment'; import RenameEnvironment from '../../RenameEnvironment'; import EnvironmentVariables from './EnvironmentVariables'; -const EnvironmentDetails = ({ environment, collection, setIsModified }) => { +const EnvironmentDetails = ({ environment, collection, setIsModified, onClose }) => { const [openEditModal, setOpenEditModal] = useState(false); const [openDeleteModal, setOpenDeleteModal] = useState(false); const [openCopyModal, setOpenCopyModal] = useState(false); @@ -38,7 +38,7 @@ const EnvironmentDetails = ({ environment, collection, setIsModified }) => {
- +
); diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js index 48f341f26..278a7f25d 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js @@ -11,7 +11,7 @@ import ConfirmSwitchEnv from './ConfirmSwitchEnv'; import ToolHint from 'components/ToolHint'; import { isEqual } from 'lodash'; -const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collection, isModified, setIsModified }) => { +const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collection, isModified, setIsModified, onClose }) => { const { environments } = collection; const [openCreateModal, setOpenCreateModal] = useState(false); const [openImportModal, setOpenImportModal] = useState(false); @@ -141,6 +141,7 @@ const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collecti collection={collection} setIsModified={setIsModified} originalEnvironmentVariables={originalEnvironmentVariables} + onClose={onClose} />
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js index 3a17e2ecd..81c663caf 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js @@ -72,6 +72,7 @@ const EnvironmentSettings = ({ collection, onClose }) => { collection={collection} isModified={isModified} setIsModified={setIsModified} + onClose={onClose} /> ); From dab4bb6a1cb54045bd678d02d8e9b8a20eabbf4d Mon Sep 17 00:00:00 2001 From: naman-bruno Date: Fri, 17 Jan 2025 13:07:39 +0530 Subject: [PATCH 14/18] fix: hide env dropdown on configure (#3826) --- .../src/components/Environments/EnvironmentSelector/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js index c2dfb3bdf..848048c13 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js @@ -78,7 +78,10 @@ const EnvironmentSelector = ({ collection }) => { No Environment -
+
{ + handleSettingsIconClick(); + dropdownTippyRef.current.hide(); + }}>
From 3e6204e49bb40a77a91c62ad716483c4eef28080 Mon Sep 17 00:00:00 2001 From: naman-bruno Date: Fri, 17 Jan 2025 13:10:16 +0530 Subject: [PATCH 15/18] Fix: Horizontal Rules missing in markdown docs preview (#3814) --- packages/bruno-app/src/components/MarkDown/StyledWrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/MarkDown/StyledWrapper.js b/packages/bruno-app/src/components/MarkDown/StyledWrapper.js index 85be8f137..fa1269e14 100644 --- a/packages/bruno-app/src/components/MarkDown/StyledWrapper.js +++ b/packages/bruno-app/src/components/MarkDown/StyledWrapper.js @@ -55,7 +55,7 @@ const StyledMarkdownBodyWrapper = styled.div` height: 1px; padding: 0; margin: 24px 0; - background-color: var(--color-border-default); + background-color: var(--color-sidebar-collection-item-active-indent-border); border: 0; } From 8a71dfc02296e61c461f456ca45cbb9924a2b748 Mon Sep 17 00:00:00 2001 From: naman-bruno Date: Fri, 17 Jan 2025 13:20:53 +0530 Subject: [PATCH 16/18] enhancement: moved collection click area from name to div (#3813) --- .../src/components/Sidebar/Collections/Collection/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js index 61dd8b6ed..3b814a7e5 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js @@ -152,6 +152,8 @@ const Collection = ({ collection, searchText }) => {
{ style={{ width: 16, minWidth: 16, color: 'rgb(160 160 160)' }} onClick={handleClick} /> - From 31b28188219f1356bc65ab1785b164a9720df183 Mon Sep 17 00:00:00 2001 From: sanish chirayath Date: Fri, 17 Jan 2025 14:52:06 +0530 Subject: [PATCH 17/18] fix: modal - provide default handleConfirm function and update dependencies in useEffect (#3830) --- packages/bruno-app/src/components/Modal/index.js | 6 +++--- .../src/components/Sidebar/ImportCollection/index.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/bruno-app/src/components/Modal/index.js b/packages/bruno-app/src/components/Modal/index.js index 3ee08cbb9..0b44b928b 100644 --- a/packages/bruno-app/src/components/Modal/index.js +++ b/packages/bruno-app/src/components/Modal/index.js @@ -62,7 +62,7 @@ const Modal = ({ confirmText, cancelText, handleCancel, - handleConfirm, + handleConfirm = () => {}, children, confirmDisabled, hideCancel, @@ -92,7 +92,7 @@ const Modal = ({ }; useFocusTrap(modalRef); - + const closeModal = (args) => { setIsClosing(true); setTimeout(() => handleCancel(args), closeModalFadeTimeout); @@ -103,7 +103,7 @@ const Modal = ({ return () => { document.removeEventListener('keydown', handleKeydown); }; - }, [disableEscapeKey, document]); + }, [disableEscapeKey, document, handleConfirm]); let classes = 'bruno-modal'; if (isClosing) { diff --git a/packages/bruno-app/src/components/Sidebar/ImportCollection/index.js b/packages/bruno-app/src/components/Sidebar/ImportCollection/index.js index 6c4031729..47f0f553e 100644 --- a/packages/bruno-app/src/components/Sidebar/ImportCollection/index.js +++ b/packages/bruno-app/src/components/Sidebar/ImportCollection/index.js @@ -68,7 +68,7 @@ const ImportCollection = ({ onClose, handleSubmit }) => { ); }; return ( - +

Select the type of your existing collection :

From d03de2b62217bc439c38ba8f496a0e9e7a4d66c9 Mon Sep 17 00:00:00 2001 From: Bobby Bonestell Date: Fri, 17 Jan 2025 08:03:53 -0700 Subject: [PATCH 18/18] fix: Inherited apikey auth mapping for bruno-cli (#3512) * Added bruno-cli support for mapping inherited apikey auth from collection Co-authored-by: Anoop M D --- .../bruno-cli/src/runner/prepare-request.js | 22 ++- .../tests/runner/prepare-request.spec.js | 143 +++++++++++++++++- 2 files changed, 161 insertions(+), 4 deletions(-) diff --git a/packages/bruno-cli/src/runner/prepare-request.js b/packages/bruno-cli/src/runner/prepare-request.js index f031ff0aa..11963bd29 100644 --- a/packages/bruno-cli/src/runner/prepare-request.js +++ b/packages/bruno-cli/src/runner/prepare-request.js @@ -36,7 +36,7 @@ const prepareRequest = (item = {}, collection = {}) => { }; const collectionAuth = get(collection, 'root.request.auth'); - if (collectionAuth && request.auth.mode === 'inherit') { + if (collectionAuth && request.auth?.mode === 'inherit') { if (collectionAuth.mode === 'basic') { axiosRequest.auth = { username: get(collectionAuth, 'basic.username'), @@ -47,9 +47,27 @@ const prepareRequest = (item = {}, collection = {}) => { if (collectionAuth.mode === 'bearer') { axiosRequest.headers['Authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`; } + + if (collectionAuth.mode === 'apikey') { + if (collectionAuth.apikey?.placement === 'header') { + axiosRequest.headers[collectionAuth.apikey?.key] = collectionAuth.apikey?.value; + } + + if (collectionAuth.apikey?.placement === 'queryparams') { + if (axiosRequest.url && collectionAuth.apikey?.key) { + try { + const urlObj = new URL(request.url); + urlObj.searchParams.set(collectionAuth.apikey?.key, collectionAuth.apikey?.value); + axiosRequest.url = urlObj.toString(); + } catch (error) { + console.error('Invalid URL:', request.url, error); + } + } + } + } } - if (request.auth) { + if (request.auth && request.auth.mode !== 'inherit') { if (request.auth.mode === 'basic') { axiosRequest.auth = { username: get(request, 'auth.basic.username'), diff --git a/packages/bruno-cli/tests/runner/prepare-request.spec.js b/packages/bruno-cli/tests/runner/prepare-request.spec.js index 37d3e34d3..ffc9986df 100644 --- a/packages/bruno-cli/tests/runner/prepare-request.spec.js +++ b/packages/bruno-cli/tests/runner/prepare-request.spec.js @@ -1,5 +1,4 @@ -const { describe, it, expect } = require('@jest/globals'); - +const { describe, it, expect, beforeEach } = require('@jest/globals'); const prepareRequest = require('../../src/runner/prepare-request'); describe('prepare-request: prepareRequest', () => { @@ -22,4 +21,144 @@ describe('prepare-request: prepareRequest', () => { expect(result.data).toEqual(expected); }); }); + + describe('Properly maps inherited auth from collectionRoot', () => { + // Initialize Test Fixtures + let collection, item; + + beforeEach(() => { + collection = { + name: 'Test Collection', + root: { + request: { + auth: {} + } + } + }; + + item = { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + headers: [], + params: [], + url: 'https://usebruno.com', + auth: { + mode: 'inherit' + }, + script: { + req: 'console.log("Pre Request")', + res: 'console.log("Post Response")' + } + } + }; + }); + + describe('API Key Authentication', () => { + it('If collection auth is apikey in header', () => { + collection.root.request.auth = { + mode: "apikey", + apikey: { + key: "x-api-key", + value: "{{apiKey}}", + placement: "header" + } + }; + + const result = prepareRequest(item, collection); + expect(result.headers).toHaveProperty('x-api-key', '{{apiKey}}'); + }); + + it('If collection auth is apikey in header and request has existing headers', () => { + collection.root.request.auth = { + mode: "apikey", + apikey: { + key: "x-api-key", + value: "{{apiKey}}", + placement: "header" + } + }; + + item.request.headers.push({ name: 'Content-Type', value: 'application/json', enabled: true }); + const result = prepareRequest(item, collection); + expect(result.headers).toHaveProperty('Content-Type', 'application/json'); + expect(result.headers).toHaveProperty('x-api-key', '{{apiKey}}'); + }); + + it('If collection auth is apikey in query parameters', () => { + collection.root.request.auth = { + mode: "apikey", + apikey: { + key: "x-api-key", + value: "{{apiKey}}", + placement: "queryparams" + } + }; + + const urlObj = new URL(item.request.url); + urlObj.searchParams.set(collection.root.request.auth.apikey.key, collection.root.request.auth.apikey.value); + + const expected = urlObj.toString(); + const result = prepareRequest(item, collection); + expect(result.url).toEqual(expected); + }); + }); + + describe('Basic Authentication', () => { + it('If collection auth is basic auth', () => { + collection.root.request.auth = { + mode: 'basic', + basic: { + username: 'testUser', + password: 'testPass123' + } + }; + + const result = prepareRequest(item, collection); + const expected = { username: 'testUser', password: 'testPass123' }; + expect(result.auth).toEqual(expected); + }); + }); + + describe('Bearer Token Authentication', () => { + it('If collection auth is bearer token', () => { + collection.root.request.auth = { + mode: 'bearer', + bearer: { + token: 'token' + } + }; + + const result = prepareRequest(item, collection); + expect(result.headers).toHaveProperty('Authorization', 'Bearer token'); + }); + + it('If collection auth is bearer token and request has existing headers', () => { + collection.root.request.auth = { + mode: 'bearer', + bearer: { + token: 'token' + } + }; + + item.request.headers.push({ name: 'Content-Type', value: 'application/json', enabled: true }); + + const result = prepareRequest(item, collection); + expect(result.headers).toHaveProperty('Authorization', 'Bearer token'); + expect(result.headers).toHaveProperty('Content-Type', 'application/json'); + }); + }); + + describe('No Authentication', () => { + it('If request does not have auth configured', () => { + delete item.request.auth; + let result; + expect(() => { + result = prepareRequest(item, collection); + }).not.toThrow(); + expect(result).toBeDefined(); + }); + }); + }); });