Postman - Cant run pm.sendRequest() in collection level pre-request script
Asked Answered
S

1

8

Im using newman to run api tests after build in travis.

Im trying to limit the duplication of pre-request scripts so checked out some workarounds on how can I have pre-request-scripts at collection level.

My problem is that I dont want to run them on every request, only the ones where I need them.

Example: Im trying to run a login script to use the returned token on private endpoints.

My code looks like:

Collection level pre-request script definiton:

    Object.prototype.login = function() {
        const request = {
            url: 'somthing',
            method: 'GET',
            header: 'Content-Type:application/json',
            body: {
              mode: 'application/json',
              raw: JSON.stringify(
                {
                  email: pm.environment.get('someenv'),
                  password: pm.environment.get('someenv')
                })
            }
        };

        pm.sendRequest(request, function (err, res) {
            var response = res.json();
            pm.environment.set("token", response.token);
        });
    }

Request level pre-request script definiton:

    _.login();

Can someone help me out why I cant run pm.sendRequest in this scope?

pm.environment.get('someenv') works like a charm, so Im not sure what to do here.

It runs fine when called from Collection level pre-request script without using the Object, but if I just put the whole request there, it will run before every request what I want to avoid in the first place.

I have tried to log some stuff out using console.log(), but it seems that the callback in pm.sendRequest() never runs.

Solarism answered 8/6, 2020 at 15:19 Comment(0)
S
5

So I have found a workaround for the issue, I hope its going to help out someone in the future :)

So its easy to setup a collection level pre-request that runs before every single request.

But to optimize this a little bit because you dont need to run every script for every request you make in a collection. You can use my solution here. :)

The issue I think is caused by:

PM object used in a different scope is not going to affect the PM object in global scope, so first you should pass global PM object as parameter for function call.

The collection level request should look like this:

login = function (pm) {
    const request = {
        url: pm.environment.get('base_url') + '/login',
        method: 'POST',
        header: {
            'Content-Type': 'application/json',
        },
        body: {
            mode: 'application/json',
            raw: JSON.stringify({
                email: pm.environment.get('email'),
                password:pm.environment.get('passwd')
            })
        }
    };

    pm.sendRequest(request, (err, res) => {
        var response = res.json();
        pm.expect(err).to.be.a('null');
        pm.expect(response).to.have.property('token')
            .and.to.not.be.empty;
        pm.globals.set("token", response.token);
    });
};

And for the exact request where you want to call auth first and use the token for the request call:

login(pm);
Solarism answered 9/6, 2020 at 10:54 Comment(2)
Can confirm this solution works. It's interesting that use can use features like pm.expect via the globally available variable from deep inside pre-request scripts, but the sendRequest method fails. That is, unless one takes your suggestion of passing it in directly from the point of use. This really got me over a hump - much appreciated.Tyson
@AdamBellas welcome to the wonders of JS silently failing. The pm.sendRequest simply isn't called. Nothing in it triggers unless I pass the pm object to the collection level.Hilda

© 2022 - 2024 — McMap. All rights reserved.