Skip to content

Commit

Permalink
chore: add channel-beta postman collection dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
vedkribhu committed Sep 7, 2023
1 parent 5e890c2 commit 5d00855
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 25 deletions.
7 changes: 5 additions & 2 deletions lib/sandbox/console.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const dispatchEvent = require('./dispatch-event');

var teleportJS = require('teleport-javascript'),

arrayProtoSlice = Array.prototype.slice,
Expand Down Expand Up @@ -45,7 +47,7 @@ function replacer (key, value) {
return value;
}

function PostmanConsole (emitter, cursor, originalConsole) {
function PostmanConsole (emitter, cursor, originalConsole, execution) {
const dispatch = function (level) { // create a dispatch function that emits events
const args = arrayProtoSlice.call(arguments, 1);

Expand All @@ -54,7 +56,8 @@ function PostmanConsole (emitter, cursor, originalConsole) {
originalConsole[level].apply(originalConsole, args);
}

emitter.dispatch(CONSOLE_EVENT, cursor, level, teleportJS.stringify(args, replacer));

dispatchEvent(emitter, execution, CONSOLE_EVENT, cursor, level, teleportJS.stringify(args, replacer));
};

// setup variants of the logger based on log levels
Expand Down
7 changes: 5 additions & 2 deletions lib/sandbox/cookie-store.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const dispatchEvent = require('./dispatch-event');

const _ = require('lodash'),

Store = require('@postman/tough-cookie').Store,
Expand All @@ -14,12 +16,13 @@ const _ = require('lodash'),
arrayProtoSlice = Array.prototype.slice;

class PostmanCookieStore extends Store {
constructor (id, emitter, timers) {
constructor (id, emitter, timers, execution) {
super();

this.id = id; // execution identifier
this.emitter = emitter;
this.timers = timers;
this.execution = execution;
}
}

Expand Down Expand Up @@ -77,7 +80,7 @@ STORE_METHODS.forEach(function (method) {
// Refer: https://github.com/postmanlabs/postman-app-support/issues/11064
setTimeout(() => {
// finally, dispatch event over the bridge
this.emitter.dispatch(eventName, eventId, EVENT_STORE_ACTION, method, args);
dispatchEvent(this.emitter, this.execution, eventName, eventId, EVENT_STORE_ACTION, method, args);
});
};
});
Expand Down
15 changes: 15 additions & 0 deletions lib/sandbox/dispatch-event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
*
* @param {any} bridge - the bridge object
* @param {{ shouldSkipExecution: boolean }} execution - the execution object
* @param {string} event - the event name
* @param {...any} args - the arguments to be passed to the event
*/
module.exports = function dispatchEvent (bridge, execution, event, ...args) {
// if the execution is skipped, do not dispatch the event
if (execution && execution.shouldSkipExecution) {
return;
}

bridge.dispatch(event, ...args);
};
49 changes: 29 additions & 20 deletions lib/sandbox/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const _ = require('lodash'),
EXECUTION_ASSERTION_EVENT = 'execution.assertion',
EXECUTION_ASSERTION_EVENT_BASE = 'execution.assertion.',

executeContext = require('./execute-context');
executeContext = require('./execute-context'),
dispatchEvent = require('./dispatch-event');

module.exports = function (bridge, glob) {
// @note we use a common scope for all executions. this causes issues when scripts are run inside the sandbox
Expand Down Expand Up @@ -49,7 +50,7 @@ module.exports = function (bridge, glob) {
if (!template) {
chai.use(require('chai-postman')(sdk, _, Ajv));

return bridge.dispatch('initialize');
return dispatchEvent(bridge, null, 'initialize');
}

const _module = { exports: {} },
Expand All @@ -66,7 +67,7 @@ module.exports = function (bridge, glob) {

scope.exec(template, (err) => {
if (err) {
return bridge.dispatch('initialize', err);
return dispatchEvent(bridge, null, 'initialize', err);
}

const { chaiPlugin, initializeExecution: setupExecution } = (_module && _module.exports) || {};
Expand All @@ -79,7 +80,7 @@ module.exports = function (bridge, glob) {
initializeExecution = setupExecution;
}

bridge.dispatch('initialize');
dispatchEvent(bridge, null, 'initialize');
});
});

Expand All @@ -97,7 +98,8 @@ module.exports = function (bridge, glob) {
*/
bridge.on('execute', function (id, event, context, options) {
if (!(id && _.isString(id))) {
return bridge.dispatch('error', new Error('sandbox: execution identifier parameter(s) missing'));
return dispatchEvent(bridge, null, 'error',
new Error('sandbox: execution identifier parameter(s) missing'));
}

!options && (options = {});
Expand All @@ -114,9 +116,9 @@ module.exports = function (bridge, glob) {

// extract the code from event. The event can be the code itself and we know that if the event is of type
// string.
code = _.isFunction(event.script && event.script.toSource) && event.script.toSource(),
code = _.isFunction(event.script && event.script.toSource) && event.script.toSource();
// create the execution object
execution = new Execution(id, event, context, { ...options, initializeExecution }),
let execution = new Execution(id, event, context, { ...options, initializeExecution }),

/**
* Dispatch assertions from `pm.test` or legacy `test` API.
Expand All @@ -136,20 +138,19 @@ module.exports = function (bridge, glob) {
// For compatibility, dispatch the single assertion as an array.
!Array.isArray(assertions) && (assertions = [assertions]);

bridge.dispatch(assertionEventName, options.cursor, assertions);
bridge.dispatch(EXECUTION_ASSERTION_EVENT, options.cursor, assertions);
};

let waiting,
dispatchEvent(bridge, execution, assertionEventName, options.cursor, assertions);
dispatchEvent(bridge, execution, EXECUTION_ASSERTION_EVENT, options.cursor, assertions);
},
waiting,
timers;

execution.return.async = false;

// create the controlled timers
timers = new PostmanTimers(null, function (err) {
if (err) { // propagate the error out of sandbox
bridge.dispatch(errorEventName, options.cursor, err);
bridge.dispatch(EXECUTION_ERROR_EVENT, options.cursor, err);
dispatchEvent(bridge, execution, errorEventName, options.cursor, err);
dispatchEvent(bridge, execution, EXECUTION_ERROR_EVENT, options.cursor, err);
}
}, function () {
execution.return.async = true;
Expand All @@ -169,16 +170,17 @@ module.exports = function (bridge, glob) {
bridge.off(cookiesEventName);

if (err) { // fire extra execution error event
bridge.dispatch(errorEventName, options.cursor, err);
bridge.dispatch(EXECUTION_ERROR_EVENT, options.cursor, err);
dispatchEvent(bridge, execution, options.cursor, err);
dispatchEvent(bridge, execution, options.cursor, err);
}

// @note delete response from the execution object to avoid dispatching
// the large response payload back due to performance reasons.
execution.response && (delete execution.response);

// fire the execution completion event
(dnd !== true) && bridge.dispatch(executionEventName, err || null, execution);
(dnd !== true) && dispatchEvent(bridge, { shouldSkipExecution: false },
executionEventName, err || null, execution);
});

// if a timeout is set, we must ensure that all pending timers are cleared and an execution timeout event is
Expand Down Expand Up @@ -207,14 +209,21 @@ module.exports = function (bridge, glob) {
executeContext(scope, code, execution,
// if a console is sent, we use it. otherwise this also prevents erroneous referencing to any console
// inside this closure.
(new PostmanConsole(bridge, options.cursor, options.debug && glob.console)),
(new PostmanConsole(bridge, options.cursor, options.debug && glob.console, execution)),
timers,
(
new PostmanAPI(execution, function (request, callback) {
var eventId = timers.setEvent(callback);

bridge.dispatch(executionRequestEventName, options.cursor, id, eventId, request);
}, dispatchAssertions, new PostmanCookieStore(id, bridge, timers), {
dispatchEvent(bridge, execution, executionRequestEventName, options.cursor, id, eventId, request);
}, function () {
execution.shouldSkipExecution = true;
timers.terminate(null, true);

// disable further edits on execution
execution = JSON.parse(JSON.stringify(execution));
},
dispatchAssertions, new PostmanCookieStore(id, bridge, timers, execution), {
disabledAPIs: initializationOptions.disabledAPIs
})
),
Expand Down
1 change: 1 addition & 0 deletions lib/sandbox/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Execution {
this.id = id;
this.target = event.listen || PROPERTY.SCRIPT;
this.legacy = options.legacy || {};
this.shouldSkipExecution = false;
this.cursor = _.isObject(options.cursor) ? options.cursor : {};

this.data = _.get(context, PROPERTY.DATA, {});
Expand Down
7 changes: 6 additions & 1 deletion lib/sandbox/pmapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ const _ = require('lodash'),
*
* @param {Execution} execution -
* @param {Function} onRequest -
* @param {Function} onSkipRequest - callback to execute when pm.skipRequest called
* @param {Function} onAssertion -
* @param {Object} cookieStore -
* @param {Object} [options] -
* @param {Array.<String>} [options.disabledAPIs] -
*/
function Postman (execution, onRequest, onAssertion, cookieStore, options = {}) {
function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, options = {}) {
// @todo - ensure runtime passes data in a scope format
let iterationData = new VariableScope();

Expand Down Expand Up @@ -273,6 +274,10 @@ function Postman (execution, onRequest, onAssertion, cookieStore, options = {})
return chai.expect(this).to;
}
});

Object.defineProperty(this.request, 'stopExecution', {
value: onSkipRequest
});
}

iterationData = null; // precautionary
Expand Down
116 changes: 116 additions & 0 deletions test/unit/sandbox-libraries/pm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,122 @@ describe('sandbox library - pm api', function () {
}, done);
});

it('should not execute any line after pm.request.stopExecution in pre-request script', function (done) {
context.on('console', function (level, ...args) {
expect(args[1]).to.equal('pre-request log 1');
});
context.execute(`
preRequestScript: {
console.log('pre-request log 1');
pm.request.stopExecution();
console.log('pre-request log 2');
}
`, {
timeout: 200,
context: {
request: 'https://postman-echo.com/get?foo=bar'
}
}, function (err, execution) {
if (err) { return done(err); }
expect(execution).to.include({ shouldSkipExecution: true });

return done();
});
});

it(`should not execute any line after pm.request.stopExecution in pre-request script,
even if the pm.request.stopExecution invoked inside a try catch block`, function (done) {
context.on('console', function (level, ...args) {
// console.log(args);
expect(args[1]).to.equal('pre-request log 1');
});
context.execute(`
preRequestScript: {
console.log('pre-request log 1');
try {
pm.request.stopExecution();
} catch (err) {
// ignore
}
console.log('pre-request log 2');
}
`, {
timeout: 200,
context: {
request: 'https://postman-echo.com/get?foo=bar'
}
}, function (err, execution) {
if (err) { return done(err); }
expect(execution).to.include({ shouldSkipExecution: true });

return done();
});
});

it(`should not execute any line after pm.request.stopExecution in pre-request script,
even if the pm.request.stopExecution invoked inside an async function`, function (done) {
context.on('console', function (level, ...args) {
expect(args[1]).to.equal('pre-request log 1');
});
context.execute(`
preRequestScript: {
console.log('pre-request log 1');
async function myAsyncFunction() {
pm.request.stopExecution();
}
myAsyncFunction();
console.log('pre-request log 2');
}
`, {
timeout: 200,
context: {
request: 'https://postman-echo.com/get?foo=bar'
}
}, function (err, execution) {
if (err) { return done(err); }
expect(execution).to.include({ shouldSkipExecution: true });

return done();
});
});

it('should not reflect any variable change line after pm.request.stopExecution in pre-request script',
function (done) {
context.on('console', function (level, ...args) {
expect(args[1]).to.equal('pre-request log 1');
});
context.execute(`
preRequestScript: {
async function myFun () {
console.log('pre-request log 1');
pm.variables.set('foo', 'bar');
pm.request.stopExecution();
new Promise((res) => setTimeout(res, 100))
pm.variables.set('foo', 'nobar');
console.log('pre-request log 2');
}
myFun();
}
`, {
timeout: 200,
context: {
request: 'https://postman-echo.com/get?foo=bar'
}
}, function (err, execution) {
if (err) { return done(err); }
expect(execution).to.include({ shouldSkipExecution: true });
expect(execution).to.deep.nested.include({ '_variables.values': [
{ value: 'bar', key: 'foo', type: 'any' }
] });

return done();
});
});

it('when serialized should not have assertion helpers added by sandbox', function (done) {
context.execute(`
var assert = require('assert'),
Expand Down

0 comments on commit 5d00855

Please sign in to comment.