mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-24 21:25:45 +00:00
feat: enhance translation capabilities for Bruno to Postman conversion (#7052)
* feat: enhance translation capabilities for Bruno to Postman conversion - Added support for translating req.getHost(), req.getPath(), and req.getQueryString() to their Postman equivalents. - Implemented translation for req.getPathParams() to pm.request.url.variables. - Introduced handling for bru.visualize() to pm.visualizer.set() with various argument types. - Added tests to validate new translation features and ensure correct behavior for URL-related methods and visualizer functionality. * rm: duplicates * refactor: remove bru.visualize transformation and associated tests * feat: enhance BDD-style assertion translations in Postman converter - Updated transformation logic to translate BDD-style assertions like pm.response.to.be.ok, pm.response.to.be.success, and others to their corresponding expect statements. - Added comprehensive tests to validate the new translations for various response status checks. - Improved handling of BDD assertions within test blocks to ensure accurate translation. * fix: correct variable naming in transformation logic for Postman converter - Updated variable names in the transformation logic to improve clarity and consistency. - Ensured that the correct nodes are replaced and added to the transformedNodes set during processing. * fix: improve AST mutation handling in Postman to Bruno translation - Enhanced the processTransformations function to capture stable references before mutating the AST, ensuring correct node replacement and insertion. - Added a defensive guard for ExpressionStatements to prevent errors when accessing undefined properties. - Improved the logic for inserting remaining nodes after the grandparent in reverse order to maintain the correct sequence. * fix: remove unnecessary defensive guard in AST mutation for Postman to Bruno translation
This commit is contained in:
@@ -8,12 +8,14 @@ const simpleTranslations = {
|
||||
// Global Variables
|
||||
'pm.globals.get': 'bru.getGlobalEnvVar',
|
||||
'pm.globals.set': 'bru.setGlobalEnvVar',
|
||||
'pm.globals.replaceIn': 'bru.interpolate',
|
||||
|
||||
// Environment variables
|
||||
'pm.environment.get': 'bru.getEnvVar',
|
||||
'pm.environment.set': 'bru.setEnvVar',
|
||||
'pm.environment.name': 'bru.getEnvName()',
|
||||
'pm.environment.unset': 'bru.deleteEnvVar',
|
||||
'pm.environment.replaceIn': 'bru.interpolate',
|
||||
|
||||
// Variables
|
||||
'pm.variables.get': 'bru.getVar',
|
||||
@@ -25,6 +27,7 @@ const simpleTranslations = {
|
||||
'pm.collectionVariables.set': 'bru.setVar',
|
||||
'pm.collectionVariables.has': 'bru.hasVar',
|
||||
'pm.collectionVariables.unset': 'bru.deleteVar',
|
||||
'pm.collectionVariables.replaceIn': 'bru.interpolate',
|
||||
|
||||
// Request flow control
|
||||
'pm.setNextRequest': 'bru.setNextRequest',
|
||||
@@ -80,7 +83,11 @@ const simpleTranslations = {
|
||||
// Legacy Postman API (deprecated) (we can use pm instead of postman, as we are converting all postman references to pm in the code as the part of pre-processing)
|
||||
'pm.setEnvironmentVariable': 'bru.setEnvVar',
|
||||
'pm.getEnvironmentVariable': 'bru.getEnvVar',
|
||||
'pm.clearEnvironmentVariable': 'bru.deleteEnvVar'
|
||||
'pm.clearEnvironmentVariable': 'bru.deleteEnvVar',
|
||||
|
||||
// Legacy response properties
|
||||
'responseCode.code': 'res.getStatus()',
|
||||
'responseCode.name': 'res.statusText'
|
||||
};
|
||||
|
||||
/* Complex transformations that need custom handling
|
||||
@@ -328,6 +335,229 @@ const complexTransformations = [
|
||||
[reduceFn, j.objectExpression([])]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.globals.has requires special handling
|
||||
{
|
||||
pattern: 'pm.globals.has',
|
||||
transform: (path, j) => {
|
||||
const callExpr = path.parent.value;
|
||||
const args = callExpr.arguments;
|
||||
|
||||
// Create: bru.getGlobalEnvVar(arg) !== undefined && bru.getGlobalEnvVar(arg) !== null
|
||||
return j.logicalExpression(
|
||||
'&&',
|
||||
j.binaryExpression(
|
||||
'!==',
|
||||
j.callExpression(j.identifier('bru.getGlobalEnvVar'), args),
|
||||
j.identifier('undefined')
|
||||
),
|
||||
j.binaryExpression(
|
||||
'!==',
|
||||
j.callExpression(j.identifier('bru.getGlobalEnvVar'), args),
|
||||
j.identifier('null')
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.request.headers.add({key, value}) -> req.setHeader(key, value)
|
||||
{
|
||||
pattern: 'pm.request.headers.add',
|
||||
transform: (path, j) => {
|
||||
const callExpr = path.parent.value;
|
||||
const args = callExpr.arguments;
|
||||
|
||||
// Check if the argument is an object with key and value properties
|
||||
if (args.length > 0 && args[0].type === 'ObjectExpression') {
|
||||
const obj = args[0];
|
||||
let keyProp = null;
|
||||
let valueProp = null;
|
||||
|
||||
obj.properties.forEach((prop) => {
|
||||
if (prop.key.name === 'key' || prop.key.value === 'key') {
|
||||
keyProp = prop.value;
|
||||
}
|
||||
if (prop.key.name === 'value' || prop.key.value === 'value') {
|
||||
valueProp = prop.value;
|
||||
}
|
||||
});
|
||||
|
||||
if (keyProp && valueProp) {
|
||||
return j.callExpression(
|
||||
j.identifier('req.setHeader'),
|
||||
[keyProp, valueProp]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: keep original args
|
||||
return j.callExpression(j.identifier('req.setHeader'), args);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.request.headers.upsert({key, value}) -> req.setHeader(key, value)
|
||||
{
|
||||
pattern: 'pm.request.headers.upsert',
|
||||
transform: (path, j) => {
|
||||
const callExpr = path.parent.value;
|
||||
const args = callExpr.arguments;
|
||||
|
||||
// Check if the argument is an object with key and value properties
|
||||
if (args.length > 0 && args[0].type === 'ObjectExpression') {
|
||||
const obj = args[0];
|
||||
let keyProp = null;
|
||||
let valueProp = null;
|
||||
|
||||
obj.properties.forEach((prop) => {
|
||||
if (prop.key.name === 'key' || prop.key.value === 'key') {
|
||||
keyProp = prop.value;
|
||||
}
|
||||
if (prop.key.name === 'value' || prop.key.value === 'value') {
|
||||
valueProp = prop.value;
|
||||
}
|
||||
});
|
||||
|
||||
if (keyProp && valueProp) {
|
||||
return j.callExpression(
|
||||
j.identifier('req.setHeader'),
|
||||
[keyProp, valueProp]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: keep original args
|
||||
return j.callExpression(j.identifier('req.setHeader'), args);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.be.ok -> expect(res.getStatus()).to.be.within(200, 299)
|
||||
{
|
||||
pattern: 'pm.response.to.be.ok',
|
||||
transform: (path, j) => {
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
|
||||
j.identifier('to.be.within')
|
||||
),
|
||||
[j.literal(200), j.literal(299)]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.be.success -> expect(res.getStatus()).to.be.within(200, 299)
|
||||
{
|
||||
pattern: 'pm.response.to.be.success',
|
||||
transform: (path, j) => {
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
|
||||
j.identifier('to.be.within')
|
||||
),
|
||||
[j.literal(200), j.literal(299)]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.be.redirection -> expect(res.getStatus()).to.be.within(300, 399)
|
||||
{
|
||||
pattern: 'pm.response.to.be.redirection',
|
||||
transform: (path, j) => {
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
|
||||
j.identifier('to.be.within')
|
||||
),
|
||||
[j.literal(300), j.literal(399)]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.be.clientError -> expect(res.getStatus()).to.be.within(400, 499)
|
||||
{
|
||||
pattern: 'pm.response.to.be.clientError',
|
||||
transform: (path, j) => {
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
|
||||
j.identifier('to.be.within')
|
||||
),
|
||||
[j.literal(400), j.literal(499)]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.be.serverError -> expect(res.getStatus()).to.be.within(500, 599)
|
||||
{
|
||||
pattern: 'pm.response.to.be.serverError',
|
||||
transform: (path, j) => {
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
|
||||
j.identifier('to.be.within')
|
||||
),
|
||||
[j.literal(500), j.literal(599)]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.be.error -> expect(res.getStatus()).to.be.at.least(400)
|
||||
{
|
||||
pattern: 'pm.response.to.be.error',
|
||||
transform: (path, j) => {
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
|
||||
j.identifier('to.be.at.least')
|
||||
),
|
||||
[j.literal(400)]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// pm.response.to.have.jsonBody(path) -> expect(res.getBody()).to.have.nested.property(path)
|
||||
{
|
||||
pattern: 'pm.response.to.have.jsonBody',
|
||||
transform: (path, j) => {
|
||||
const callExpr = path.parent.value;
|
||||
const args = callExpr.arguments;
|
||||
|
||||
if (args.length === 0) {
|
||||
// No path provided, just check that body exists
|
||||
return j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
|
||||
j.identifier('to.exist')
|
||||
);
|
||||
} else if (args.length === 1) {
|
||||
// Path provided, check property exists
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
|
||||
j.identifier('to.have.nested.property')
|
||||
),
|
||||
args
|
||||
);
|
||||
} else {
|
||||
// Path and value provided, check property equals value
|
||||
return j.callExpression(
|
||||
j.memberExpression(
|
||||
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
|
||||
j.identifier('to.have.nested.property')
|
||||
),
|
||||
args
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Legacy postman.getResponseHeader(name) -> res.getHeader(name)
|
||||
{
|
||||
pattern: 'pm.getResponseHeader',
|
||||
transform: (path, j) => {
|
||||
const callExpr = path.parent.value;
|
||||
const args = callExpr.arguments;
|
||||
return j.callExpression(j.identifier('res.getHeader'), args);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -360,24 +590,40 @@ function processTransformations(ast, transformedNodes) {
|
||||
}
|
||||
|
||||
// Then check for complex transformations (O(1))
|
||||
if (complexTransformationsMap.hasOwnProperty(memberExprStr)
|
||||
&& path.parent.value.type === 'CallExpression') {
|
||||
const transform = complexTransformationsMap[memberExprStr];
|
||||
const replacement = transform.transform(path, j);
|
||||
if (Array.isArray(replacement)) {
|
||||
replacement.forEach((nodePath, index) => {
|
||||
if (index === 0) {
|
||||
j(path.parent).replaceWith(nodePath);
|
||||
} else {
|
||||
j(path.parent.parent).insertAfter(nodePath);
|
||||
if (complexTransformationsMap.hasOwnProperty(memberExprStr)) {
|
||||
const parentType = path.parent.value.type;
|
||||
|
||||
// Call-based patterns (e.g., pm.response.to.have.jsonBody("path"))
|
||||
if (parentType === 'CallExpression') {
|
||||
const transform = complexTransformationsMap[memberExprStr];
|
||||
const replacement = transform.transform(path, j);
|
||||
if (Array.isArray(replacement)) {
|
||||
// Capture stable references before mutating the AST
|
||||
const parentPath = path.parent;
|
||||
const grandParentPath = parentPath.parent;
|
||||
|
||||
// Replace the original CallExpression with the first node
|
||||
j(parentPath).replaceWith(replacement[0]);
|
||||
transformedNodes.add(replacement[0]);
|
||||
transformedNodes.add(parentPath.node);
|
||||
|
||||
// Insert remaining nodes after the grandparent in reverse order
|
||||
// so that repeated insertAfter on the same anchor yields correct sequence
|
||||
for (let i = replacement.length - 1; i >= 1; i--) {
|
||||
j(grandParentPath).insertAfter(replacement[i]);
|
||||
transformedNodes.add(replacement[i]);
|
||||
}
|
||||
transformedNodes.add(nodePath.node);
|
||||
} else {
|
||||
j(path.parent).replaceWith(replacement);
|
||||
transformedNodes.add(path.node);
|
||||
transformedNodes.add(path.parent.node);
|
||||
});
|
||||
} else {
|
||||
j(path.parent).replaceWith(replacement);
|
||||
}
|
||||
} else if (parentType === 'ExpressionStatement') {
|
||||
// Property-access patterns used as statements (e.g., pm.response.to.be.ok;)
|
||||
const transform = complexTransformationsMap[memberExprStr];
|
||||
const replacement = transform.transform(path, j);
|
||||
j(path).replaceWith(replacement);
|
||||
transformedNodes.add(path.node);
|
||||
transformedNodes.add(path.parent.node);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -203,4 +203,18 @@ console.log("Headers:", JSON.stringify(pm.request.headers));
|
||||
const translatedCode = translateBruToPostman(code);
|
||||
expect(translatedCode).toBe('const pathParams = pm.request.url.variables;');
|
||||
});
|
||||
|
||||
it('should handle URL methods in complex expressions', () => {
|
||||
const code = 'const fullUrl = req.getHost() + req.getPath() + "?" + req.getQueryString();';
|
||||
const translatedCode = translateBruToPostman(code);
|
||||
expect(translatedCode).toContain('pm.request.url.getHost()');
|
||||
expect(translatedCode).toContain('pm.request.url.getPath()');
|
||||
expect(translatedCode).toContain('pm.request.url.getQueryString()');
|
||||
});
|
||||
|
||||
it('should handle req.getPathParams() in conditional', () => {
|
||||
const code = 'if (req.getPathParams().id) { console.log("Has ID"); }';
|
||||
const translatedCode = translateBruToPostman(code);
|
||||
expect(translatedCode).toContain('pm.request.url.variables.id');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -295,4 +295,55 @@ describe('Legacy Postman API Translation', () => {
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('responseCode translations', () => {
|
||||
test('should translate responseCode.code', () => {
|
||||
const input = 'const status = responseCode.code;';
|
||||
const result = translateCode(input);
|
||||
expect(result).toBe('const status = res.getStatus();');
|
||||
});
|
||||
|
||||
test('should translate responseCode.name', () => {
|
||||
const input = 'const statusName = responseCode.name;';
|
||||
const result = translateCode(input);
|
||||
expect(result).toBe('const statusName = res.statusText;');
|
||||
});
|
||||
|
||||
test('should translate responseCode.code in conditional', () => {
|
||||
const input = 'if (responseCode.code === 200) { console.log("Success"); }';
|
||||
const result = translateCode(input);
|
||||
expect(result).toBe('if (res.getStatus() === 200) { console.log("Success"); }');
|
||||
});
|
||||
|
||||
test('should translate both responseCode.code and responseCode.name together', () => {
|
||||
const input = `
|
||||
const code = responseCode.code;
|
||||
const name = responseCode.name;
|
||||
console.log(code, name);
|
||||
`;
|
||||
const result = translateCode(input);
|
||||
expect(result).toContain('const code = res.getStatus();');
|
||||
expect(result).toContain('const name = res.statusText;');
|
||||
});
|
||||
});
|
||||
|
||||
describe('postman.getResponseHeader translations', () => {
|
||||
test('should translate postman.getResponseHeader', () => {
|
||||
const input = 'postman.getResponseHeader("Content-Type");';
|
||||
const result = translateCode(input);
|
||||
expect(result).toBe('res.getHeader("Content-Type");');
|
||||
});
|
||||
|
||||
test('should translate postman.getResponseHeader in assignment', () => {
|
||||
const input = 'const contentType = postman.getResponseHeader("Content-Type");';
|
||||
const result = translateCode(input);
|
||||
expect(result).toBe('const contentType = res.getHeader("Content-Type");');
|
||||
});
|
||||
|
||||
test('should translate postman.getResponseHeader with variable argument', () => {
|
||||
const input = 'const headerName = "Authorization"; const value = postman.getResponseHeader(headerName);';
|
||||
const result = translateCode(input);
|
||||
expect(result).toContain('res.getHeader(headerName)');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -121,4 +121,39 @@ describe('Request Translation', () => {
|
||||
const name = req.getName();
|
||||
`);
|
||||
});
|
||||
|
||||
// --- pm.request.headers.add and upsert ---------------------------
|
||||
it('should translate pm.request.headers.add with object argument', () => {
|
||||
const code = 'pm.request.headers.add({key: "Authorization", value: "Bearer token"});';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('req.setHeader("Authorization", "Bearer token");');
|
||||
});
|
||||
|
||||
it('should translate pm.request.headers.upsert with object argument', () => {
|
||||
const code = 'pm.request.headers.upsert({key: "Content-Type", value: "application/json"});';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('req.setHeader("Content-Type", "application/json");');
|
||||
});
|
||||
|
||||
it('should translate pm.request.headers.add with quoted key property', () => {
|
||||
const code = 'pm.request.headers.add({"key": "X-Custom-Header", "value": "custom-value"});';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('req.setHeader("X-Custom-Header", "custom-value");');
|
||||
});
|
||||
|
||||
it('should translate pm.request.headers.upsert with variable values', () => {
|
||||
const code = 'const headerName = "Authorization"; const headerValue = "Bearer " + token; pm.request.headers.upsert({key: headerName, value: headerValue});';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('req.setHeader(headerName, headerValue)');
|
||||
});
|
||||
|
||||
it('should translate multiple headers.add calls', () => {
|
||||
const code = `
|
||||
pm.request.headers.add({key: "Authorization", value: "Bearer token"});
|
||||
pm.request.headers.add({key: "Content-Type", value: "application/json"});
|
||||
`;
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('req.setHeader("Authorization", "Bearer token")');
|
||||
expect(translatedCode).toContain('req.setHeader("Content-Type", "application/json")');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -583,4 +583,97 @@ describe('Response Translation', () => {
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('const responseSize = res.getSize().body;');
|
||||
});
|
||||
|
||||
// --- BDD-style response assertions ---------------------------
|
||||
|
||||
it('should translate pm.response.to.be.ok', () => {
|
||||
const code = 'pm.response.to.be.ok;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(200, 299)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.be.success', () => {
|
||||
const code = 'pm.response.to.be.success;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(200, 299)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.be.redirection', () => {
|
||||
const code = 'pm.response.to.be.redirection;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(300, 399)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.be.clientError', () => {
|
||||
const code = 'pm.response.to.be.clientError;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(400, 499)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.be.serverError', () => {
|
||||
const code = 'pm.response.to.be.serverError;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(500, 599)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.be.error', () => {
|
||||
const code = 'pm.response.to.be.error;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.at.least(400)');
|
||||
});
|
||||
|
||||
it('should handle BDD-style assertions inside test blocks', () => {
|
||||
const code = `
|
||||
pm.test("Status check", function() {
|
||||
pm.response.to.be.ok;
|
||||
pm.response.to.be.success;
|
||||
});
|
||||
`;
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('test("Status check", function() {');
|
||||
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(200, 299)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.have.jsonBody with path', () => {
|
||||
const code = 'pm.response.to.have.jsonBody("user.id");';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.have.nested.property("user.id")');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.have.jsonBody with path and value', () => {
|
||||
const code = 'pm.response.to.have.jsonBody("status", "success");';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.have.nested.property("status", "success")');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.have.jsonBody without arguments', () => {
|
||||
const code = 'pm.response.to.have.jsonBody();';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.exist');
|
||||
});
|
||||
|
||||
it('should handle pm.response.to.have.jsonBody inside test blocks', () => {
|
||||
const code = `
|
||||
pm.test("Response validation", function() {
|
||||
pm.response.to.have.jsonBody("data");
|
||||
pm.response.to.have.jsonBody("data.id", 123);
|
||||
});
|
||||
`;
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('test("Response validation", function() {');
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.have.nested.property("data")');
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.have.nested.property("data.id", 123)');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.have.jsonBody with nested path', () => {
|
||||
const code = 'pm.response.to.have.jsonBody("response.data.items[0].name");';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.have.nested.property("response.data.items[0].name")');
|
||||
});
|
||||
|
||||
it('should translate pm.response.to.have.jsonBody with variable path', () => {
|
||||
const code = 'const path = "user.id"; pm.response.to.have.jsonBody(path);';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toContain('expect(res.getBody()).to.have.nested.property(path)');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -204,4 +204,58 @@ describe('Variables Translation', () => {
|
||||
|
||||
expect(translatedCode).toBe('bru.setVar("fullPath", bru.getEnvVar("baseUrl") + bru.getVar("endpoint"));');
|
||||
});
|
||||
|
||||
// replaceIn tests for different variable scopes
|
||||
it('should translate pm.globals.replaceIn', () => {
|
||||
const code = 'pm.globals.replaceIn("Hello {{name}}");';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toBe('bru.interpolate("Hello {{name}}");');
|
||||
});
|
||||
|
||||
it('should translate pm.environment.replaceIn', () => {
|
||||
const code = 'pm.environment.replaceIn("{{baseUrl}}/api");';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toBe('bru.interpolate("{{baseUrl}}/api");');
|
||||
});
|
||||
|
||||
it('should translate pm.collectionVariables.replaceIn', () => {
|
||||
const code = 'pm.collectionVariables.replaceIn("{{apiKey}}");';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toBe('bru.interpolate("{{apiKey}}");');
|
||||
});
|
||||
|
||||
it('should translate pm.globals.replaceIn in assignment', () => {
|
||||
const code = 'const message = pm.globals.replaceIn("Welcome {{username}}!");';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toBe('const message = bru.interpolate("Welcome {{username}}!");');
|
||||
});
|
||||
|
||||
// pm.globals.has tests
|
||||
it('should translate pm.globals.has', () => {
|
||||
const code = 'pm.globals.has("token");';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toContain('bru.getGlobalEnvVar("token") !== undefined');
|
||||
expect(translatedCode).toContain('bru.getGlobalEnvVar("token") !== null');
|
||||
});
|
||||
|
||||
it('should translate pm.globals.has in conditional', () => {
|
||||
const code = 'if (pm.globals.has("authToken")) { console.log("Token exists"); }';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toContain('bru.getGlobalEnvVar("authToken") !== undefined');
|
||||
expect(translatedCode).toContain('bru.getGlobalEnvVar("authToken") !== null');
|
||||
expect(translatedCode).toContain('console.log("Token exists");');
|
||||
});
|
||||
|
||||
it('should translate pm.globals.has with variable assignment', () => {
|
||||
const code = 'const hasGlobal = pm.globals.has("config");';
|
||||
const translatedCode = translateCode(code);
|
||||
|
||||
expect(translatedCode).toContain('const hasGlobal = bru.getGlobalEnvVar("config") !== undefined && bru.getGlobalEnvVar("config") !== null');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user