Let’s start simple, before we dive into the whole JSON. Let’s say we have a super-simple JSON object, that contains just a couple of keys:
To test such an object we can write a following test. Of course, in real world we would probably not test a fixture, but to demonstrate the point I like to keep things simple. Instead of
.fixture() you can imagine a
.wait() command that intercepts a network call.
It does not matter what kind of value our object attribute has, we can access it using so-called dot notation. This is the
objectname.attribute notation, separated by a dot, hence the name. We can use a so called bracket notation, which does exactly the same thing, but with slightly different syntax:
You might ask why would anyone choose this syntax over the dot notation which looks much more polished, especially if we were to access an attribute that’s few levels deep. With bracket syntax, you can actually pass a variable, so you can write something like this:
While we are at it, I suggest you look into
Let’s now add another item in our
car.json fixture. This will be a list of feature formatted as an array:
Let’s say we’d like to write a test for couple of these feature items. That test would look something like this.
Notice how we use a similar style as the mentioned bracket notation. This is how you access items in and array. However, there is no dot notation for arrays, so attemting to write something like
features.1 would result in an error.
Arrays are widely used and can sometimes contain a lot of information. If you want to test an array for just a single item, you can use
include assertion as we did in previous example:
There are tons of different assertions you can use with arrays, and I suggest you check out the documentation to learn more.
Let’s now combine arrays and object. Our car fixture will now have multiple objects inside it - a common situation when working with api that returns a list of items. Our JSON file will look something like this:
To test e.g. the color of our second item, we will to combine two mentioned approaches - referencing array item & referencing object key:
cars, we are selecting the second item from our array of objects, and within that object, we are using
.color to select the proper value from that object. In other words, we are travelling through the JSON structure. We could of course also use bracket notation and write the same thing like this:
These combinations can be overwhelming at first, but they become natural after a while. Chrome DevTools can be a great help here. Right click on a JSON object can trigger a menu from where you can copy an attribute path to a given value. This works across many places in Chrome DevTools.
While trying to find your way around JSON objects, you might come across different errors. For example, there’s this strange behavior when you try to compare our
car.features array to another array. Let’s say we have an assertion like this:
Although it looks like it should definitely pass, our test will fail. What’s even weirder, is the error in the console:
Everything looks the same, so why does the test fail?
'1' == 1 will return
'1' === 1 will return
false. The difference is connected to how strict that comparison is. When comparing two arrays, we need to use
deep.eq instead of
eq in our test.
Mistakes happen while figuring out the proper path to a property. You may have already encountered an error similar to the one mentioned in subheading. This error can get super confusing and does not tell us a whole lot about what is the problem.
To dive deeper into the problem, let’s expand our JSON file with some extra attributes:
We’ve added some
engine attributes, so let’s test them with following test:
This test will fail with a following error:
![Cannot read property 'x' of undefined](cannot-read-property-x-of-undefined.png" shadow="shadow-md)
The reason why this test fails is that the
horsepower key cannot be found. The
of undefined part points us closer to the reason. It seems that key that should be inside
engines attribute is not defined.
What I usually do in these types of cases is that instead of the whole path, I try to
console.log() out the parent attribute and then continue up with each parent until I find something that can help me find a way.
If I do it in this case, I quickly realize that I made a typo and instead of
engines I should have typed
engine. This seems like an obvious mistake in this example. But things can get pretty tricky with huge payloads that contain multiple levels of information.
I hope this will help you with working with JSON objects. I write a blog like this every week, so if you’d like to get notified, signup for the newlsetter (form is in footer) and follow me on Twitter or LinkedIn.
From time to time I send some useful tips to your inbox and let you know about upcoming events. Sign up if you want to stay in loop.