Hi there! How are you? I hope you are well!
Well, lately I am trying really hard to find ways to properly test React components. We are talking mainly about UI tests using the enzyme library. It is a great way to test them. If you have not used it yet, I totally recommend it to you. Try it!
So, let’s explain a little bit the situation I was in last week when I had to fix a very stupid bug but wanted to seal it away for ever by writing a meaningful test for it!
WARNING: Any code you will see is not the real one. Names and certain domain stuff are altered in order to keep everything clean and safe.
So, we have a component SomethingContainer and the associated test file that accompanies it. I forgot to mention that our codebase just lately started being heavily refactored based on the atomic design principles and methodology. This means that you have several different levels of abstractions in order to construct the UI. You start with “atoms”, then “molecules”, then “organisms” here you have a more meaningful naming such as “pages”, “templates”, “themes” and so on. I hate the chemistry terms to describe UI components but just for the sake of the example I will stick to them.
Back to the example, we have a Button which is an “atom”. How do you test an atom? Let’s say it has two props: title and a click handler, e.g. title and onClick. How do you go about it? First of all, we have to think that here in this level there is no business rules or user perspective or value in general for the users of the Button. So, you just test – and this is a real unit test – what this button does! What is its functionality? It needs to show some text and handle clicks. So, we can test if it passed down its props correctly. For the title we can assert that when provided with one it prints it on the screen and for the handler we can just use a spy callback and pass it down to the component and check if this callback is called when we click the button. We abstract how it works and we do not tie ourselves to specific implementations by not defining a specific case for our test. To make it more clear especially for the click callback:
we do not care if the button opens a modal or submits a form or does very specific things because we test its functionality in isolation!
We could not care less what its interactions with other components are! That is the purpose of the next level of components abstraction and the purpose of an integration test.
But we will continue in the next post since this gets a bit long.