POSTMAN - Test failure false to be truthy - api

As a beginner I have few questions. I am using the Get request, which would populate json below.
https://reqres.in/api/users
{
"total": 12,
"total_pages": 4,
"data": [{
"id": 1,
"first_name": "George",
"last_name": "Bluth",
"avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
}]
}
for the 2 tests below while the 1st one passes the 2nd test fails with the message:
AssertionError: expected false to be truthy
//Verify Page number total is 12
var jsonData = JSON.parse(responseBody);
tests["Checking total page number-Manual"] = jsonData.total === 12;
//verify is exists and is 1
var jsonData = JSON.parse(responseBody);
tests["Checking ID exists and is 1"] = jsonData.id === 1;
Question 1:
A github post that I found says there may be an error and suggests to use
the new pm.* equivalent instead. However I do not see any difference between the 1st and the 2nd. So why does the 2nd test fail?
Question 2:
Is it possible to write test to verify that for ID:1 the firstname is George?
Thanks in advance for your time.

The reason that your 2nd test fails is because data is an array and in this case you must access the first element. You would want to do something like this (new syntax):
pm.test("Verify id is equal to 1", function() {
var jsonData = pm.response.json();
pm.expect(jsonData.data[0].id).to.equal(1);
});
Similarly for testing first name is George:
pm.test("Verify id is equal to 1", function() {
var jsonData = pm.response.json();
pm.expect(jsonData.data[0].first_name).to.equal("George");
});
If you always expect it to only be a single element in the array then you're safe to use index 0 i.e. data[0]. However if you expect there to be more elements in the data array then you would have to iterate through them to look for the correct element.
Here's a good reference for the API:
https://learning.getpostman.com/docs/postman/scripts/postman_sandbox_api_reference/

Related

How to iterate over a dynamic array of objects and use each object as a parameter in test?

I started my adventure with Karate a month ago. I have a simple GET test called getAllCars.feature showing a list of cars currently available:
[
{
"brandName": "BMW",
"id": 1,
"winterTires": false,
"modelName": "X5"
},
{
"brandName": "Opel",
"id": 34,
"winterTires": true,
"modelName": "Insignia"
},
{
"brandName": "Mercedes-Benz",
"id": 36,
"winterTires": true,
"modelName": "GLE Coupe"
},
{
"brandName": "Huydai",
"id": 251,
"winterTires": false,
"modelName": "i30"
}
]
I have to use each id as a parameter for the next feature file, the problem is, the list of cars is dynamic, ids don't repeat and I will have to use this list of ids for several other feature files. I managed to create a helper getCarIds.feature, which creates an array of objects "carId": "#number":
Feature: Get car IDs
Scenario: Get car IDs
* call read('classpath:x/automation/cars/getAllCars.feature')
* def carIds = $response[*].id
* def carFeeder = karate.mapWithKey(carIds, 'carId')
The following getCarParameters.feature has to iterate over the array from getCarIds.feature and pass each id as a parameter to get a response with performance parameters of each car and I don't know how to use each id separately as a parameter (keeping in mind that the list of ids is changing):
Feature: Get parameters of each car
Scenario: Get parameters for each car
* call read('classpath:x/automation/cars/getCarIds.feature')
Given url carUrl + '/carparameters'
And param carId =
When method GET
Then status 200
I managed to do it when passing the values from getCarIds.feature to getCarParameters.feature like described here by adding following line to getCarIds.feature:
* call read('classpath:x/automation/cars/getCarParameters.feature') carFeeder
but several other tests require car ids. I need getCarIds.feature to be reusable, so I would have to retrieve data from feature file, which creates the array with ids, instead of passing it to the GET feature and apparently it isn't so easy. Maybe my approach is completely wrong.
I think this is a valid case for karate.callSingle(): https://github.com/karatelabs/karate#karatecallsingle
So you can actually stick this in any feature and it is guaranteed to execute only once across your test suite. If the data is indeed something used by a majority of your test suite, you could even do this initialization in karate-config.js.
So this should work. First the reusable feature common.feature. Instead of the hard-coded response, you know how to make an actual HTTP request.
#ignore
Feature:
Scenario:
* def response =
"""
[
{
"brandName": "BMW",
"id": 1,
"winterTires": false,
"modelName": "X5"
},
{
"brandName": "Opel",
"id": 34,
"winterTires": true,
"modelName": "Insignia"
}
]
"""
* print 'getting car ids'
* def carIds = response.map(x => ({ id: x.id }))
Note the use of the JS map() function above, which I have started to recommend instead of JsonPath.
And here is a feature that uses the above. This uses the new #setup annotation that makes it easy to "loop": https://github.com/karatelabs/karate#setup
You can try this example quickly, and watch it make 2 requests using a param id from the loop.
Feature:
#setup
Scenario:
* def data = karate.callSingle('call-single-common.feature').carIds
Scenario Outline:
* url 'https://httpbin.org/get'
* param id = id
* method get
Examples:
| karate.setup().data |
There are other ways to loop, refer: https://github.com/karatelabs/karate#data-driven-features

Filtering dstore collection against an array field

I'm trying to filter a dstore collection by a field that has an array of values. My json data looks like the following (simplified):
[{
user_id: 1,
user_name: "John Doe",
teams: [{team_id: 100, team_name: 'Red Sox'}, {team_id: 101, team_name: 'Buccaneers'}]
},
{
user_id: 2,
user_name: "Fred Smith",
teams: [{team_id: 100, team_name: 'Buccaneers'}, {team_id: 102, team_name: 'Rays'}]
}]
I can do a simple filter against the username field and it works perfectly.
this.dstoreFilter = new this.dstore.Filter();
var results = this.dgrid.set('collection', this.dstore.filter(
this.dstoreFilter.match('user_name',new RegExp(searchTerm, 'i'))
));
How, though, do I construct a filter to show me only those players who play for the Red Sox, for example. I've tried using the filter.contains() method, but I can't find any adequate documentation on how it works. Looking at the dstore code, I see that the filter.contains() method has the following signature: (value, required, object, key), but that's not helping me much.
Any guidance would be much appreciated. Thanks in advance!
You can find documentation on Filtering here.
In your case, .contains() will not work because it is intended to work on values of array type. What you want to filter here is array of objects. Here is a quote from the doc link:
contains: Filters for objects where the specified property's value is an array and the array contains any value that equals the provided value or satisfies the provided expression.
In my opinion, the best way here is to override the filter method where you want to filter by team name. Here is some sample code:
this.grid.set('collection', this.dstore.filter(lang.hitch(this, function (item) {
var displayUser = false;
for(var i=0; i < item.teams.length; i++){
var team = item.teams[i];
if(team.team_name == 'Red Sox'){
displayUser = true;
break;
}
}
return displayUser;
})));
this.grid.refresh();
For each user in the store, if false is returned, it's display is set to false and if true is returned it gets displayed. This is by far the easiest way that I know of to apply complex filtering on dstore.
Some similar questions that you might want to read up: link, link, link

Postman JSON value check test fails

I have an API which has response as below:
"data": {
"catalog_list_items": [
{
"catalog_list_items": [
{
"catalog_list_items": [
{
"title": "L13",
"content_id": "58a85146b0000ec",
"sequence_no": 1,
"language": "hindi",
"genres": [
"xxxx"
]
I would like to create a test in postman to verify that the language key has value as 'hindi'. I am writing below test in Postman which always fails. Cannot find the reason.
var jsonData = JSON.parse(responseBody);
tests["Language is hindi"] = jsonData.data.catalog_list_items[3].language === "hindi";
However, when I use the similar structure to test sequence_no, it works fine
var jsonData = JSON.parse(responseBody);
tests["Sequence No is 1"]= jsonData.data.catalog_list_items[3].sequence_no === 1;
Can anyone shed a light for me?
I could see 3 level nested arrays in your response body.
So I don't know how are you getting your value through this expression:
jsonData.data.catalog_list_items[3].language
The correct expression to get the 'language' key from above response should be:
jsonData.data.catalog_list_items[0].catalog_list_items[0].catalog_list_items[0].language

How to generate jQuery DataTables rowId client side?

The jQuery DataTables reference shows an example of setting the rowId option to a column from the data source (server side). This setting is used for the "select" extension and retaining row selection on Ajax reload.
Is there any way to generate the row identifier value 1) client side, or 2) as a combination of multiple columns from the data source?
Example data source:
{
"data": [
{
"aid": 5421,
"bid": 4502,
"name": "John Smith"
}
}
Code:
$("#datatable").DataTable({
select: true,
//rowId: "aid" each row ID is the value of the "aid" column
// e.g., <tr id="5421">
//rowId: 0 each row ID is the value of the 0-indexed column
// e.g., <tr id="5421"> (same as above)
rowId: [0, 1] // How? row ID combined value of 2+ columns
// e.g. <tr id="5421-4502">
rowId: "random" // How? random generated client-side ID
// e.g., <tr id="id34e04">
});
Apparently there's no way to do this directly. As a workaround, you could use the ajax.dataSrc option and/or the rowId option:
// Example using dataSrc option to manipulate data:
$("#example").dataTable({
ajax: {
url: "data.json",
dataSrc: function (json) {
for (var i = 0, ien = json.data.length; i < ien; i++) {
json.data[i][0] = 'View Message';
}
}
}
});
This worked for me:
$("#datatable").DataTable({
...
'createdRow': function(nRow, aData, iDataIndex) {
$(nRow).attr('id', 'row' + iDataIndex); // or if you prefer 'row' + aData.aid + aData.bid
},
...
});
I updated it from a question that seems to be a duplicate of this one. The createdRow callback is documented here.

NodeJS JSON Array filtering

I have used Node to retrieve a set of results from SQL and they're returned like this;
[
{
"event_id": 111111,
"date_time": "2012-11-16T01:59:07.000Z",
"agent_addr": "127.0.0.1",
"priority": 6,
"message": "aaaaaaaaa",
"up_time": 9015040,
"hostname": "bbbbbbb",
"context": "ccccccc"
},
{
"event_id": 111112,
"date_time": "2012-11-16T01:59:07.000Z",
"agent_addr": "127.0.0.1",
"priority": 6,
"message": "aaaaaaaaa",
"up_time": 9015040,
"hostname": "bbbbbbb",
"context": "ddddddd"
},
]
There are usually a lot of entries in the array and I need to efficiently filter the array to show only the entries that have a context of "ccccccc". I've tried a for loop, but it's incredibly slow.
Any suggesstions?
There is a very simple way of doing that if you want to do that in node and don't want to use sql for that you can user javascript built-in Array.filter function.
var output = arr.filter(function(x){return x.context=="ccccccc"}); //arr here is you result array
The ouput array will contains only objects having context "ccccccc".
Another way of doing what Khurrum said, is with the arrow function. It has the same result but some people prefer that notation.
var output = arr.filter(x => x.context == "ccccccc" );
As suggested by Matt, why not include WHERE context = "ccccccc" in yout SQL query?
Else if you must keep all in maybe use one of the following to filter the results
// Place all "ccccccc" context row in an array
var ccccccc = [];
for (var i = results.length - 1; i >= 0; i--) {
if(results[i] == 'ccccccc')
ccccccc.push(results[i]);
};
// Place any context in an named array within an object
var contexts = {};
for (var i = results.length - 1; i >= 0; i--) {
if(contexts[results[i]] == 'undefined')
contexts[results[i]]
contexts[results[i]].push(results[i]);
};
or use the underscore (or similar) filter function.