Shotgun is a new show that lets you ride shotgun with me while I tackle real programming challenges for real apps and libraries. The show is only available to members of EricElliottJS.com , but I’m journaling the adventures here.
Inepisode 1 we start a brand new React project — an online course presentation engine with React. We covered unit testing with Tape, auto-lint & test with Watch, and bumped into a glitch with Enzyme.
Still Hopeful about Enzyme
In the first episode, we switched to Cheerio for the DOM tests. It’s probably the 5th time I’ve been derailed by Enzyme bugs . I’m really excited about Enzyme, but be prepared to run into bugs and file bug reports. Please feel free to follow those links, investigate the bugs, and file proper issues & PRs. I’d love to do it if I had the time.
At this early stage, it Enzyme will probably slow you down compared to other alternatives, but I’m hopeful that 6 months from now, it’ll be a different story. The thing that excites me about Enzyme is that it works with the React synthetic event system to put a friendly wrapper around event testing, which is a problem I haven’t found a great solution to (let me know if you have).
I keep trying to use Enzyme because I’m very hopeful that it will become the great solution I’m looking for. Maybe when I’m testing synthetic events, I’ll be more motivated to chase down the bugs and get them fixed, myself.
Writing UI Tests That Last
I don’t know about you, but I’m constantly making changes to my UI markup while I build apps. When you’re testing UI components, it can be easy for every little change to break a bunch of unit tests.
In order to prevent that, I avoid writing tests that know more about the DOM than they need to know. For example, in the Course Player project, we have a `card-player` div that looks like this:
As you can see, it has a `nav-bar` , a select menu, some card content, and a continue button. I have considered moving the card navigation down below the card content. If I was looking for it in the `nav-bar` element test, moving it down would break that test, and I’d have to refactor more than needed.
When I know that something is likely to change shape, I don’t try to replicate the work of all the child tests by testing the full component output. Instead, for container elements, I simply test that the element can be selected, and that it renders children. Let’s look at an example:
Look at the `output` variable. It selects the `.nav-bar` element, grabs the children collection and checks its `.length` property. The `actual` test simply ensures that `.length` is greater than zero, which tells you whether or not its rendering any children.
You could argue that a nav bar should be checking to see if the navigation options are displayed, but the nav element will have its own tests to ensure that the children passed to it will be rendered, so that test would be redundant, and only serve to make the test suite more brittle than it needs to be.
Now, if I decide to move the nav list out of the `.nav-bar` component, sure, maybe I could rethink calling it nav-anything because at that point it’s more of a title bar than a navigation bar, but we’ll cross that bridge if we ever get there.
Boolean Attributes in JSX
HTML has some boolean attributes. In the course player, we use the `disabled` attribute to disable the continue button if the card requirements have not been met, yet, indicating to the student that the card should be completed before attempting to move on.
When writing HTML, you may be tempted to simply add the disabled attribute like this:
While working on this episode, I tried doing this:
And it just magically worked.
Note the `isCompleted` ternary expression. For a minute, I worried that the empty disabled value would cause the `disabled` attribute to try to render with a falsy value, which is not valid HTML, but I was happily reminded that React does the right thing when you pass a falsy value to a boolean attribute: A convenient shortcut that makes working with boolean attributes a breeze.
I think we all expect things to be harder than they really are sometimes. Thankfully, React devs are lazy, and they want things to “just work” the first time.
If you’re a member, feel free to dive into episode 2 now .
If you’re not yet a member, check out the teaser video, and join us . Shotgun is bundled with the Lifetime Access Pass , which gives you access to all our videos: a webcast series and course content covering topics like TDD, prototypal OO, functional programming, React, universal app development, ES6+ and more.