Using Flow and jest
This article is part of the series my journey with React and its ecosystem. If you are not familiar with it, I suggest you check that out first!
In the previous article of the series, I explained how I introduced a timer in
passata, my playground application for
the pomodoro technique. At the time, the code was part of the
component, and I planned to extract the timer to its own class, add some tests
and learn more about ES6, jest and Flow. This was an exciting plan and it turned
out to be even more interesting than I anticipated. Each small step I took
generated many questions, I have always been a fan of such activities.
How do I test with jest?
jest is a testing framework and I’ve wanted
to try it out for a while. I heard good things about it from people I trust and
had a good impression while skimming its documentation. Setting it up took
minutes, I only had to install two packages: jest and
babel-jest. I got a
first green test here in
no time, because I deliberately wrote a meaningless test: my goal was to test
the toolchain and understand it better. I considered it a successful test
because it generated many questions:
- Am I even running Flow? I set it up a while ago but now I’m not sure it’s working.
- If I’m running Flow, am I running it when running the tests?
- How do I make the build fail when Flow reports errors? I believe there’s no point in annotating the source code otherwise.
I felt slightly overwhelmed, yet I could turn it into excitement. After all I’m still learning.
How do I flow?
I turned out I had never run Flow after setting it up. As soon as I ran it again, Flow gave me so many errors that its output was scary. I decided to investigate the problem and fix the errors before moving on to integrating Flow with the rest of the toolchain.
I researched the errors Flow reported and understood I needed to install
flow-typed is a central repository of Flow library definitions, it
provides definitions for widely diffused libraries. The experience with
flow-typed was nice. Once I installed it, I only needed to run:
$ ./node_modules/.bin/flow-typed install
The command analysed my dependencies, downloaded all the available libraries’ definitions and provided stubs for the unavailable ones. This commit contains all the definitions I needed. Finally, Flow detected no errors.
How do I flow and test?
I read jest getting started guide which is friendly and well written. However, I felt I needed to know more about the framework matchers and other utilities you normally find in a testing framework. The API documentation is clear and useful but I find its table of contents confusing. For example, the matchers menu item is labeled expect; I know it’s technically correct but that did not result in good user experience for me. The API itself is friendly and familiar to RSpec users. I have always had a soft spot for RSpec so I felt at home with jest.
If there’s one situation in which I’m fine with using mocking, it is when I need
to fake time. jest offers a simple API to fake
timers, and I
was happy to find out that the functionality is builtin. I implemented some
tests and started playing
with the command line options jest offers. The framework is fast, you can feel
it even with just a couple of tests, and I liked its default output. At first, I
did not understand how to run jest with additional parameters via yarn. But it
was a matter of adding
-- before the additional option as in:
yarn test -- --watch
--watch option I used in this example is quite helpful, I suggest you
check it out.
At this point, I had a setup I liked and a couple of tests I could live with, so I moved on to figure out how to run Flow when running tests. I ended up with this solution. I would prefer more integration between Flow and jest but, for now, it does the job.
How do I flow and build?
I did some research to answer this question and found out I needed to use
preloaders. Webpack documentation was great (as always):
2.x. The documentation explains how to deal with
I needed to install a plugin called
flowtype-loader and to make some
minor changes to the build configuration. I did all the changes in this
commit. The documentation
of the plugin was outdated so I opened a pull
request, hoping that other
people wouldn’t run into this problem during the transition phase between
Next step was to integrate the timer with the rest of the application. I did it here and I liked the exercise. I had to adapt the initial API I designed for the timer. As always, I felt unhappy with the code I wrote. To be honest, I’m never happy with the code I write and I consider it a good sign. It’s the main reason why I don’t believe much in the principle “write code that is easy to change”. I prefer to “write code that is easy to delete”. I find changeability to be a feature overcharged with meaning by our instinctive need for refactoring.
The timer worked fine but I wanted to be able to update the document’s title with the current time. I researched how to update the title of a document “the react way” and ran into a project I liked. It’s called react-document-title. That’s great naming: it’s called what it does and I always appreciate that. I integrated it here and managed to play a bit with lodash too. I remember running into lodash in the past and thinking that it was a nice little “underscore.js alternative”. Now, I get the impression the project has much more to offer and I plan to get back to it.
At this point, passata has its main functionality: the timer works fine and it’s nicely presented in a little progress bar. I still can’t use the application every day, though, as it misses a set of features I can’t live without:
- CRUD of categories.
- CRUD of notes.
- Running a pomodoro in a selected category.
In short, I can’t use a pomodoro application that doesn’t store my activities. Those features generate many questions for me, as I have no idea how to persist objects in a React project. In the next article I will be answering these questions and I hope you’ll find the answers useful.
Thank you for reading me and stay tuned for the next article!