VueJS unit tests as a learning tool: v-for

Matt Dionis
Vuefinder
Published in
6 min readAug 2, 2017
Repeat the pattern with ‘v-for’. Photo by vision webagency on Unsplash

This is the third post in a series which dives into unit tests within the VueJS code base in order to gain a deeper understanding of how elements within the Vue ecosystem work. I recommend checking out the first post on v-show and second post on v-if before diving into this article.

Beyond alerting one to regressions in a code base, well-written unit tests read like simple sentences and help those working on a project to understand what individual features do. Unit tests can also serve as great templates for documentation if they are written well as they should describe what a feature does and how it reacts to different inputs.

The VueJS documentation is excellent, but recently I decided to dig even deeper and begin exploring the source code behind Vue! The first piece of the code base I visited was the tests directory. Most of you have surely heard of Test Driven Development (TDD). Well, in this series I would like to introduce you to Test Driven Learning (TDL). The idea is to begin reading through the unit tests of the framework or library you are using early in order to gain a deeper understanding of how individual features work. TDL also has a beneficial side-effect in that it will reinforce the benefits of writing unit tests in your own projects and reveal solid testing patterns.

‘v-for’ unit tests

In this third post in the series we will take a look at the v-for directive. The unit tests in full can be found here, but we will be walking through them piece-by-piece below. Below is the beginning of the v-for test spec.

This first set of tests reveals that v-for works much like JavaScript’s forEach method. In these tests we see that an array is iterated over and the value of each item in the array is rendered as a span. Operations such as push and splice are applied to the array and the rendered HTML reacts as we would expect.

The final block of tests in this first section teaches us a new syntax. It appears that a second argument can be used within v-for and it is the index of the item currently being iterated over. We see this index correctly rendered and updated as the associated array is operated on.

This next set of tests is very similar to the first, but reveals that v-for works with objects just as it works with primitives. By referencing item.value in the interpolation, we can render the value property in each span.

The second argument, index, works with objects just as it does with primitives. We are now beginning to see how powerful the v-for directive can be, as iterating over objects is something we will most likely want to do in our application’s templates.

We begin to appreciate the flexibility of v-for as we read through the next set of unit tests. Not only does v-for work with arrays of both primitives and objects, but it also works with the individual properties of an object. By using the basic val in obj syntax we can render each value within the object.

When iterating over the properties of an object, the second argument refers to the key rather than the index. We notice in the second block of tests that we can easily access and render these keys.

You may be wondering: can we still access the index somehow? Yes we can! The next block of tests reveals that the third argument is the index when iterating over the properties of an object.

The final block of tests in this section shows that we can also iterate over each of the properties of data itself. If we apply a v-for to $data we can gain access to the key and value of each property on the top-level data. Nice!

As we continue to read through the unit tests, we come across a section which reveals how v-for and v-if work when used on the same element. It appears that the order of v-for and v-if does not matter. The v-if directive will be applied to each individual iteration whether it is placed before or after the v-for.

This simple test highlights the fact that v-for can be used to iterate over a range of numbers. So, for example, if we wanted to render a certain UI element ten times we could use v-for=”n in 10” instead of adding the same element to our markup ten times.

In this next set of tests we learn how the key can be used. If a key binding is not used, DOM elements are reused in place. We see that although the msg within the first child changes, the DOM element was simply reused. Nice and efficient!

However, when a key binding is used and a unique identifier is passed to it, in this case item.id, the DOM element is actually moved as the data it is bound to changes.

Moving on, we find out that v-fors can be nested and will work exactly as expected. We can access any level of our data which we need by nesting v-fors. An array of arrays, an array of objects, an array of objects with properties which are arrays? No problem!

This next set of tests reveals that we do not need to rely on native DOM elements such as div and span. We can wrap an entire block of HTML markup in a template tag and slap a v-for on that template. This entire block of HTML will then be rendered for each iteration.

So now we know that v-for can be applied to HTML elements such as divs and to templates. We’re itching for something even more powerful though. Can v-for be applied to components? Why yes it can!

We see here that v-for can be applied to a component and data can be passed through props. Do not worry about props and slot at this point though. We will cover them in detail in future posts. The important thing to take away from this first block of tests is that v-for can indeed be applied to a component.

Further down in this section of tests we see tests for v-for with “dynamic components”. The :is binding is used to determine which component is to be rendered. Again, more on this to come in future posts. The “key” point to understand here (pun intended) is that we must provide a :key binding when using v-for with dynamic components. Otherwise, we can expect to see the “component lists rendered with v-for should have explicit keys” error message.

This next small block of tests simply highlights the reactivity of v-for. Changes to deeply nested data within a nested v-for will indeed be reflected in the DOM thanks to the reactive nature of v-for!

This final block of tests reveals one more cool fact. v-for can be used on strings and will iterate over each character in the string passed to it. A small but interesting feature of v-for.

‘v-for’ docs

The v-for API docs section should make complete sense to us now that we have studied the unit tests:

As I mentioned earlier, the VueJS docs are excellent, but I would argue that reading through the unit tests behind v-for taught us all that the docs reveal and more in just a couple minutes of reading! Also, as I mentioned, reading through the tests taught us how unit tests should be written and how thorough they should be. Writing similar tests for features within your own apps should become a priority for you and your team!

Next up

In the next post, to be published soon, we will compare v-text to v-html through their unit tests!

Previous posts

If you enjoyed this post please hit the little 💚 below to let me know you’d like more of this material! Thanks! 🤓

Interested in building the future of money at Circle? We’re hiring!

--

--

Matt Dionis
Vuefinder

Staff Software Engineer at Catena Labs building identity, communications, AI and commerce products to enable a more equitable web!