postman-runtime
Version:
Underlying library of executing Postman Collections (used by Newman)
1,001 lines (945 loc) • 55.2 kB
JavaScript
var expect = require('chai').expect,
request = require('postman-request'),
runtime = require('../../index'),
sdk = require('postman-collection');
describe('UVM', function () {
describe('Libraries and functions', function () {
it('should be available', function (mochaDone) {
var errored = false,
runner = new runtime.Runner(),
rawCollection = {
'variables': [],
'info': {
'name': 'Testing general sandbox functionality',
'_postman_id': '37a82a6b-1af6-18f5-442d-2e973fa34214',
'description': '',
'schema': 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json'
},
'item': [
{
'name': 'r1',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'try {',
' var jsonObject = xml2Json(responseBody);',
' tests["xml2Json"]=true;',
'}',
'catch(e) { tests["xml2Json"]=false; }',
'try {',
' console.log(postman.getResponseHeader("Content-Length"));',
' tests["GetResponseHeader"]=true;',
'} catch(e) { tests["GetResponseHeader"]=false; }',
'try {',
' var mykookie = postman.getResponseCookie("sails.sid");',
' tests["GetResponseCookie"]=mykookie.value;',
'} catch(e) { tests["GetResponseCookie"]=false; }',
'try { console.log("RESCOOK: " , responseCookies); } catch(e) {}',
'tests["Correct global"] = globals.g1=="0";',
'try { console.log(postman.clearEnvironmentVariables()); } catch(e) {}',
'try { console.log(postman.clearGlobalVariables()); } catch(e) {}',
'postman.setGlobalVariable("g1", "0");',
'postman.setEnvironmentVariable("e1", "0");',
'try { _.each([1], function(v) {tests[\'Lodash working\'] = true;}); }',
'catch(e) { tests[\'Lodash working\'] = false; }',
'var newString="diabetes";',
'tests["SugarJS working"]=newString.has("betes");',
'tests["tv4 present"] = (typeof tv4.validate === "function");',
// eslint-disable-next-line max-len
'tests["CryptoJS md5"] = (CryptoJS.MD5("jasonpurse") == "288d14f08b5ad40da43dbe06467729c9");'
]
}
},
{
'listen': 'prerequest',
'script': {
'type': 'text/javascript',
'exec': 'postman.setGlobalVariable("g1", "0");'
}
}
],
'request': {
'url': 'https://postman-echo.com/type/xml',
'method': 'GET',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'r2',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'tests["Status code is 200"] = responseCode.code === 200;',
'var jsonData = JSON.parse(responseBody);',
// eslint-disable-next-line max-len
'tests["Correct GUID: " + jsonData.form.guid] = jsonData.form.guid.length === 36;',
// eslint-disable-next-line max-len
'tests["Correct Random: " + jsonData.form.randomInt] = parseInt(jsonData.form.randomInt)>=0;',
// eslint-disable-next-line max-len
'tests["Correct Timestamp: " + jsonData.form.timestamp] = parseInt(jsonData.form.timestamp)>1000',
'tests["Correct global"] = jsonData.form.global == "0";',
'tests["Correct global2"] = jsonData.form.global == globals.g1;',
'tests["Correct envVar"] = jsonData.form.envValue == "0";',
'tests["Correct envVar2"] = jsonData.form.envValue == environment.e1;'
]
}
}
],
'request': {
'url': 'https://postman-echo.com/post',
'method': 'POST',
'header': [],
'body': {
'mode': 'formdata',
'formdata': [
{
'key': 'k1',
'value': 'v1',
'type': 'text',
'enabled': true
},
{
'key': 'k2',
'value': 'v2',
'type': 'text',
'enabled': true
},
{
'key': 'guid',
'value': '{{$guid}}',
'type': 'text',
'enabled': true
},
{
'key': 'timestamp',
'value': '{{$timestamp}}',
'type': 'text',
'enabled': true
},
{
'key': 'randomInt',
'value': '{{$randomInt}}',
'type': 'text',
'enabled': true
},
{
'key': 'global',
'value': '{{g1}}',
'type': 'text',
'enabled': true
},
{
'key': 'envValue',
'value': '{{e1}}',
'type': 'text',
'enabled': true
}
]
},
'description': ''
},
'response': []
},
{
'name': 'r3',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': 'tests["Status code is 200"] = responseCode.code === 200;'
}
}
],
'request': {
'url': 'https://postman-echo.com/put',
'method': 'PUT',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'r4',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': 'tests["Status code is 200"] = responseCode.code === 200;'
}
}
],
'request': {
'url': 'https://postman-echo.com/patch',
'method': 'PATCH',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'delete',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': 'tests["Status code is 200"] = responseCode.code === 200;'
}
}
],
'request': {
'url': 'https://postman-echo.com/delete',
'method': 'DELETE',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'head',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'tests["Status code is 200"] = responseCode.code === 200;',
'tests["Body is correct"] = responseBody === "";'
]
}
}
],
'request': {
'url': 'https://postman-echo.com/get',
'method': 'HEAD',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'options',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'tests["Status code is 200"] = responseCode.code === 200;',
'tests["Body is correct"] = !_.isEmpty(responseBody.split(","));'
]
}
}
],
'request': {
'url': 'https://postman-echo.com/get',
'method': 'OPTIONS',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'r2 copy',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': 'tests["Status code is 200"] = responseCode.code === 200;'
}
}
],
'request': {
'url': 'https://postman-echo.com/post',
'method': 'POST',
'header': [],
'body': {
'mode': 'raw',
'raw': 'RAWDATA'
},
'description': ''
},
'response': []
},
{
'name': 'BasicAuth',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'var jsonData = JSON.parse(responseBody);',
// eslint-disable-next-line max-len
'tests["Correct auth header"] = jsonData.headers.authorization.indexOf("YWJoaWppdDprYW5l")>-1;'
]
}
}
],
'request': {
'auth': {
'type': 'basic',
'basic': {
'username': 'abhijit',
'password': 'kane',
'saveHelperData': true,
'showPassword': false
}
},
'url': 'https://postman-echo.com/post',
'method': 'POST',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'DigestAuth',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'var jsonData = JSON.parse(responseBody);',
'tests["Authenticated"] = jsonData.authenticated === true;'
]
}
}
],
'request': {
'auth': {
'type': 'digest',
'digest': {
'algorithm': '',
'username': 'postman',
'realm': 'Users',
'password': 'password',
'nonce': '',
'nonceCount': '',
'clientNonce': '',
'opaque': '',
'qop': ''
}
},
'url': 'https://postman-echo.com/digest-auth',
'method': 'GET',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'Recursive Res',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'var jsonData = JSON.parse(responseBody);',
'//tests["Recur. res. working"] = jsonData.args.a == "kane";'
]
}
},
{
'listen': 'prerequest',
'script': {
'type': 'text/javascript',
'exec': [
'postman.setGlobalVariable("name1", "kane");',
'postman.setGlobalVariable("i", "1");'
]
}
}
],
'request': {
'url': 'https://postman-echo.com/get?a={{name{{i}}}}',
'method': 'GET',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
},
{
'name': 'Buffer and JSON',
'request': 'postman-echo.com/get',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'tests[\'global JSON object\'] = typeof JSON.stringify === \'function\';',
'tests[\'global Buffer object\'] = !!Buffer'
]
}
}
]
}
]
},
collection = new sdk.Collection(rawCollection),
testables = {
iterationsStarted: [],
iterationsComplete: [],
itemsStarted: {},
itemsComplete: {}
}, // populate during the run, and then perform tests on it, at the end.
/**
* Since each callback runs in a separate callstack, this helper function
* ensures that any errors are forwarded to mocha
*
* @param func
*/
check = function (func) {
try { func(); }
catch (e) { (errored = true) && mochaDone(e); }
},
cookieJar = request.jar();
// Add a cookie to the Jar
cookieJar.setCookieSync(request.cookie('hi=hello'), 'https://postman-echo.com/type/xml');
runner.run(collection, {
iterationCount: 1,
abortOnFailure: true,
requester: {
cookieJar: cookieJar
}
}, function (err, run) {
var runStore = {}; // Used for validations *during* the run. Cursor increments, etc.
expect(err).to.be.null;
run.start({
start: function (err, cursor) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.deep.include({
position: 0,
iteration: 0,
length: 12,
cycles: 1,
eof: false,
empty: false,
bof: true,
cr: false
});
expect(cursor).to.have.property('ref');
// Set this to true, and verify at the end, so that the test will fail even if this
// callback is never called.
testables.started = true;
});
},
beforeIteration: function (err, cursor) {
check(function () {
expect(err).to.be.null;
testables.iterationsStarted.push(cursor.iteration);
runStore.iteration = cursor.iteration;
});
},
iteration: function (err, cursor) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.have.property('iteration', runStore.iteration);
testables.iterationsComplete.push(cursor.iteration);
});
},
beforeItem: function (err, cursor, item) {
check(function () {
expect(err).to.be.null;
testables.itemsStarted[cursor.iteration] = testables.itemsStarted[cursor.iteration] || [];
testables.itemsStarted[cursor.iteration].push(item);
runStore.position = cursor.position;
runStore.ref = cursor.ref;
});
},
item: function (err, cursor, item) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.deep.include({
position: runStore.position,
ref: runStore.ref
});
testables.itemsComplete[cursor.iteration] = testables.itemsComplete[cursor.iteration] || [];
testables.itemsComplete[cursor.iteration].push(item);
});
},
beforePrerequest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
prerequest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
beforeTest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
test: function (err, cursor, results) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
// This collection has no pre-request scripts
expect(results).to.have.lengthOf(1);
var result = results[0],
scriptResult = results[0];
expect(result.error).to.be.undefined;
expect(scriptResult).to.deep.nested.include({
'result.target': 'test'
});
// `tests` object is no longer bubbled-up in the results.
// expect(scriptResult.result.tests).to.be.ok;
// _.forOwn(scriptResult.result.tests, function (result) {
// expect(result).to.be.ok;
// });
});
},
beforeRequest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
response: function (err, cursor, response, request) {
check(function () {
expect(err).to.be.null;
expect(request.url.toString()).to.be.ok;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
expect(response).to.have.property('code', 200);
expect(request).to.be.ok;
});
},
done: function (err) {
check(function () {
expect(err).to.be.null;
expect(testables).to.have.property('started', true);
// Ensure that we ran (and completed two iterations)
expect(testables).to.deep.include({
iterationsStarted: [0],
iterationsComplete: [0]
});
expect(testables.itemsStarted[0]).to.have.lengthOf(12);
expect(testables.itemsComplete[0]).to.have.lengthOf(12);
// Expect the end position to be correct
expect(runStore).to.deep.include({
iteration: 0,
position: 11
});
!errored && mochaDone();
});
}
});
});
});
});
describe('Sugar JS', function () {
it('should expose the full functionality', function (mochaDone) {
var errored = false,
runner = new runtime.Runner(),
rawCollection = {
'variables': [],
'info': {
'name': 'NewmanSetNextRequest',
'_postman_id': 'd6f7bb29-2258-4e1b-9576-b2315cf5b77e',
'description': '',
'schema': 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json'
},
'item': [
{
'id': 'bf0a6006-c987-253a-525d-9f6be7071210',
'name': 'First Request',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
'exec': [
'var d = new Date(1470659144696);', // Monday, Aug 08, 2016
'tests[\'date prototype\'] = (\'Monday\' === d.format(\'{Weekday}\'));',
'tests[\'string prototype\'] = \'asdasd\'.has(\'as\');',
'tests[\'Object\'] = typeof Object.each === \'function\'',
'tests[\'Date.create\'] = typeof Date.create === \'function\';',
// eslint-disable-next-line max-len
'tests[\'Other Date functions\'] = !!(1).daysAfter(new Date()).format(\'{yyyy}{MM}{dd}\');'
]
}
}
],
'request': {
'url': 'https://postman-echo.com/redirect-to?url=https://postman-echo.com/get',
'method': 'GET'
}
}
]
},
collection = new sdk.Collection(rawCollection),
testables = {
iterationsStarted: [],
iterationsComplete: [],
itemsStarted: {},
itemsComplete: {}
}, // populate during the run, and then perform tests on it, at the end.
/**
* Since each callback runs in a separate callstack, this helper function
* ensures that any errors are forwarded to mocha
*
* @param func
*/
check = function (func) {
try { func(); }
catch (e) { (errored = true) && mochaDone(e); }
};
runner.run(collection, {
iterationCount: 1
}, function (err, run) {
var runStore = {}; // Used for validations *during* the run. Cursor increments, etc.
expect(err).to.be.null;
run.start({
exception: function (err) {
check(function () {
expect(err).to.be.null;
});
},
error: function (err) {
check(function () {
expect(err).to.be.null;
});
},
start: function (err, cursor) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.deep.include({
position: 0,
iteration: 0,
length: 1,
cycles: 1,
eof: false,
empty: false,
bof: true,
cr: false
});
expect(cursor).to.have.property('ref');
// Set this to true, and verify at the end, so that the test will fail even if this
// callback is never called.
testables.started = true;
});
},
beforeIteration: function (err, cursor) {
check(function () {
expect(err).to.be.null;
testables.iterationsStarted.push(cursor.iteration);
runStore.iteration = cursor.iteration;
});
},
iteration: function (err, cursor) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.have.property('iteration', runStore.iteration);
testables.iterationsComplete.push(cursor.iteration);
});
},
beforeItem: function (err, cursor, item) {
check(function () {
expect(err).to.be.null;
testables.itemsStarted[cursor.iteration] = testables.itemsStarted[cursor.iteration] || [];
testables.itemsStarted[cursor.iteration].push(item);
runStore.position = cursor.position;
runStore.ref = cursor.ref;
});
},
item: function (err, cursor, item) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.deep.include({
position: runStore.position,
ref: runStore.ref
});
testables.itemsComplete[cursor.iteration] = testables.itemsComplete[cursor.iteration] || [];
testables.itemsComplete[cursor.iteration].push(item);
});
},
beforePrerequest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
prerequest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
beforeTest: function (err, cursor, events) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
// This collection has no pre-request scripts
expect(events).to.have.lengthOf(1);
});
},
test: function (err, cursor, results) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
// This collection has no pre-request scripts
expect(results).to.have.lengthOf(1);
var scriptResult = results[0];
expect(scriptResult.error).to.be.undefined;
expect(scriptResult).to.deep.nested.include({
'result.target': 'test'
});
});
},
beforeRequest: function (err, cursor) {
check(function () {
expect(err).to.be.null;
// Sanity
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position,
ref: runStore.ref
});
});
},
request: function (err, cursor, response, request) {
check(function () {
expect(err).to.be.null;
expect(request.url.toString()).to.be.ok;
// Sanity
expect(cursor.iteration).to.eql(runStore.iteration);
expect(cursor.position).to.eql(runStore.position);
expect(cursor.ref).to.eql(runStore.ref);
expect(response).to.have.property('code', 200);
expect(request).to.be.ok;
});
},
done: function (err) {
check(function () {
err && console.error(err.stack);
expect(err).to.be.null;
!errored && mochaDone();
});
}
});
});
});
it('should work correctly with extended object prototypes', function (mochaDone) {
var errored = false,
runner = new runtime.Runner(),
rawCollection = {
'variables': [],
'info': {
'name': 'SugarJS and native prototypes work',
'_postman_id': '8f31aeff-c5b5-5c42-9540-fae109785538',
'description': 'A set of requests to test Array, String, Date, and Function prototypes',
'schema': 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json'
},
'item': [
{
'name': 'objectPrototype',
'event': [
{
'listen': 'test',
'script': {
'type': 'text/javascript',
// eslint-disable-next-line max-len
'exec': '// Extended Array prototype tests\ntests["Array prototype none"] = [\'a\', \'b\', \'c\'].none(\'d\');\ntests["Array prototype any"] = [ [1,2], [2,3] ].any([2,3]);\ntests["Array prototype average"] = [ 1, 2, 3, 4, 5 ].average() === 3;\n\n// Extended Date prototype tests\nconsole.log(Object.keys(new Date()));\ntests["Date prototype getTime"] = Date.now()==(new Date()).getTime();\ntests["Date prototype isFuture"] = Date.create(\'next week\').isFuture();\ntests["Date prototype isLeapYear"] = Date.create(\'2000\').isLeapYear();\ntests["Date prototype isPast"] = Date.create(\'last week\').isPast();\ntests["Date prototype isValid"] = new Date().isValid();\ntests["Date prototype negated isValid"] = !(new Date(\'random string\').isValid());\n\n// Extended Function prototype tests\nvar fCount = 0;\nvar fn = (function() {\n fCount++;\n}).once(); fn(); fn(); fn();\ntests["Function prototype once"] = fCount===1;\n\n// Extended Number prototype tests\ntests["Number prototype hex"] = (56).hex() === \'38\';\ntests["Number prototype isEven"] = (56).isEven() === true;\ntests["Number prototype ordinalize"] = (56).ordinalize() === \'56th\';\ntests["Number prototype format"] = (56789.10).format() === \'56,789.1\';\n\n// Extended String prototype tests\ntests["String prototype endsWith"] = \'jumpy\'.endsWith(\'py\');\ntests["String prototype negated endsWith"] = !(\'jumpy\'.endsWith(\'MPY\'));\ntests["String prototype camelize"] = \'a-beta\'.camelize() === \'ABeta\';\ntests["String prototype repeat"] = \'a\'.repeat(5) === \'aaaaa\';\ntests["String prototype shift"] = \'abc\'.shift(5) === \'fgh\';\ntests["String prototype spacify"] = \'a-b_cD\'.spacify() === \'a b c d\';'
}
}
],
'request': {
'url': 'postman-echo.com/get',
'method': 'GET',
'header': [],
'body': {
'mode': 'formdata',
'formdata': []
},
'description': ''
},
'response': []
}
]
},
collection = new sdk.Collection(rawCollection),
testables = {
iterationsStarted: [],
iterationsComplete: [],
itemsStarted: {},
itemsComplete: {}
}, // populate during the run, and then perform tests on it, at the end.
/**
* Since each callback runs in a separate callstack, this helper function
* ensures that any errors are forwarded to mocha
*
* @param func
*/
check = function (func) {
try { func(); }
catch (e) { (errored = true) && mochaDone(e); }
};
runner.run(collection, {
iterationCount: 1
}, function (err, run) {
var runStore = {}; // Used for validations *during* the run. Cursor increments, etc.
expect(err).to.be.null;
run.start({
console: function (cursor, level) {
expect(level).to.equal('log');
expect(cursor).to.deep.include({
iteration: runStore.iteration,
position: runStore.position
});
},
exception: function (err) {
check(function () {
expect(err).to.not.be.ok;
});
},
error: function (err) {
check(function () {
expect(err).to.not.be.ok;
});
},
start: function (err, cursor) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.deep.include({
position: 0,
iteration: 0,
length: 1,
cycles: 1,
eof: false,
empty: false,
bof: true,
cr: false
});
expect(cursor).to.have.property('ref');
// Set this to true, and verify at the end, so that the test will fail even if this
// callback is never called.
testables.started = true;
});
},
beforeIteration: function (err, cursor) {
check(function () {
expect(err).to.be.null;
testables.iterationsStarted.push(cursor.iteration);
runStore.iteration = cursor.iteration;
});
},
iteration: function (err, cursor) {
check(function () {
expect(err).to.be.null;
expect(cursor).to.have.property('iteration', runStore.iteration);
testables.iterationsComplete.push(cursor.iteration);
});
},
beforeItem: function (err, cursor, item) {
check(function () {
expect(err).to.be.null;
testables.itemsStarted[cursor.iteration] = testables.itemsStarted[cursor.iteration] || [];
testables.itemsStarted[cursor.iteration].push(item);
runStore.position = cursor.position;