A workaround for using libraries in Postman

Hi!

I was pretty unsatisfied with the functionality regarding loading libraries into Postman. I really disliked having to go into my environment file, copy the code out, paste it into another editor, then add it back to the environment. So, I came up with a solution! LOAD!

Now, this DOES require a necessary evil. The following LOAD function needs to be stored in your globals, at least once.
(arg I canā€™t figure out how to format code hereā€¦)

Script = require(ā€˜postman-collectionā€™).Script;
function LOAD(library) {

const pullLibrary = {
    url: 'https://api.getpostman.com/collections/' + pm.environment.get(collection),
    method: 'GET',
    header: {
        'X-Api-Key': environment.postmanApiKey
    }
};
let x;
if (library == 'all') {
pm.sendRequest(pullLibrary, function(err, res) {
  for(x in res.json().collection.item[0].item){
script = new Script(res.json().collection.item[0].item[x].event[0].script);
pm.environment.set('' + res.json().collection.item[0].item[x].name, script.toSource());
console.log('loaded ' + res.json().collection.item[0].item[x].name);
   } 
});
} else {
    pm.sendRequest(pullLibrary, function(err, res) {
        let foundLibrary = (_.findWhere(res.json().collection.item[0].item, {
            name: library
        }));
        if(foundLibrary){
        script = new Script(foundLibrary.event[0].script);
        pm.environment.set('' + foundLibrary.name, script.toSource());
        console.log('loaded ' + foundLibrary.name);
        } else {
            throw new Error('library ' + library + ' does not exist!');
        }
    });
};

};

  1. First, you need to save the LOAD script into your globals,
  2. Then, create a new collection in your workspace called ā€œLibrariesā€
  3. Add a new environment variable named collection, and set it to use the ā€˜Libraryā€™ collectionā€™s uuid provided by the Postman API, e.g. 1234123-abc12345-aaaa-bbbb-cccc-123456789123
  4. Create a subfolder called ā€œScriptsā€
  5. This is where you would create new requests. Put any code you want to reuse in the ā€œTestsā€ tab. You can add as many requests as you like, each containing their own special code.
  6. Create another environment variable, postmanApiKey, which will contain your postman api key.
  7. Run eval(globals.LOAD) in any pre-request, then LOAD(ā€˜allā€™)
  8. After that, you can call any script saved this way just by using eval(environment.yourRequestScriptsName).

While this is still using the old, typical solution of cluttering up the environment file, it allows you to edit your scripts in an actual editor, without having to copy and paste them in and out of the environment. LOAD only really needs to be run once at the beginning of a run, just to pick up any changes made to your library.

If anyone has any questions, tips, or improvements, please let me know! Iā€™m still new to javascript and have a lot to learn.

7 Likes

Nice work @akaczinski!

If I understand correctly, is the main aim here to ease sharing of common snippets between workspaces since global/environment variable scope is limited to a workspace?

Itā€™s a clever approach to use the Postman API to fetch resources from one part of Postman for use in another!

Along the same lines as this, I put together a pre-request script and local server that allows you to pull in external modules not included in the sandbox:

Iā€™m going to review your snippet a little more to see if thereā€™s improvements I can make to the way Iā€™m executing my script, and, perhaps you might like to flick through mine for the same.

2 Likes

I really like your approach, your code is much neater than mine. I really dig the approach using the global variable require, makes it much more intuitive to use, itā€™s very clever! I think I might implement some of your methods, specifically using require and storing all packages in one variable.

I should probably go through mine again anyways and see if thereā€™s a way to neaten it up or download all at once (as opposed to a bunch of requests). Just realized it is missing the Postman Scripts require at the top, somehow the post deleted it, will fix that in my op. Might be a way to use that to process the scripts without using eval, actually.

Only thing I can really think of is maybe adding an update check to the local server when pkgs returns installed, but Iā€™m not really sure how important checking for updates would be.

2 Likes

Wow I was going to post a use case of as a Tess developer I want to create a postman library so I can maintain common routines efficiently,

But I think hopefully you have answered it - will study and feedback!!!

1 Like

I updated @akaczinski code (a huge thanks to him toiling around for a rather elegant hack to this problem) to accept an array and be a bit clearer and concise as well as have better names and to use the global scope for variables rather than environment. I also used a convention I started where I adopted this script to reference variables not in Requests or JSON and that live strictly within Postman with an _. Here is the modified code and modified steps below:

function _includeLibrary(library) {
    let Script = require('postman-collection').Script

    const postmanApiRequest = {
        url: 'https://api.getpostman.com/collections/' + pm.globals.get('_includeLibrariesCollectionUuid'),
        method: 'GET',
        header: {
            'X-Api-Key': pm.globals.get('_postmanApiKey')
        }
    }

    pm.sendRequest(postmanApiRequest, function (err, res) {
        if (_.isArray(library)) {
            _.forEach(library, function (libraryName) {
                if (libraryName == 'all') {
                    throw new Error('_includeLibrary: The library "all" cannot be in an array of libraries to include.')
                }

                const foundLibrary = (_.findWhere(res.json().collection.item[0].item, {
                    name: libraryName
                }))

                if (foundLibrary) {
                    script = new Script(foundLibrary.event[0].script)
                    pm.globals.set('' + foundLibrary.name, script.toSource())
                    console.log('_includeLibrary: Loaded the "' + foundLibrary.name + '" library.')
                } else {
                    throw new Error('_includeLibrary: The library "' + libraryName + '" does not exist.')
                }
            })
        } else if (_.isString(library)) {
            switch (library) {
                case '':
                case '*':
                case 'all':
                    for (const x in res.json().collection.item[0].item) {
                        script = new Script(res.json().collection.item[0].item[x].event[0].script)
                        pm.globals.set('' + res.json().collection.item[0].item[x].name, script.toSource())
                        console.log('_includeLibrary: Library "' + res.json().collection.item[0].item[x].name + '" loaded.')
                    }
                    break
                default:
                    _includeLibrary([library])
                    break
            }
        } else {
            _includeLibrary('*')
        }
    })
}
  1. First, you need to save the script into a variable named _includeLibrary into your Global variables
  2. Create a new collection in your workspace named ā€œ_includedLibrariesā€
  3. Add a new Global variable named _includeLibrariesCollectionUuid and set it to use the _includeLibrariesCollection collectionā€™s UUID provided by the Postman API (e.g. 1234123-abc12345-aaaa-bbbb-cccc-123456789123)
  4. Create a folder in the _includeLibrariesCollection called ā€œscriptsā€
  5. This is where you would create new Requests. Put ALL code you want to reuse in the ā€œTestsā€ tab and there is no need to fill out anything else. You can add as many Requests as you like, each containing their own special code.
  6. Create another Global variable, _postmanApiKey, which will contain your Postman API key.
  7. Run eval(pm.globals.get(ā€™_includeLibrariesFunctionā€™)) and then _includeLibrary([ā€˜fooā€™, ā€˜barā€™, ā€˜external-minified-jsā€™]) in any Pre-Request Test. Optionally you can specify: _includeLibrary(ā€™*ā€™) to include ALL of the scripts you have saved.
  8. After that, you can call any script saved this way just by using eval(pm.globals.get(ā€˜fooā€™)) and then subsequently calling any functions defined in those scripts with this.myHelloWorldFunction() (note the this).

EDIT: The text formatting tool for whatever Postman is using for these community boards is AWFUL!

2 Likes

Wow I love seeing the progression of this, @johnwyles and @akaczinski ! Iā€™ll try it out myself too.

& yes, unfortunately the code formatting ability in discourse isnā€™t ideal :-/