This document describes one way to load external JavaScript modules into Postman pre-request or test scripts to augment the functionality of your own scripts.
In the collection pre-request script, export common utility functions (feel free to add additional functions for your own use case as this is a common technique for sharing code among individual requests):
// get latest version
_ = require('lodash');
// export common utility functions
pm.globals.set('util', String(() => ({
// use the open interval hack to wait until async
// operations are done before sending the request
// in a pre-request script
waitUntilDone(promise) {
const wait = setInterval(() => {}, 300000);
promise.finally(() => clearInterval(wait));
},
// promisified pm.sendRequest()
sendRequest(req) {
return new Promise(
(resolve, reject) => pm.sendRequest(req, (err, res) => {
if (!err && res.code / 100 < 4) return resolve(res);
let message = `Request "${req.url||req}" failed (${res.code})`;
if (err?.message) message += `: ${err.message}`;
reject({message});
}));
},
// load external library modules in order,
// then return this[thisProp] or just this
async loadModules(urls, thisProp=undefined) {
const thisKeys = Object.keys(this);
(await Promise.all(urls.map(this.sendRequest)))
.forEach(res => eval(res.text()));
const thisObj = _.omit(this, thisKeys);
//console.log('KEYS: this', Object.keys(thisObj));
return !thisProp && thisObj || thisObj[thisProp];
},
decodeJWT(jwt) {
// return both header and claims
return jwt?.split('.').slice(0, 2)
.reduce((claims, encoded) => {
const buf = Buffer.from(encoded, 'base64');
const props = JSON.parse(buf.toString('utf8'));
return Object.assign(claims, props);
}, {})
|| {};
},
})));
Then, in the pre-request script of some request in the same collection, load modules that you need in an async manner (the sample code below loads moment.js
; it should work equally well for other JavaScript modules that are distributed via CDN):
const util = eval(pm.globals.get('util'))();
const vars = pm.variables;
const coVars = pm.collectionVariables;
// this isn't important... just some sample code.
const jwt = util.decodeJWT(vars.get('app_token'));
util.waitUntilDone((async () => {
const [
{rat}, // get "revoked_at" in first API call
{moment}, // load "moment.js" JavaScript modules
] = await Promise.all([
util.sendRequest({
url: `${vars.get('my_api_url')}/apps/${jwt.sub}/tokens/${jwt.jti}`,
header: {
Authorization: `Bearer ${vars.get('superuser_token')}`,
},
})
.then(res => res.json())
.catch(err => ({})),
util.loadModules([
'https://momentjs.com/downloads/moment.min.js',
'https://momentjs.com/downloads/moment-timezone-with-data.min.js',
]),
]);
// use "moment" as it's now loaded
const tsToDate = ts => {
const date = new Date(ts);
let str = moment(date).format('L hh:mm:ss A');
const tz = moment.tz(date, moment.tz.guess());
const dur = moment.duration(date - new Date());
return `${str} ${tz.zoneAbbr()} (${dur.humanize(true)})`;
};
vars.set('iat', tsToDate(jwt.iat));
vars.set('exp', tsToDate(jwt.exp));
vars.set('rat', tsToDate(rat));
})());