Skip to content

Commit

Permalink
Add console warning when legacy API is used (#991)
Browse files Browse the repository at this point in the history
  • Loading branch information
coditva authored Apr 1, 2024
1 parent 6fec074 commit a0c8ec1
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
unreleased:
new features:
- GH-987 Deprecated legacy sandbox APIs
- GH-991 Added warnings in console when legacy sandbox APIs are used

4.6.1:
date: 2024-04-01
fixed bugs:
Expand Down
2 changes: 1 addition & 1 deletion lib/sandbox/execute-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.exports = function (scope, code, execution, console, timers, pmapi, onAss
execution.return.async = (timers.queueLength() > 0);

// call this hook to perform any post script execution tasks
legacy.finish(scope, pmapi, onAssertion);
legacy.finish(scope, pmapi, console, onAssertion);

function complete () {
// if timers are running, we do not need to proceed with any logic of completing execution. instead we wait
Expand Down
74 changes: 73 additions & 1 deletion lib/sandbox/postman-legacy-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,29 @@ const _ = require('lodash'),
// 'JSON', // removing JSON from the list since it is a standard JS object
],

LEGACY_GLOBS_ALTERNATIVES = {
tests: 'pm.test()',
globals: 'pm.globals',
environment: 'pm.environment',
data: 'pm.iterationData',
request: 'pm.request',
responseCookies: 'pm.cookies',
responseHeaders: 'pm.response.headers',
responseTime: 'pm.response.responseTime',
responseCode: 'pm.response.code',
responseBody: 'pm.response.text()',
iteration: 'pm.info.iteration',
_: 'require(\'lodash\')',
CryptoJS: 'require(\'crypto-js\')',
atob: 'require(\'atob\')',
btoa: 'require(\'btoa\')',
tv4: 'require(\'ajv\')',
xml2Json: 'require(\'xml2js\')',
Backbone: 'require(\'backbone\')',
cheerio: 'require(\'cheerio\')',
'postman.setNextRequest': 'pm.execution.setNextRequest()'
},

E = '',
FUNCTION = 'function',
TARGET_TEST = 'test',
Expand Down Expand Up @@ -380,6 +403,43 @@ module.exports = {
globalvars.postman = new (execution.target === TARGET_TEST ?
PostmanLegacyTestInterface : PostmanLegacyInterface)(execution, globalvars);

scope.__postman_legacy_api_usage = new Set();

// wrap all globals to ensure we track their usage to show warnings
// on access.
LEGACY_GLOBS.forEach((key) => {
if (!(globalvars[key] && ['object', 'function'].includes(typeof globalvars[key]))) {
return;
}

globalvars[key] = new Proxy(globalvars[key], {
set (target, prop, value) {
scope.__postman_legacy_api_usage.add(key);

target[prop] = value;
},

get (target, prop) {
// special handling for postman because setNextRequest is
// used a lot.
if (key === 'postman') {
scope.__postman_legacy_api_usage.add('postman.setNextRequest');
}
else {
scope.__postman_legacy_api_usage.add(key);
}

return target[prop];
},

apply (target, thisArg, args) {
scope.__postman_legacy_api_usage.add(key);

return target.apply(thisArg, args);
}
});
});

// make a final pass to ensure that the global variables are present


Expand Down Expand Up @@ -409,13 +469,25 @@ module.exports = {
*
* @param {Uniscope} scope -
* @param {Object} pmapi -
* @param {Object} console -
* @param {Function} onAssertion -
*/
finish (scope, pmapi, onAssertion) {
finish (scope, pmapi, console, onAssertion) {
if (!scope.__postman_legacy_setup) {
return;
}

if (scope.__postman_legacy_api_usage) {
scope.__postman_legacy_api_usage.forEach((key) => {
if (LEGACY_GLOBS_ALTERNATIVES[key]) {
console.warn(`Using "${key}" is deprecated. Use "${LEGACY_GLOBS_ALTERNATIVES[key]}" instead.`);
}
else if (LEGACY_GLOBS.includes(key)) {
console.warn(`Using "${key}" is deprecated.`);
}
});
}

raiseAssertionEvent(scope, pmapi, onAssertion);
},

Expand Down
115 changes: 115 additions & 0 deletions test/unit/sandbox-libraries/legacy.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
describe('sandbox library - legacy', function () {
this.timeout(1000 * 60);
var Sandbox = require('../../../'),
context;

beforeEach(function (done) {
Sandbox.createContext({}, function (err, ctx) {
context = ctx;
done(err);
});
});

afterEach(function () {
context.dispose();
context = null;
});

it('should not show a warning if no legacy vars used', function (done) {
const consoleSpy = sinon.spy();

context.on('console', consoleSpy);
context.execute(`
pm.iterationData.get('foo');
`, function (err) {
if (err) {
return done(err);
}

expect(consoleSpy).to.not.be.called;
done();
});
});

it('should show warning on using legacy vars', function (done) {
const consoleSpy = sinon.spy();

context.on('console', consoleSpy);
context.execute(`
data['foo'] = 'bar';
`, function (err) {
if (err) {
return done(err);
}

expect(consoleSpy).to.be.calledOnce;
expect(consoleSpy.firstCall.args[1]).to.equal('warn');
expect(consoleSpy.firstCall.args[2])
.to.equal('Using "data" is deprecated. Use "pm.iterationData" instead.');
done();
});
});

it('should show a warning on using legacy functions', function (done) {
const consoleSpy = sinon.spy();

context.on('console', consoleSpy);
context.execute(`
atob('a');
`, function (err) {
if (err) {
return done(err);
}

expect(consoleSpy).to.be.calledOnce;
expect(consoleSpy.firstCall.args[1]).to.equal('warn');
expect(consoleSpy.firstCall.args[2])
.to.equal('Using "atob" is deprecated. Use "require(\'atob\')" instead.');
done();
});
});

it('should show a single warning per execution for each global', function (done) {
const consoleSpy = sinon.spy();

context.on('console', consoleSpy);
context.execute(`
data['foo'] = 'bar1';
data['foo'] = 'bar2';
environment['foo'] = 'bar';
`, function (err) {
if (err) {
return done(err);
}

expect(consoleSpy).to.be.calledTwice;
expect(consoleSpy.firstCall.args[1]).to.equal('warn');
expect(consoleSpy.firstCall.args[2])
.to.equal('Using "data" is deprecated. Use "pm.iterationData" instead.');

expect(consoleSpy.secondCall.args[1]).to.equal('warn');
expect(consoleSpy.secondCall.args[2])
.to.equal('Using "environment" is deprecated. Use "pm.environment" instead.');
done();
});
});

it('should have special handling for postman.setNextRequest', function (done) {
const consoleSpy = sinon.spy();

context.on('console', consoleSpy);
context.execute(`
postman.setNextRequest('abc');
`, function (err) {
if (err) {
return done(err);
}

expect(consoleSpy).to.be.calledOnce;
expect(consoleSpy.firstCall.args[1]).to.equal('warn');
expect(consoleSpy.firstCall.args[2])
.to.equal('Using "postman.setNextRequest" is deprecated. Use "pm.execution.setNextRequest()" instead.');
done();
});
});
});

0 comments on commit a0c8ec1

Please sign in to comment.