From 587e3cfe5d1144c0d0f7472ea9a4c6c37971504c Mon Sep 17 00:00:00 2001 From: pooja-bruno Date: Thu, 26 Jun 2025 15:52:17 +0530 Subject: [PATCH] add: script error card in collection runner --- .../RunnerResults/ResponsePane/index.js | 31 +++- .../src/components/RunnerResults/index.jsx | 10 +- .../ReduxStore/slices/collections/index.js | 27 +++ .../bruno-electron/src/ipc/network/index.js | 157 +++++++++++++----- 4 files changed, 178 insertions(+), 47 deletions(-) diff --git a/packages/bruno-app/src/components/RunnerResults/ResponsePane/index.js b/packages/bruno-app/src/components/RunnerResults/ResponsePane/index.js index 21f02406e..76a65d0cd 100644 --- a/packages/bruno-app/src/components/RunnerResults/ResponsePane/index.js +++ b/packages/bruno-app/src/components/RunnerResults/ResponsePane/index.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import get from 'lodash/get'; import classnames from 'classnames'; import { safeStringifyJSON } from 'utils/common'; @@ -12,17 +12,28 @@ import TestResultsLabel from 'components/ResponsePane/TestResultsLabel'; import StyledWrapper from './StyledWrapper'; import SkippedRequest from 'components/ResponsePane/SkippedRequest'; import RunnerTimeline from 'components/ResponsePane/RunnerTimeline'; +import ScriptError from 'components/ResponsePane/ScriptError'; +import ScriptErrorIcon from 'components/ResponsePane/ScriptErrorIcon'; const ResponsePane = ({ rightPaneWidth, item, collection }) => { const [selectedTab, setSelectedTab] = useState('response'); + const [showScriptErrorCard, setShowScriptErrorCard] = useState(false); const { requestSent, responseReceived, testResults, assertionResults, preRequestTestResults, postResponseTestResults, error } = item; + useEffect(() => { + if (item?.preRequestScriptErrorMessage || item?.postResponseScriptErrorMessage || item?.testScriptErrorMessage) { + setShowScriptErrorCard(true); + } + }, [item?.preRequestScriptErrorMessage, item?.postResponseScriptErrorMessage, item?.testScriptErrorMessage]); + const headers = get(item, 'responseReceived.headers', []); const status = get(item, 'responseReceived.status', 0); const size = get(item, 'responseReceived.size', 0); const duration = get(item, 'responseReceived.duration', 0); + const hasScriptError = item?.preRequestScriptErrorMessage || item?.postResponseScriptErrorMessage || item?.testScriptErrorMessage; + const selectTab = (tab) => setSelectedTab(tab); const getTabPanel = (tab) => { @@ -99,12 +110,28 @@ const ResponsePane = ({ rightPaneWidth, item, collection }) => { />
+ {hasScriptError && !showScriptErrorCard && ( + setShowScriptErrorCard(true)} + /> + )}
-
{getTabPanel(selectedTab)}
+
+ {hasScriptError && showScriptErrorCard && ( + setShowScriptErrorCard(false)} + /> + )} +
+ {getTabPanel(selectedTab)} +
+
); }; diff --git a/packages/bruno-app/src/components/RunnerResults/index.jsx b/packages/bruno-app/src/components/RunnerResults/index.jsx index cbf099e5b..b35d366a6 100644 --- a/packages/bruno-app/src/components/RunnerResults/index.jsx +++ b/packages/bruno-app/src/components/RunnerResults/index.jsx @@ -27,7 +27,10 @@ const allTestsPassed = (item) => { item.testStatus === 'pass' && item.assertionStatus === 'pass' && item.preRequestTestStatus === 'pass' && - item.postResponseTestStatus === 'pass'; + item.postResponseTestStatus === 'pass' && + !item.preRequestScriptErrorMessage && + !item.postResponseScriptErrorMessage && + !item.testScriptErrorMessage; }; const anyTestFailed = (item) => { @@ -35,7 +38,10 @@ const anyTestFailed = (item) => { item.testStatus === 'fail' || item.assertionStatus === 'fail' || item.preRequestTestStatus === 'fail' || - item.postResponseTestStatus === 'fail'; + item.postResponseTestStatus === 'fail' || + item.preRequestScriptErrorMessage || + item.postResponseScriptErrorMessage || + item.testScriptErrorMessage; }; export default function RunnerResults({ collection }) { 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 9139ec599..55945a853 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -2177,6 +2177,33 @@ export const collectionsSlice = createSlice({ item.status = 'skipped'; item.responseReceived = action.payload.responseReceived; } + + if (type === 'post-response-script-execution') { + const item = collection.runnerResult.items.findLast((i) => i.uid === request.uid); + if (action.payload.errorMessage) { + item.postResponseScriptErrorMessage = action.payload.errorMessage; + } else { + item.postResponseScriptErrorMessage = null; + } + } + + if (type === 'test-script-execution') { + const item = collection.runnerResult.items.findLast((i) => i.uid === request.uid); + if (action.payload.errorMessage) { + item.testScriptErrorMessage = action.payload.errorMessage; + } else { + item.testScriptErrorMessage = null; + } + } + + if (type === 'pre-request-script-execution') { + const item = collection.runnerResult.items.findLast((i) => i.uid === request.uid); + if (action.payload.errorMessage) { + item.preRequestScriptErrorMessage = action.payload.errorMessage; + } else { + item.preRequestScriptErrorMessage = null; + } + } } }, resetCollectionRunner: (state, action) => { diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index aa70ab8c6..490fc2535 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -1032,18 +1032,49 @@ const registerNetworkIpc = (mainWindow) => { const requestUid = uuid(); try { - const preRequestScriptResult = await runPreRequest( - request, - requestUid, - envVars, - collectionPath, - collection, - collectionUid, - runtimeVariables, - processEnvVars, - scriptingConfig, - runRequestByItemPathname - ); + let preRequestScriptResult; + try { + preRequestScriptResult = await runPreRequest( + request, + requestUid, + envVars, + collectionPath, + collection, + collectionUid, + runtimeVariables, + processEnvVars, + scriptingConfig, + runRequestByItemPathname + ); + + // Send pre-request test results if available + if (preRequestScriptResult?.results) { + mainWindow.webContents.send('main:run-folder-event', { + type: 'test-results-pre-request', + preRequestTestResults: preRequestScriptResult.results, + ...eventData + }); + } + + mainWindow.webContents.send('main:run-folder-event', { + type: 'pre-request-script-execution', + ...eventData, + errorMessage: null, + }); + } catch (error) { + console.error('Pre-request script error:', error); + + // Format a more readable error message + const errorMessage = error?.message || 'An error occurred in pre-request script'; + + mainWindow.webContents.send('main:run-folder-event', { + type: 'pre-request-script-execution', + ...eventData, + errorMessage: errorMessage, + }); + + throw error; + } if (preRequestScriptResult?.nextRequestName !== undefined) { nextRequestName = preRequestScriptResult.nextRequestName; @@ -1053,15 +1084,6 @@ const registerNetworkIpc = (mainWindow) => { stopRunnerExecution = true; } - // Send pre-request test results if available - if (preRequestScriptResult?.results) { - mainWindow.webContents.send('main:run-folder-event', { - type: 'test-results-pre-request', - preRequestTestResults: preRequestScriptResult.results, - ...eventData - }); - } - if (preRequestScriptResult?.skipRequest) { mainWindow.webContents.send('main:run-folder-event', { type: 'runner-request-skipped', @@ -1200,19 +1222,39 @@ const registerNetworkIpc = (mainWindow) => { } } - const postResponseScriptResult = await runPostResponse( - request, - response, - requestUid, - envVars, - collectionPath, - collection, - collectionUid, - runtimeVariables, - processEnvVars, - scriptingConfig, - runRequestByItemPathname - ); + let postResponseScriptResult; + try { + postResponseScriptResult = await runPostResponse( + request, + response, + requestUid, + envVars, + collectionPath, + collection, + collectionUid, + runtimeVariables, + processEnvVars, + scriptingConfig, + runRequestByItemPathname + ); + + mainWindow.webContents.send('main:run-folder-event', { + type: 'post-response-script-execution', + ...eventData, + errorMessage: null, + }); + } catch (error) { + console.error('Post-response script error:', error); + + // Format a more readable error message + const errorMessage = error?.message || 'An error occurred in post-response script'; + + mainWindow.webContents.send('main:run-folder-event', { + type: 'post-response-script-execution', + ...eventData, + errorMessage: errorMessage, + }); + } if (postResponseScriptResult?.nextRequestName !== undefined) { nextRequestName = postResponseScriptResult.nextRequestName; @@ -1255,9 +1297,12 @@ const registerNetworkIpc = (mainWindow) => { const testFile = get(request, 'tests'); const collectionName = collection?.name if (typeof testFile === 'string') { + let testResults = null; + let testError = null; + try { const testRuntime = new TestRuntime({ runtime: scriptingConfig?.runtime }); - const testResults = await testRuntime.runTests( + testResults = await testRuntime.runTests( decomment(testFile), request, response, @@ -1292,30 +1337,56 @@ const registerNetworkIpc = (mainWindow) => { }); collection.globalEnvironmentVariables = testResults.globalEnvironmentVariables; - } catch (testError) { + } catch (error) { + testError = error; - if (testError.partialResults && testError.partialResults.results.length > 0) { - + if (error.partialResults) { + testResults = error.partialResults; + } else { + testResults = { + request, + envVariables: envVars, + runtimeVariables, + globalEnvironmentVariables: request?.globalEnvironmentVariables || {}, + results: [], + nextRequestName: null + }; + } + + if (testResults && testResults.results.length > 0) { // Send the partial test results mainWindow.webContents.send('main:run-folder-event', { type: 'test-results', - testResults: testError.partialResults.results, + testResults: testResults.results, ...eventData }); mainWindow.webContents.send('main:script-environment-update', { - envVariables: testError.partialResults.envVariables, - runtimeVariables: testError.partialResults.runtimeVariables, + envVariables: testResults.envVariables, + runtimeVariables: testResults.runtimeVariables, collectionUid }); mainWindow.webContents.send('main:global-environment-variables-update', { - globalEnvironmentVariables: testError.partialResults.globalEnvironmentVariables + globalEnvironmentVariables: testResults.globalEnvironmentVariables }); - collection.globalEnvironmentVariables = testError.partialResults.globalEnvironmentVariables; + collection.globalEnvironmentVariables = testResults.globalEnvironmentVariables; } } + + const testScriptExecutionEvent = { + type: 'test-script-execution', + ...eventData, + errorMessage: null, + } + + if (testError) { + const errorMessage = testError?.message || 'An error occurred in test script'; + testScriptExecutionEvent.errorMessage = errorMessage; + } + + mainWindow.webContents.send('main:run-folder-event', testScriptExecutionEvent); } } catch (error) { mainWindow.webContents.send('main:run-folder-event', {