Thursday, 7 September, 2017 UTC

Summary

Love it or hate, JavaScript is everywhere. Recently, I took another step toward assimilation by attending the Big Nerd Ranch Front-end Essentials bootcamp. And… all biases aside, IT WAS GREAT! I began the week with two goals:

How to even modern CSS?

React Native sounds cool, but how to test?

Thankfully, the answer to my first goal was “stop being lazy, Jay. Learn flexbox.” The second part was a little more subtle, and I expanded upon the ideas that I had learned in class once I returned home. Throughout the next few posts on the topic, I’ll explain my findings.

Object Traversal

In my recent experience, getting started with React Native testing is a little rough. There are good tools for snapshot testing and shallow rendering, but I wanted something capable of deep rendering without the tight coupling of a full snapshot. To start, I began digging into the output of React’s test renderer which is used with snapshot testing. As it turns out, the results of test rendering are a deeply-nested, often circular object tree.

The first hurdle in establishing a strategy for integrated component testing with React Native is picking out particular nodes in deeply nested object trees. The below screenshots illustrate this nesting. So for example, you might want to assert that certain text is found somewhere in the hierarchy. If you have any functional programming leanings, you may immediately think of this as a recursive problem, and to be honest, it’s quite natural to reason about the problem recursively.

Recursion is great, but it can be tricky to bail early on the routine if you’re only interested in finding the first matching node. Not to mention the complicated story with tail-call optimization in JavaScript. Modern JavaScript provides a useful tool for solving our traversal problem: Generator Functions.

Since the return value of generators conform to the iterable protocol, they can be used with the for..of construct! So how should the visit() function be implemented?

Writing visit()

Here’s your generator function signature. Don’t forget the asterisk!

function* visit(obj) { // }

The data structures encountered in React Native are often very deeply nested (and sometimes circular), so with that foresight it makes sense to implement visit() as a breadth-first search. To avoid recursion stack limits in JavaScript, revert back to good-ole looping. Initialize a queue with the subject of your search and loop until you’re all out of nodes:

So, if the next value in queue is an Array, add all its values to the array. Otherwise, if it’s any sort of object, add all of its enumerable properties to the queue. The spread operator (...) is particularly handy for this use.

That’s it! You can now visit each node in any object graph. However, there are a couple more things to consider.

API

For general use cases, it may not be desirable to require folks to deal with visit() directly. Instead, you might want to expose a more functional interface such as each():

Theory and generalizations are fun and all, but how can we use this practically? I promised to relate this to React Native testing. You’ll have to look out for the next post to see how this all comes together. Stay tuned!