feat: add missing status assertions and .not negation support (#7660)

* feat: add new status assertions and negated variants for response checks

- Introduced new status assertions: `pm.response.to.be.info`, `pm.response.to.be.accepted`, `pm.response.to.be.badRequest`, `pm.response.to.be.unauthorized`, `pm.response.to.be.forbidden`, `pm.response.to.be.notFound`, `pm.response.to.be.rateLimited`, and `pm.response.to.be.withoutBody`.
- Implemented negated variants for existing assertions, allowing checks like `pm.response.to.not.be.ok` and `pm.response.to.not.be.success`.
- Enhanced test coverage to validate the translation of these new assertions and their negated forms in the Postman to Bruno conversion process.

* refactor: update response translation for body assertions

- Changed the translation logic for `pm.response.to.be.withoutBody` to `pm.response.to.be.withBody`, reflecting the actual body content checks.
- Updated corresponding test cases to validate the new assertions and ensure correct translation behavior for body presence checks.
- Enhanced negated variants for body assertions to align with the updated logic.

* feat: add header transformation methods for Postman to Bruno conversion

- Introduced new transformations for `pm.request.headers.prepend`, `pm.request.headers.insert`, and `pm.request.headers.insertAfter` to map to `req.headerList.add`, enhancing header management during the conversion process.
- Updated the transformation logic to ensure only the first argument is retained for these methods, aligning with the intended behavior of the header list operations.

* refactor: update header transformation logic for Postman to Bruno conversion

- Simplified the transformation for `pm.response.to.have.header` and `pm.response.to.not.have.header` to use `res.getHeader` instead of `res.getHeaders`, improving clarity and consistency in the assertions.
- Adjusted related test cases to validate the new transformation logic, ensuring accurate translation of header checks in the conversion process.

* refactor: update header transformation logic for Postman to Bruno conversion

- Enhanced the transformation for `pm.response.to.have.header` and `pm.response.to.not.have.header` to utilize `res.getHeaders()` with lowercased header names, improving consistency and accuracy in header assertions.
- Updated related test cases to reflect the new transformation logic, ensuring correct translation of header checks in the conversion process.

* feat: add data-driven status assertions for response checks

- Introduced a new utility to generate data-driven status assertion entries for `pm.response.to.be.*` checks, including positive and negated variants.
- Integrated the new status assertions into the Postman to Bruno translation logic, enhancing the capability to handle various response status checks.
- Updated tests to validate the translation of new assertions, ensuring accurate conversion of status checks in the response handling process.

* feat: enhance response assertion translations for negated variants

- Updated the transformation logic for `pm.response.to.have.*` assertions to include negated variants, allowing for patterns like `pm.response.to.have.not.status`, `pm.response.to.have.not.header`, and `pm.response.to.have.not.body`.
- Adjusted related test cases to validate the new translations, ensuring accurate conversion of negated assertions in the response handling process.

* refactor: convert status assertion utility to ES module syntax

- Changed the export of `buildStatusAssertionEntries` to ES module syntax for better compatibility with modern JavaScript practices.
- Updated the import statement in the Postman to Bruno translator to reflect the new export format, ensuring seamless integration of the status assertion utility.

* feat: update response body assertion translations to use undefined checks

- Modified the transformation logic for `pm.response.to.be.withBody`, `pm.response.to.not.be.withBody`, and `pm.response.to.be.not.withBody` to use an undefined check instead of truthiness, allowing for accurate handling of falsy body values.
- Updated related test cases to reflect these changes, ensuring correct translation of body presence assertions in the response handling process.
This commit is contained in:
sanish chirayath
2026-05-19 18:04:51 +05:30
committed by GitHub
parent cea883eda2
commit 8cc3a670c6
3 changed files with 417 additions and 139 deletions

View File

@@ -0,0 +1,51 @@
const j = require('jscodeshift');
/**
* Generates data-driven status assertion entries for pm.response.to.be.*
* Each assertion gets positive, to.not.be, and to.be.not variants.
*/
export const buildStatusAssertionEntries = () => {
const buildStatusTransform = (chain, litArgs) => (path) => {
return j.callExpression(
j.memberExpression(
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
j.identifier(chain)
),
litArgs.map((v) => j.literal(v))
);
};
// Only replaces the first 'to.' — safe because all chains start with 'to.' and contain no other 'to.'
const negateChain = (chain) => chain.replace('to.', 'to.not.');
const statusAssertions = [
// Range-based assertions
{ name: 'ok', chain: 'to.be.within', args: [200, 299] },
{ name: 'success', chain: 'to.be.within', args: [200, 299] },
{ name: 'info', chain: 'to.be.within', args: [100, 199] },
{ name: 'redirection', chain: 'to.be.within', args: [300, 399] },
{ name: 'clientError', chain: 'to.be.within', args: [400, 499] },
{ name: 'serverError', chain: 'to.be.within', args: [500, 599] },
{ name: 'error', chain: 'to.be.at.least', args: [400] },
// Specific status code assertions
{ name: 'accepted', chain: 'to.equal', args: [202] },
{ name: 'badRequest', chain: 'to.equal', args: [400] },
{ name: 'unauthorized', chain: 'to.equal', args: [401] },
{ name: 'forbidden', chain: 'to.equal', args: [403] },
{ name: 'notFound', chain: 'to.equal', args: [404] },
{ name: 'rateLimited', chain: 'to.equal', args: [429] }
];
const entries = [];
// Generate positive + negated entries for each status assertion
statusAssertions.forEach(({ name, chain, args }) => {
entries.push(
{ pattern: `pm.response.to.be.${name}`, transform: buildStatusTransform(chain, args) },
{ pattern: `pm.response.to.not.be.${name}`, transform: buildStatusTransform(negateChain(chain), args) },
{ pattern: `pm.response.to.be.not.${name}`, transform: buildStatusTransform(negateChain(chain), args) }
);
});
return entries;
};

View File

@@ -2,6 +2,7 @@ import sendRequestTransformer from './send-request-transformer';
import { getMemberExpressionString } from './ast-utils';
const j = require('jscodeshift');
const cloneDeep = require('lodash/cloneDeep');
import { buildStatusAssertionEntries } from './postman-status-assertions';
// Simple 1:1 translations for straightforward replacements
// TODO: Restore the commented-out translations once the UI update fixes are live.
@@ -211,87 +212,60 @@ const complexTransformations = [
return j.callExpression(j.identifier('res.getHeader'), path.parent.value.arguments);
}
},
// Handle pm.response.to.have.status
{
pattern: 'pm.response.to.have.status',
// pm.response.to[.not].have.status -> expect(res.getStatus()).to[.not].equal(arg)
...['to.have.status', 'to.not.have.status', 'to.have.not.status'].map((pattern) => ({
pattern: `pm.response.${pattern}`,
transform: (path, j) => {
const callExpr = path.parent.value;
const args = callExpr.arguments;
// Create: expect(res.getStatus()).to.equal(arg)
const negated = pattern.includes('.not.');
return j.callExpression(
j.memberExpression(
j.callExpression(
j.identifier('expect'),
[
j.callExpression(
j.identifier('res.getStatus'),
[]
)
]
),
j.identifier('to.equal')
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getStatus'), [])]),
j.identifier(negated ? 'to.not.equal' : 'to.equal')
),
args
path.parent.value.arguments
);
}
},
})),
// handle 'pm.response.to.have.header' to expect(res.getHeaders()).to.have.property(args)
{
pattern: 'pm.response.to.have.header',
// pm.response.to[.not].have.header -> expect(res.getHeaders()).to[.not].have.property(args)
// Header names are lowercased because axios normalizes response headers to lowercase
...['to.have.header', 'to.not.have.header', 'to.have.not.header'].map((pattern) => ({
pattern: `pm.response.${pattern}`,
transform: (path, j) => {
const callExpr = path.parent.value;
const args = callExpr.arguments;
const args = path.parent.value.arguments;
const negated = pattern.includes('.not.');
if (args.length > 0) {
// Apply toLowerCase() to the first argument
args[0] = j.callExpression(
j.memberExpression(
args[0],
j.identifier('toLowerCase')
),
j.memberExpression(args[0], j.identifier('toLowerCase')),
[]
);
}
// Create: expect(res.getHeaders()).to.have.property(args)
return j.callExpression(
j.memberExpression(
j.callExpression(
j.identifier('expect'),
[
j.callExpression(
j.identifier('res.getHeaders'),
[]
)
]
),
j.identifier('to.have.property')
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getHeaders'), [])]),
j.identifier(negated ? 'to.not.have.property' : 'to.have.property')
),
args
);
}
},
// handle pm.response.to.have.body to expect(res.getBody()).to.equal(arg)
{
pattern: 'pm.response.to.have.body',
})),
// pm.response.to[.not].have.body -> expect(res.getBody()).to[.not].equal(arg)
...['to.have.body', 'to.not.have.body', 'to.have.not.body'].map((pattern) => ({
pattern: `pm.response.${pattern}`,
transform: (path, j) => {
const callExpr = path.parent.value;
const args = callExpr.arguments;
const negated = pattern.includes('.not.');
return j.callExpression(
j.memberExpression(
j.callExpression(j.identifier('expect'), [j.identifier('res.getBody()')]),
j.identifier('to.equal')
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
j.identifier(negated ? 'to.not.equal' : 'to.equal')
),
args
path.parent.value.arguments
);
}
},
})),
// Handle pm.execution.setNextRequest(null)
{
@@ -439,90 +413,6 @@ const complexTransformations = [
}
},
// 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(...) -> expect(res.getBody()).to.have.jsonBody(...)
{
pattern: 'pm.response.to.have.jsonBody',
@@ -655,7 +545,49 @@ const complexTransformations = [
const args = callExpr.arguments;
return j.callExpression(j.identifier('res.getHeader'), args);
}
}
},
// pm.response.to.be.withBody -> expect(res.getBody()).to.not.equal(undefined)
// Uses undefined check instead of truthiness (.to.be.ok) so falsy bodies (false, 0, null) pass correctly
{
pattern: 'pm.response.to.be.withBody',
transform: (path, j) => {
return j.callExpression(
j.memberExpression(
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
j.identifier('to.not.equal')
),
[j.identifier('undefined')]
);
}
},
{
pattern: 'pm.response.to.not.be.withBody',
transform: (path, j) => {
return j.callExpression(
j.memberExpression(
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
j.identifier('to.equal')
),
[j.identifier('undefined')]
);
}
},
{
pattern: 'pm.response.to.be.not.withBody',
transform: (path, j) => {
return j.callExpression(
j.memberExpression(
j.callExpression(j.identifier('expect'), [j.callExpression(j.identifier('res.getBody'), [])]),
j.identifier('to.equal')
),
[j.identifier('undefined')]
);
}
},
// --- Data-driven status assertions (pm.response.to.be.*) ---
...buildStatusAssertionEntries()
];
// Create a map for complex transformations to enable O(1) lookups

View File

@@ -906,4 +906,299 @@ describe('Response Translation', () => {
const translatedCode = translateCode(code);
expect(translatedCode).toBe('const json = res.headerList.toJSON();');
});
// --- New status assertions ---
it('should translate pm.response.to.be.info', () => {
const code = 'pm.response.to.be.info;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(100, 199)');
});
it('should translate pm.response.to.be.accepted', () => {
const code = 'pm.response.to.be.accepted;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(202)');
});
it('should translate pm.response.to.be.badRequest', () => {
const code = 'pm.response.to.be.badRequest;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(400)');
});
it('should translate pm.response.to.be.unauthorized', () => {
const code = 'pm.response.to.be.unauthorized;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(401)');
});
it('should translate pm.response.to.be.forbidden', () => {
const code = 'pm.response.to.be.forbidden;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(403)');
});
it('should translate pm.response.to.be.notFound', () => {
const code = 'pm.response.to.be.notFound;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(404)');
});
it('should translate pm.response.to.be.rateLimited', () => {
const code = 'pm.response.to.be.rateLimited;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(429)');
});
it('should translate pm.response.to.be.withBody', () => {
const code = 'pm.response.to.be.withBody;';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getBody()).to.not.equal(undefined);');
});
it('should translate withBody using undefined check (not truthiness) so falsy bodies work', () => {
const code = 'pm.response.to.be.withBody;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('to.not.equal(undefined)');
});
it('should handle new status assertions inside test blocks', () => {
const code = `
pm.test("Status checks", function() {
pm.response.to.be.info;
pm.response.to.be.accepted;
pm.response.to.be.badRequest;
pm.response.to.be.unauthorized;
pm.response.to.be.forbidden;
pm.response.to.be.notFound;
pm.response.to.be.rateLimited;
});
`;
const translatedCode = translateCode(code);
expect(translatedCode).toContain('test("Status checks", function() {');
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(100, 199)');
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(202)');
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(400)');
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(401)');
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(403)');
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(404)');
expect(translatedCode).toContain('expect(res.getStatus()).to.equal(429)');
});
// --- .not negation for to.be.* assertions ---
it('should translate pm.response.to.not.be.ok', () => {
const code = 'pm.response.to.not.be.ok;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(200, 299)');
});
it('should translate pm.response.to.be.not.ok (alternate position)', () => {
const code = 'pm.response.to.be.not.ok;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(200, 299)');
});
it('should translate pm.response.to.be.not.forbidden (alternate position)', () => {
const code = 'pm.response.to.be.not.forbidden;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(403)');
});
it('should translate pm.response.to.be.not.serverError (alternate position)', () => {
const code = 'pm.response.to.be.not.serverError;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(500, 599)');
});
it('should translate pm.response.to.be.not.withBody (alternate position)', () => {
const code = 'pm.response.to.be.not.withBody;';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getBody()).to.equal(undefined);');
});
it('should translate pm.response.to.not.be.success', () => {
const code = 'pm.response.to.not.be.success;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(200, 299)');
});
it('should translate pm.response.to.not.be.serverError', () => {
const code = 'pm.response.to.not.be.serverError;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(500, 599)');
});
it('should translate pm.response.to.not.be.clientError', () => {
const code = 'pm.response.to.not.be.clientError;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(400, 499)');
});
it('should translate pm.response.to.not.be.redirection', () => {
const code = 'pm.response.to.not.be.redirection;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(300, 399)');
});
it('should translate pm.response.to.not.be.error', () => {
const code = 'pm.response.to.not.be.error;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.at.least(400)');
});
it('should translate pm.response.to.not.be.info', () => {
const code = 'pm.response.to.not.be.info;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(100, 199)');
});
it('should translate pm.response.to.not.be.accepted', () => {
const code = 'pm.response.to.not.be.accepted;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(202)');
});
it('should translate pm.response.to.not.be.badRequest', () => {
const code = 'pm.response.to.not.be.badRequest;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(400)');
});
it('should translate pm.response.to.not.be.unauthorized', () => {
const code = 'pm.response.to.not.be.unauthorized;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(401)');
});
it('should translate pm.response.to.not.be.forbidden', () => {
const code = 'pm.response.to.not.be.forbidden;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(403)');
});
it('should translate pm.response.to.not.be.notFound', () => {
const code = 'pm.response.to.not.be.notFound;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(404)');
});
it('should translate pm.response.to.not.be.rateLimited', () => {
const code = 'pm.response.to.not.be.rateLimited;';
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(429)');
});
it('should translate pm.response.to.not.be.withBody', () => {
const code = 'pm.response.to.not.be.withBody;';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getBody()).to.equal(undefined);');
});
it('should handle negated assertions inside test blocks', () => {
const code = `
pm.test("Response is not a server error", function() {
pm.response.to.not.be.serverError;
pm.response.to.not.be.clientError;
});
`;
const translatedCode = translateCode(code);
expect(translatedCode).toContain('test("Response is not a server error", function() {');
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(500, 599)');
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(400, 499)');
});
it('should handle mixed positive and negated assertions', () => {
const code = `
pm.test("Mixed assertions", function() {
pm.response.to.be.success;
pm.response.to.not.be.serverError;
});
`;
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.be.within(200, 299)');
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(500, 599)');
});
it('should handle negated assertions with aliases', () => {
const code = `
const resp = pm.response;
resp.to.not.be.serverError;
`;
const translatedCode = translateCode(code);
expect(translatedCode).toContain('expect(res.getStatus()).to.not.be.within(500, 599)');
});
// --- .not negation for to.have.* assertions ---
it('should translate pm.response.to.not.have.status', () => {
const code = 'pm.response.to.not.have.status(404);';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getStatus()).to.not.equal(404);');
});
it('should translate pm.response.to.not.have.header', () => {
const code = 'pm.response.to.not.have.header("X-Error");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getHeaders()).to.not.have.property("X-Error".toLowerCase());');
});
it('should translate pm.response.to.not.have.header with value', () => {
const code = 'pm.response.to.not.have.header("Content-Type", "text/plain");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getHeaders()).to.not.have.property("Content-Type".toLowerCase(), "text/plain");');
});
it('should translate pm.response.to.not.have.body', () => {
const code = 'pm.response.to.not.have.body("error");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getBody()).to.not.equal("error");');
});
// --- to.have.not.* (alternate .not position) ---
it('should translate pm.response.to.have.not.status (alternate position)', () => {
const code = 'pm.response.to.have.not.status(404);';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getStatus()).to.not.equal(404);');
});
it('should translate pm.response.to.have.not.header (alternate position)', () => {
const code = 'pm.response.to.have.not.header("X-Error");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getHeaders()).to.not.have.property("X-Error".toLowerCase());');
});
it('should translate pm.response.to.have.not.body (alternate position)', () => {
const code = 'pm.response.to.have.not.body("error");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('expect(res.getBody()).to.not.equal("error");');
});
it('should handle negated to.have.* assertions inside test blocks', () => {
const code = `
pm.test("Negative assertions", function() {
pm.response.to.not.have.status(500);
pm.response.to.not.have.header("X-Error");
pm.response.to.not.have.body("error");
});
`;
const translatedCode = translateCode(code);
expect(translatedCode).toContain('test("Negative assertions", function() {');
expect(translatedCode).toContain('expect(res.getStatus()).to.not.equal(500)');
expect(translatedCode).toContain('expect(res.getHeaders()).to.not.have.property("X-Error".toLowerCase())');
expect(translatedCode).toContain('expect(res.getBody()).to.not.equal("error")');
});
it('should handle negated to.have.status with alias', () => {
const code = `
const resp = pm.response;
resp.to.not.have.status(404);
`;
const translatedCode = translateCode(code);
expect(translatedCode).toBe(`
expect(res.getStatus()).to.not.equal(404);
`);
});
});