From 1b63798ff36847be0170d47a5cb3a32423952e3a Mon Sep 17 00:00:00 2001 From: lohxt1 Date: Tue, 1 Jul 2025 20:04:42 +0530 Subject: [PATCH] handle requestConfig translations when passed to pm.sendRequest as a variable --- .../src/utils/send-request-transformer.js | 53 ++++++++ .../transformers/send-request.test.js | 118 ++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/packages/bruno-converters/src/utils/send-request-transformer.js b/packages/bruno-converters/src/utils/send-request-transformer.js index 1029b1943..4f16c4311 100644 --- a/packages/bruno-converters/src/utils/send-request-transformer.js +++ b/packages/bruno-converters/src/utils/send-request-transformer.js @@ -225,6 +225,49 @@ const transformCallback = (j, callback) => { ); }; +/** + * Find and transform variable declaration for request config + * @param {Object} j - jscodeshift API + * @param {Object} root - Root AST node + * @param {string} variableName - Name of the variable to find + * @param {Set} visited - Set of visited variable names to prevent infinite loops + * @returns {Object|null} - Transformed object expression or null if not found + */ +const findAndTransformVariableDeclaration = (j, root, variableName, visited = new Set()) => { + // Prevent infinite loops from circular references + if (visited.has(variableName)) { + return null; + } + visited.add(variableName); + + let transformedConfig = null; + + // Find the variable declaration + root.find(j.VariableDeclarator, { + id: { name: variableName } + }).forEach(declaratorPath => { + const init = declaratorPath.value.init; + + if (init && init.type === 'ObjectExpression') { + // Found the actual object expression - clone and transform it + const configClone = j(init).at(0).get().value; + + // Transform headers and body + transformHeaders(j, configClone); + transformBody(j, configClone); + + transformedConfig = configClone; + } + else if (init && init.type === 'Identifier') { + // This variable references another variable - follow the chain + const referencedVariableName = init.name; + transformedConfig = findAndTransformVariableDeclaration(j, root, referencedVariableName, visited); + } + }); + + return transformedConfig; +}; + const sendRequestTransformer = (path, j) => { const callExpr = path.parent.value; if (callExpr.type !== 'CallExpression') return; @@ -246,6 +289,16 @@ const sendRequestTransformer = (path, j) => { // Transform body transformBody(j, requestOptions); } + // Handle case where requestOptions is a variable reference + else if (requestOptions.type === 'Identifier') { + const variableName = requestOptions.name; + + // Find the root of the current file/program + const root = j(path).closest(j.Program); + + // Find and transform the variable declaration + findAndTransformVariableDeclaration(j, root, variableName); + } // Create the callback block and promise chain if there's a callback if (callback) { diff --git a/packages/bruno-converters/tests/postman/postman-translations/transpiler-tests/transformers/send-request.test.js b/packages/bruno-converters/tests/postman/postman-translations/transpiler-tests/transformers/send-request.test.js index d6e9e62a7..68ac426d4 100644 --- a/packages/bruno-converters/tests/postman/postman-translations/transpiler-tests/transformers/send-request.test.js +++ b/packages/bruno-converters/tests/postman/postman-translations/transpiler-tests/transformers/send-request.test.js @@ -685,4 +685,122 @@ describe('Send Request Translation', () => { `); }); }); + + describe('requestConfig variables', () => { + it('requestConfig passed as a variable', () => { + const code = ` + const requestConfig = { + url: 'https://echo.usebruno.com', + method: 'POST', + header: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: { + mode: 'raw', + raw: JSON.stringify({ + "x": 1 + }) + } + }; + pm.sendRequest(requestConfig, async function (error, response) { + if (error) { + const errorCode = error.code; + console.log(errorCode); + } + if (response) { + const response_body = response.json(); + const response_headers = response.headers; + console.log(response_body, response_headers); + } + }); + `; + const translatedCode = translateCode(code); + expect(translatedCode).toBe(` + const requestConfig = { + url: 'https://echo.usebruno.com', + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + data: JSON.stringify({ + "x": 1 + }) + }; + await bru.sendRequest(requestConfig, async function(error, response) { + if (error) { + const errorCode = error.code; + console.log(errorCode); + } + if (response) { + const response_body = response.data; + const response_headers = response.headers; + console.log(response_body, response_headers); + } + }); + `); + }); + + it('requestConfig passed as a variable with multi-level references', () => { + const code = ` + const requestConfig = { + url: 'https://echo.usebruno.com', + method: 'POST', + header: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: { + mode: 'raw', + raw: JSON.stringify({ + "x": 1 + }) + } + }; + const requestConfig1 = requestConfig; + const requestConfig2 = requestConfig1; + const requestConfig3 = requestConfig2; + pm.sendRequest(requestConfig3, async function (error, response) { + if (error) { + const errorCode = error.code; + console.log(errorCode); + } + if (response) { + const response_body = response.json(); + const response_headers = response.headers; + console.log(response_body, response_headers); + } + }); + `; + const translatedCode = translateCode(code); + expect(translatedCode).toBe(` + const requestConfig = { + url: 'https://echo.usebruno.com', + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + data: JSON.stringify({ + "x": 1 + }) + }; + const requestConfig1 = requestConfig; + const requestConfig2 = requestConfig1; + const requestConfig3 = requestConfig2; + await bru.sendRequest(requestConfig3, async function(error, response) { + if (error) { + const errorCode = error.code; + console.log(errorCode); + } + if (response) { + const response_body = response.data; + const response_headers = response.headers; + console.log(response_body, response_headers); + } + }); + `); + }); + }); }); \ No newline at end of file