From ede29e29bdcea79f200684f832867cbfe2a6fcd6 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 29 Jun 2024 16:01:21 +0530 Subject: [PATCH] feat: folder level scripts and tests --- package-lock.json | 79 +++--------------- .../FolderSettings/Headers/index.js | 3 + .../FolderSettings/Script/StyledWrapper.js | 13 +++ .../components/FolderSettings/Script/index.js | 81 ++++++++++++++++++ .../FolderSettings/StyledWrapper.js | 46 ++++++++++ .../FolderSettings/Tests/StyledWrapper.js | 5 ++ .../components/FolderSettings/Tests/index.js | 51 ++++++++++++ .../src/components/FolderSettings/index.js | 48 +++++++---- .../RequestTabs/CollectionToolBar/index.js | 2 +- .../RequestTabs/RequestTab/SpecialTab.js | 12 +-- .../RequestTabs/RequestTab/index.js | 6 +- .../src/providers/App/useIpcEvents.js | 8 -- .../ReduxStore/slices/collections/actions.js | 63 +++----------- .../ReduxStore/slices/collections/index.js | 64 +++++++++++--- packages/bruno-electron/src/app/watcher.js | 79 +++++++----------- packages/bruno-electron/src/bru/index.js | 20 +++++ packages/bruno-electron/src/ipc/collection.js | 9 +- .../bruno-electron/src/ipc/network/index.js | 6 +- .../src/ipc/network/prepare-request.js | 83 ++++++++++++++++++- .../bruno-electron/src/utils/collection.js | 57 +++++++++++++ 20 files changed, 511 insertions(+), 224 deletions(-) create mode 100644 packages/bruno-app/src/components/FolderSettings/Script/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/FolderSettings/Script/index.js create mode 100644 packages/bruno-app/src/components/FolderSettings/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/FolderSettings/Tests/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/FolderSettings/Tests/index.js create mode 100644 packages/bruno-electron/src/utils/collection.js diff --git a/package-lock.json b/package-lock.json index 76cfe4c18..f4652d39e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9996,32 +9996,6 @@ "graphql": ">=0.11 <=16" } }, - "node_modules/handlebars": { - "version": "4.7.8", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/minimist": { - "version": "1.2.8", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/har-schema": { "version": "2.0.0", "license": "ISC", @@ -10433,7 +10407,6 @@ }, "node_modules/iconv-lite": { "version": "0.6.3", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -12985,6 +12958,7 @@ }, "node_modules/neo-async": { "version": "2.6.2", + "dev": true, "license": "MIT" }, "node_modules/new-github-issue-url": { @@ -16443,6 +16417,7 @@ }, "node_modules/source-map": { "version": "0.6.1", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -17737,17 +17712,6 @@ "version": "1.0.6", "license": "MIT" }, - "node_modules/uglify-js": { - "version": "3.17.4", - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/underscore": { "version": "1.6.0" }, @@ -18363,10 +18327,6 @@ "dev": true, "license": "MIT" }, - "node_modules/wordwrap": { - "version": "1.0.0", - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "6.2.0", "license": "MIT", @@ -19753,6 +19713,7 @@ "graphql": "^16.6.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", + "iconv-lite": "^0.6.3", "is-valid-path": "^0.1.1", "js-yaml": "^4.1.0", "json-bigint": "^1.0.0", @@ -20806,6 +20767,7 @@ "version": "0.12.0", "license": "MIT", "dependencies": { + "@usebruno/common": "0.1.0", "@usebruno/query": "0.1.0", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", @@ -20815,7 +20777,6 @@ "chai": "^4.3.7", "chai-string": "^1.5.0", "crypto-js": "^4.1.1", - "handlebars": "^4.7.8", "json-query": "^2.2.2", "lodash": "^4.17.21", "moment": "^2.29.4", @@ -25207,6 +25168,7 @@ "@usebruno/js": { "version": "file:packages/bruno-js", "requires": { + "@usebruno/common": "0.1.0", "@usebruno/query": "0.1.0", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", @@ -25216,7 +25178,6 @@ "chai": "^4.3.7", "chai-string": "^1.5.0", "crypto-js": "^4.1.1", - "handlebars": "^4.7.8", "json-query": "^2.2.2", "lodash": "^4.17.21", "moment": "^2.29.4", @@ -26162,6 +26123,7 @@ "graphql": "^16.6.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", + "iconv-lite": "^0.6.3", "is-valid-path": "^0.1.1", "js-yaml": "^4.1.0", "json-bigint": "^1.0.0", @@ -29284,21 +29246,6 @@ "graphql-ws": { "version": "5.12.1" }, - "handlebars": { - "version": "4.7.8", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.8" - } - } - }, "har-schema": { "version": "2.0.0" }, @@ -29543,7 +29490,6 @@ }, "iconv-lite": { "version": "0.6.3", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -31169,7 +31115,8 @@ "version": "0.6.3" }, "neo-async": { - "version": "2.6.2" + "version": "2.6.2", + "dev": true }, "new-github-issue-url": { "version": "0.2.1" @@ -33261,7 +33208,8 @@ } }, "source-map": { - "version": "0.6.1" + "version": "0.6.1", + "dev": true }, "source-map-js": { "version": "1.0.2" @@ -34060,10 +34008,6 @@ "uc.micro": { "version": "1.0.6" }, - "uglify-js": { - "version": "3.17.4", - "optional": true - }, "underscore": { "version": "1.6.0" }, @@ -34458,9 +34402,6 @@ "version": "2.0.1", "dev": true }, - "wordwrap": { - "version": "1.0.0" - }, "wrap-ansi": { "version": "6.2.0", "requires": { diff --git a/packages/bruno-app/src/components/FolderSettings/Headers/index.js b/packages/bruno-app/src/components/FolderSettings/Headers/index.js index a944285e6..550a835c2 100644 --- a/packages/bruno-app/src/components/FolderSettings/Headers/index.js +++ b/packages/bruno-app/src/components/FolderSettings/Headers/index.js @@ -63,6 +63,9 @@ const Headers = ({ collection, folder }) => { return ( +
+ Request headers that will be sent with every request inside this folder. +
diff --git a/packages/bruno-app/src/components/FolderSettings/Script/StyledWrapper.js b/packages/bruno-app/src/components/FolderSettings/Script/StyledWrapper.js new file mode 100644 index 000000000..66ba1ed3d --- /dev/null +++ b/packages/bruno-app/src/components/FolderSettings/Script/StyledWrapper.js @@ -0,0 +1,13 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + div.CodeMirror { + height: inherit; + } + + div.title { + color: var(--color-tab-inactive); + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/FolderSettings/Script/index.js b/packages/bruno-app/src/components/FolderSettings/Script/index.js new file mode 100644 index 000000000..6c51c062d --- /dev/null +++ b/packages/bruno-app/src/components/FolderSettings/Script/index.js @@ -0,0 +1,81 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useDispatch, useSelector } from 'react-redux'; +import CodeEditor from 'components/CodeEditor'; +import { updateFolderRequestScript, updateFolderResponseScript } from 'providers/ReduxStore/slices/collections'; +import { saveFolderRoot } from 'providers/ReduxStore/slices/collections/actions'; +import { useTheme } from 'providers/Theme'; +import StyledWrapper from './StyledWrapper'; + +const Script = ({ collection, folder }) => { + const dispatch = useDispatch(); + const requestScript = get(folder, 'root.request.script.req', ''); + const responseScript = get(folder, 'root.request.script.res', ''); + + const { displayedTheme } = useTheme(); + const preferences = useSelector((state) => state.app.preferences); + + const onRequestScriptEdit = (value) => { + dispatch( + updateFolderRequestScript({ + script: value, + collectionUid: collection.uid, + folderUid: folder.uid + }) + ); + }; + + const onResponseScriptEdit = (value) => { + dispatch( + updateFolderResponseScript({ + script: value, + collectionUid: collection.uid, + folderUid: folder.uid + }) + ); + }; + + const handleSave = () => { + dispatch(saveFolderRoot(collection.uid, folder.uid)); + }; + + return ( + +
+ Pre and post-request scripts that will run before and after any request inside this folder is sent. +
+
+
Pre Request
+ +
+
+
Post Response
+ +
+ +
+ +
+
+ ); +}; + +export default Script; diff --git a/packages/bruno-app/src/components/FolderSettings/StyledWrapper.js b/packages/bruno-app/src/components/FolderSettings/StyledWrapper.js new file mode 100644 index 000000000..b88a31e0d --- /dev/null +++ b/packages/bruno-app/src/components/FolderSettings/StyledWrapper.js @@ -0,0 +1,46 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + max-width: 800px; + + div.tabs { + div.tab { + padding: 6px 0px; + border: none; + border-bottom: solid 2px transparent; + margin-right: 1.25rem; + color: var(--color-tab-inactive); + cursor: pointer; + + &:focus, + &:active, + &:focus-within, + &:focus-visible, + &:target { + outline: none !important; + box-shadow: none !important; + } + + &.active { + color: ${(props) => props.theme.tabs.active.color} !important; + border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; + } + } + } + table { + thead, + td { + border: 1px solid ${(props) => props.theme.table.border}; + + li { + background-color: ${(props) => props.theme.bg} !important; + } + } + } + + .muted { + color: ${(props) => props.theme.colors.text.muted}; + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/FolderSettings/Tests/StyledWrapper.js b/packages/bruno-app/src/components/FolderSettings/Tests/StyledWrapper.js new file mode 100644 index 000000000..ec278887d --- /dev/null +++ b/packages/bruno-app/src/components/FolderSettings/Tests/StyledWrapper.js @@ -0,0 +1,5 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div``; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/FolderSettings/Tests/index.js b/packages/bruno-app/src/components/FolderSettings/Tests/index.js new file mode 100644 index 000000000..b163c6b1e --- /dev/null +++ b/packages/bruno-app/src/components/FolderSettings/Tests/index.js @@ -0,0 +1,51 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useDispatch, useSelector } from 'react-redux'; +import CodeEditor from 'components/CodeEditor'; +import { updateFolderTests } from 'providers/ReduxStore/slices/collections'; +import { saveFolderRoot } from 'providers/ReduxStore/slices/collections/actions'; +import { useTheme } from 'providers/Theme'; +import StyledWrapper from './StyledWrapper'; + +const Tests = ({ collection, folder }) => { + const dispatch = useDispatch(); + const tests = get(folder, 'root.request.tests', ''); + + const { displayedTheme } = useTheme(); + const preferences = useSelector((state) => state.app.preferences); + + const onEdit = (value) => { + dispatch( + updateFolderTests({ + tests: value, + collectionUid: collection.uid, + folderUid: folder.uid + }) + ); + }; + + const handleSave = () => dispatch(saveFolderRoot(collection.uid, folder.uid)); + + return ( + +
These tests will run any time a request in this collection is sent.
+ + +
+ +
+
+ ); +}; + +export default Tests; diff --git a/packages/bruno-app/src/components/FolderSettings/index.js b/packages/bruno-app/src/components/FolderSettings/index.js index b1d6ee249..233cd1139 100644 --- a/packages/bruno-app/src/components/FolderSettings/index.js +++ b/packages/bruno-app/src/components/FolderSettings/index.js @@ -1,16 +1,24 @@ import React from 'react'; import classnames from 'classnames'; -import { updateSettingsSelectedTab } from 'providers/ReduxStore/slices/collections'; +import { updatedFolderSettingsSelectedTab } from 'providers/ReduxStore/slices/collections'; import { useDispatch } from 'react-redux'; import Headers from './Headers'; +import Script from './Script'; +import Tests from './Tests'; +import StyledWrapper from './StyledWrapper'; const FolderSettings = ({ collection, folder }) => { const dispatch = useDispatch(); - const tab = folder?.settingsSelectedTab || 'headers'; + let tab = 'headers'; + const { folderLevelSettingsSelectedTab } = collection; + if (folderLevelSettingsSelectedTab?.[folder.uid]) { + tab = folderLevelSettingsSelectedTab[folder.uid]; + } + const setTab = (tab) => { dispatch( - updateSettingsSelectedTab({ - collectionUid: folder.collectionUid, + updatedFolderSettingsSelectedTab({ + collectionUid: collection.uid, folderUid: folder.uid, tab }) @@ -22,7 +30,12 @@ const FolderSettings = ({ collection, folder }) => { case 'headers': { return ; } - // TODO: Add auth + case 'script': { + return