How can I test nested properties using JSON test data?

I have some property to test in JSON response using test data of JSON file.

How can I validate that data from JSON test data file (only one value and iteration ‘title’) matches property under items.

I would like to access following property in response in other way than:
x.items[5].title

For the moment I can easily reach it by hardcoding:

const jsonData = pm.response.json();
        
pm.expect(jsonData.items[5].title).to.eql(pm.iterationData.get("title"));

but how to use it without specifying this [5]. Is there other way to “say” find title within items no matter of positioning?

If I would have in JSON test file e.g. 100 titles to verify, then it will be easier than specifying same 100 lines of the code…

Postman uses JavaScript under the hood, so this can be achieved using the JavaScript find() or filter() functions.

If you post an example response with 2-3 objects, I can help you with the specific formatting for the function.

I can send you screenshot from example, JSON path finder. In fact there are 8 titles which I need to validate using some smart solution:

If you send the request, you can copy and paste from the response pane.

I need the request as text, as I send it to Postman Echo to replicate the response.

When you say eight titles. What test are you envisioning? Do you need to test all eight titles, or just the 1?

request is normal GET of specific ID of that collection of documents

I will try to mock response a bit, as that is sensitive data :frowning:

yes let’s say to simplify I have only one expected ‘title’ in JSON test data file and in test I want to find it easily in that list of 8 titles under items property.

However final thing would be to have test which will go thru all 8 expected titles in JSON test data file and validate it against JSON response, however order is not needed, just fact if some title exists in response or not

that is JSON test data:

[
  {
    "title": "Title1"
  },
  {
    "title": "Title2"
  },
  {
    "title": "Title3"
  },
  {
    "title": "Title4"
  },
  {
    "title": "Title5"
  },
  {
    "title": "Title6"
  },
  {
    "title": "Title7"
  },
  {
    "title": "Title8"
  }
]

Here is an example using find, and another example using a forEach loop with a basic test.

const response = pm.response.json().data;

pm.test('Title5 exists', () => {
    let search = response.find(obj => obj.title === "Title5");
    pm.expect(search).to.not.be.undefined
})


response.forEach((obj, i) => {
    pm.test(`title exists - object ${i} `, () => {
        pm.expect("title" in obj).to.be.true
        pm.expect(obj.title).to.not.be.undefined
    })
});

image

thanks, how can I use pm.iterationData here? instead of `get(“title”)’

I would like to compare values from JSON test data vs JSON api response

Assign the iteration data to a variable.

let title = pm.iterationData.get("title");

pm.test(`${title} exists`, () => {
    let search = response.find(obj => obj.title === title);
    pm.expect(search).to.not.be.undefined
})
1 Like

thanks, but I’m getting this error while executing collection with JSON test data:

TypeError: Cannot read properties of undefined (reading 'find')

here is my complete post-script:

const response = pm.response.json().data;

let title = pm.iterationData.get("title");

pm.test(`${title} exists`, () => {
    let search = response.find(obj => obj.title === title);
    pm.expect(search).to.not.be.undefined
})
const response = pm.response.json().data;

You just need to remove the data element from the end.

It’s included because this is how Postman Echo works. I usually remove it when I post code, but forgot in this instance.

ok, thanks it was indeed looking weirdly.

close to resolve issue :wink:

now there is an error: response.find is not a function

What does the response look like?

Is it the same as the example you gave me. (Which is an array of objects).

The error message is basically telling that you response is not an array.

find is a JavaScript function\method that is only available to arrays, so if response is not an array, then the find method will not exist, so its correctly telling you that find is not a function.

Ouch, sorry for misunderstanding. In the example I send you test data which I’m uploading while running collection - and that is simply JSON file.

Response is also in JSON and I would need to look under this JSON path finder,example:
x.items[4].title

so in my code I have been using that:
pm.expect(jsonData.items[4].title).to.eql(pm.iterationData.get("title"));

which of course works for single element, but how to look (expect) for ‘title’ in any items property?

It would appear that your array is under items, so the find function would need to be something like…

const response = pm.response.json();
let search = response.items.find(obj => obj.title === title);

great, it works - thanks, a lot

now just need to make some loop and add rest of the titles into the JSON test data file, to validate whole JSON test data title against response. Can I reuse forEach function somehow?

Not sure I follow you.

The JSON data files used with the collection runners need to be an array of objects, with each iteration using the data from a single object.

If you want to validate all of the objects in a response in a single request, then you will need to format your data file differently.

[
    {
        "testData": [
            {
                "title": "Title1"
            },
            {
                "title": "Title2"
            },
            {
                "title": "Title3"
            },
            {
                "title": "Title4"
            },
            {
                "title": "Title5"
            },
            {
                "title": "Title6"
            },
            {
                "title": "Title7"
            },
            {
                "title": "Title8"
            }
        ]
    }
]

This is an array with a single object in it (so will only run one iteration). That object has a single key called testData where the value is your array of test data.

You can then access the testData array using…

let testData = pm.iterationData.get("testData")

Or the special data variable (which contains the current iterations data).

let testData = data.testData

Thanks a lot for your effort, you helped me a lot

I will ping you one more time if there will be some error with executing it against modified json test data

hello

btw do I need to use forEach as in your first example? or how it should look like?

Depends on what you want to test.

It sounds like you want a forEach loop against the test data array, and then test to see if the current title is in the response, so yes, a forEach loop would help with this.

Define the current title in the loop as a variable, and you can then use backticks and string literals to customize the test case name, like following.

pm.test(${title} exists, () => {

Otherwise, all of the tests will have the same name, and it will be hard to work out which one has failed.

yes, I would like to simply test if all titles from JSON files exist in the API JSON response (within items in my example)