Postman Test with comparison to global variable - postman

I want to orchestrate two requests in Postman. The first response will give me a variable. I save this id to a global variable id. In Postman this variable is usually accessible via {{id}}.
Then I send a second request with this id (like GET foo.bar/{{id}}). Now I want to check, if the id is in the result as well.
This is what I tried in the test code:
var jsonData = pm.response.json();
pm.expect(jsonData.id).to.eql({{id}});
where idis the variable from the first response (e.g. 72b302bf297a228a75730123efef7c41).
The response for the second request looks sth. like this:
{
"id": "72b302bf297a228a75730123efef7c41"
}
Here some examples which did not work either:
var jsonData = pm.response.json();
pm.expect(jsonData.id).to.eql("{{id}}");
var jsonData = pm.response.json();
var myId = {{id}};
pm.expect(jsonData.id).to.eql(myId);
My excpectation is, that the test will be positive and the `id from the request will be found in the response.
Do you have an idea how to solve this problem?
Thanks for the help.

The {{...}} syntax cannot be used like that, in the sandbox environment, you would need to access it this way.
pm.expect(jsonData.id).to.eql(pm.globals.get('id'))
The test syntax would be:
pm.test("IDs equal?", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.id).to.eql(pm.globals.get('id'))
});

Related

Postman test script - how to call an api twice to simulate 409 error

I am trying to run a few automated testing using the Postman tool. For regular scenarios, I understand how to write pre-test and test scripts. What I do not know (and trying to understand) is, how to write scripts for checking 409 error (let us call it duplicate resource check).
I want to run a create resource api like below, then run it again and ensure that the 2nd invocation really returns 409 error.
POST /myservice/books
Is there a way to run the same api twice and check the return value for 2nd invocation. If yes, how do I do that. One crude way of achieving this could be to create a dependency between two tests, where the first one creates a resource, and the second one uses the same payload once again to create the same resource. I am looking for a single test to do an end-to-end testing.
Postman doesn't really provide a standard way, but is still flexible. I realized that we have to write javascript code in the pre-request tab, to do our own http request (using sendRequest method) and store the resulting data into env vars for use by the main api call.
Here is a sample:
var phone = pm.variables.replaceIn("{{$randomPhoneNumber}}");
console.log("phone:", phone)
var baseURL = pm.variables.replaceIn("{{ROG_SERVER}}:{{ROG_PORT}}{{ROG_BASE_URL}}")
var usersURL = pm.variables.replaceIn("{{ROG_SERVICE}}/users")
var otpURL = `${baseURL}/${phone}/_otp_x`
// Payload for partner creation
const payload = {
"name": pm.variables.replaceIn("{{username}}"),
"phone":phone,
"password": pm.variables.replaceIn("{{$randomPassword}}"),
}
console.log("user payload:", payload)
function getOTP (a, callback) {
// Get an OTP
pm.sendRequest(otpURL, function(err, response) {
if (err) throw err
var jsonDaata = response.json()
pm.expect(jsonDaata).to.haveOwnProperty('otp')
pm.environment.set("otp", jsonDaata.otp)
pm.environment.set("phone", phone);
pm.environment.set("username", "{{$randomUserName}}")
if (callback) callback(jsonDaata.otp)
})
}
// Get an OTP
getOTP("a", otp => {
console.log("OTP received:", otp)
payload.partnerRef = pm.variables.replaceIn("{{$randomPassword}}")
payload.otp = otp
//create a partner user with the otp.
let reqOpts = {
url: usersURL,
method: 'POST',
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify(payload)
}
pm.sendRequest(reqOpts, (err, response) => {
console.log("response?", response)
pm.expect(response).to.have.property('code', 201)
})
// Get a new OTP for the main request to be executed.
getOTP()
})
I did it in my test block. Create your normal request as you would send it, then in your tests, validate the original works, and then you can send the second command and validate the response.
You can also use the pre and post scripting to do something similar, or have one test after the other in the file (they run sequentially) to do the same testing.
For instance, I sent an API call here to create records. As I need the Key_ to delete them, I can make a call to GET /foo at my API
pm.test("Response should be 200", function () {
pm.response.to.be.ok;
pm.response.to.have.status(200);
});
pm.test("Parse Key_ values and send DELETE from original request response", function () {
var jsonData = JSON.parse(responseBody);
jsonData.forEach(function (TimeEntryRecord) {
console.log(TimeEntryRecord.Key_);
const DeleteURL = pm.variables.get('APIHost') + '/bar/' + TimeEntryRecord.Key_;
pm.sendRequest({
url: DeleteURL,
method: 'DELETE',
header: { 'Content-Type': 'application/json' },
body: { TimeEntryRecord }
}, function (err, res) {
console.log("Sent Delete: " + DeleteURL );
});
});
});

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

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.
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);

Invalid or unexpected token when referencing #odata.count

I am currently working with an Odata endpoint and am having an issue referencing JSON values with tags including #. The console shows “SyntaxError | Invalid or unexpected token”
JSON Response Body
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.#odata.count).to.eql(73);
});
Can someone explain how I reference that value?
pm.test("Your test name", function() {
var jsonData = pm.response.json();
pm.expect(jsonData['#odata.count']).to.eql(73);
});

Export CSV of a particular request in Postman using Newman

I have a JSON Collection of Postman requests. I am running it via Newman.
Is there a way I can export the XML Response of a particular request(Not all) to a file using newman or postman
Thanks
As I know, there is no developed XML reporter for newman.
The easiest and none-blood way to quickly resolve it this is to add response parsing to certain request or to a collection (if you need for all)
In tests you can add:
let responseJSON = JSON.parse(responseBody)
tests["Status code is 200"] = responseCode.code === 200;
if(responseCode.code !== 200)
{
console.log(responseJSON);
return;
}
OR
try {
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("jwt_token", jsonData.data.token);
} catch (err) {
console.log(err);
}
OR if you don't need to output it only after an error, then put just:
var body = JSON.parse(responseBody)
console.log(body);

how to stub a function that returns an object in QUnit?

I have the following lines in my SAPUI5 app
var dateVal = controls.awardDate.getDateValue();
var month = dateVal.getMonth();
awardDate is a datepicker the user enters a date on and returns a javascript date object. This is a snippet of my qunit to test this element.
awardDate: {
getValue: getInvalidValue,
getValueState: getValueStateWarning,
setValue: setValue,
getDatevalue: getDateValue
}
In my qunit I get an error saying that the object doesn't support property or method 'getDateValue'. I'm not sure how I'm supposed to stub this function when it returns an object. Other tests I have do it this way
var getValue = sinon.stub().returns('');
where I get an empty string.
so my attempt at to do it with the datepicker is
var getDateValue = sinon.stub().returns(new Date());
but this doesn't work. I still get the same error. Has anyone done this before?
edit/update: I was able to fix part of the problem by doing the following
var getValueDate = sinon.stub().returns(Object, function(){ });
Now the problem I have is the same error but for getMonth() which returns a string. All other variables are global but dateVal is created on the spot when the user updates the datepicker. Any ideas on how to proceed on this one?
Try with this code:
var getValueDate = sinon.stub(controls.awardDate, 'getDateValue');
var month = {
getMonth: sinon.stub()
}
getValueDate.returns([month]);
I was able to figure out how to solve this. I had to make the Object type a specific Date object like this
var getValueDate = sinon.stub().returns(new Date()), function(){ });