2

In Postman, I'm trying to achieve the following:

  1. In a collection:
    1. Create a utility object containing reusable functions
    2. Store that utility object in a global variable for later use in request test scripts.
  2. In a request:
    1. Pull the utility object code out of the global variables.
    2. Eval the code and store the resulting utility object instance in a local variable.
    3. Invoke a method on the utility object instance.

None of the many implementations I've seen scattered across the web seem to work, though. I can get all the way down to step 2.2, and then things just die a horrible flaming death. The JavaScript engine beneath Postman refuses to evaluate the object stored in the globals collection.

To isolate the issue, I've stripped this down to a bare minimum script, which is placed in the pre-request scripts for my collection:

postman.setGlobalVariable("loadUtils", function utils() {
    let utils = {};
    utils.main = function() {
        console.log("Hello, world!");
    }
    return utils;
} + ';utils()');

I then try to load this script as follows:

var code = globals.loadUtils;
console.log(code);
var utils = eval('(' + code + ')');

But the following error always occurs:

There was an error in evaluating the test script: SyntaxError: Unexpected token ;

I tried:

  • Converting the entire function to a multi-line string and storing that result in the globals environment. The same error occurred.
  • Including the enclosing parentheses directly in the function body. That didn't work, either.
  • Using lambda expressions, but that caused all sorts of problems in the editor itself.

I'm certain that this is something simple, stupid, and obvious, and that I am just not seeing it.

Can someone please point out what I am doing wrong here?

P.S. This should be possible, as suggested here on StackOverflow and the Postman forums on GitHub (though it requires some scrolling through the comments to see the solution).

Mike Hofer
  • 16,477
  • 11
  • 74
  • 110

2 Answers2

2

You store two statements as a string, which are seperated by a semicolon:

 "function utils() { /*...*/ }; utils()"

then you wrap that string in parentheses and try to execute it:

eval("(function { /*...*/ }; utils())")

that won't work, as a ; inside of an expression is a syntax error.

You either remove the parens, replace the semicolon with a colon or use an IIFE (which I'd favor here):

eval("(" + someFunc + ")()");
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • That's really odd. That's the techinique used on the most upvoted answer to [this question](https://stackoverflow.com/questions/45673961/how-to-write-global-functions-in-postman), which is almost the same problem I'm having. – Mike Hofer Mar 26 '19 at 18:45
  • @mike no it isn't. `eval(globals.loadUtils)` <- no parens – Jonas Wilms Mar 26 '19 at 18:46
  • I'm referring to the two semicolons -- it's in the top code block, where he has `} + '; loadUtils();');`. But it's neither here nor there. In the end, Do you think I need to add an additional set of parentheses? – Mike Hofer Mar 26 '19 at 18:48
2

Instead of using eval, add something like the following to your Collection's pre request script.

/* You can add collection level functions to this utils object that will be available throughout 
 the collection's requests' pre-request scripts and tests. */
utils = {
    /** This is an example function
     * @param pm pass the current pm so that this has the correct context
    */
    reusableFunction: function(pm) {
        console.log("do something amazing here instead of just logging, including manipulating environment or request, access the response, etc. That is why you pass in the pm. Request: " + JSON.stringify(pm.request));
    }
}

This function is usable in any of the collection request's pre-request script or tests. enter image description here

successhawk
  • 3,071
  • 3
  • 28
  • 44