Harry Potter and the Javascript Fatigue — Part 3

Maximilian Schuler
itemis
Published in
6 min readFeb 2, 2018

This is the last part (for now) of a series of articles on Vue.JS frontend development. In case you missed them, here is Part 1: The Philosopher’s UI

and Part 2: The Chamber of Storage

You can pull the App from here! If you do so, run git checkout part3 for this part, the final App is git checkout final.

Part 3: The Prisoner of Api

You can create and change Todos but one major draw-back is that you lose all state after restarting. You feel that having to apply a reappeariamos spell is a huge time-waster. So you ponder different solutions. Your idea is to banish the Todos to a place like Azkaban. To imprison them frozen in time in a basement of data, a database ment. You find such basements in the internet and after some consideration you decide to give either Cassandra or MongoDB a try. But you would never use Voldemort. Never.

The deus-ex-machina-backend

Because a wizard does not submit himself to backend work, you ask your house elf to write some backend for you. And he quickly comes up with a Reactive Repository

The little creature defines an Id on each task.

The elf tells you something about Command Response Segregation and how Hexagonal Architectures is the greatest discovery since coffee mugs.

He talks and talks. Now he mentions reactive backends and how reality is nothing more than a stream of past events in a message queue. You start to pity him and his simple elf mind

He finally starts to make sense when he talks about the Rest Api. He will define a GETand a POST endpoint to fetch all tasks or post a new one.

Asynchrounus testing

So the only thing left to do is writing an Api that calls the backend and updates the state of the store. That should not be too hard to do. First you have to install a library to make calling the backend a bit easier.

You let yarn do the magic: yarn install axios. And now you describe the api. You want it to fetch tasks und unwrap them from the more technical Axios Response. Also if an error occurs you must hand it down to the caller.

These two tests also use Jest’s async testing tools and mock away the axios.get method using Jest! (Note they are not annotated as async, but return a promise!)

The api itself is pretty easy to build now.

Now that the Api is ready, it makes sense to write tests for the Actions. Actions do not change the state, they only invoke mutations, as you saw in the previous Part. So this is what you define here.

  1. If the Api succeeds, it calls a FetchTasksSucceeded Mutation
  2. If the Api fails, it calls a FetchTasksFailed Mutation

You need to mock the fetchTasks method of the Api and have it return Promises. After looking at the Vuex documentation, you find out that Actions can return Promises. So you can even await the action from your testing code!

Compared to the version that returns a promise this is more succinct. You can await any promise and then assert things.

Implementing the Action is again pretty much straight-forward.

This was — to your surprise — less painful than the Herbology courses at Hogwarts. But only a little bit.

Posting data

Fetching an empty list from a database ment is not of much use. You have to fill it somehow. So you will use the POST endpoint the elf defined and write your api function.

This is exactly the same as for your fetching endpoint. But you did not specify that the way data gets to axios. Adding an extra expect statement might make sense

Here you could also specify that the correct request headers are set. The downside about these tests is that they depend on the library used. But this goes for all tests against the backend. In a perfect world, we would create a mocked endpoint using something like Wiremock. Unfortunately, I do not know a reliable method to use such tests in the frontend (yet).

You enhance the AddTask action by calling the api.

The action and your test became asynchronous but not much changed besides that. The Action itself is nothing more than an api call.

You do not have to create a Task object anymore, because you get one from the Api and it already contains an ID.

A type casting Api

Wait it contains what?

The task object you receive from the Backend contains an Id field. (You vaguely remember the house elf mentioned that). But your task model in the frontend does not have such a thing. You realise that all the type-safety in your backend calling expressions like

is nothing more than a compile-time illusion. You do not like illusions. True wizards do not deal in illusions, only in like actual real magic. Talking to a backend that might give you any object it wants to. Reality is outrageous! You have to do something about it (And now you can appreciate that you decided to put the api in its own layer)!

What you want is something like this:

You remove all the unknown fields from the result and each object must have the right types in the api. That is the wizard’s way.

First you add the id to the Task

and then you put another function into the api that casts your objects onto the right type.

You do not pretend anymore that you already get the correct type from the backend, you map to your own type.

Casting Refactoriamos

All these Promises with their catch-then-resolve-reject semantic are very verbose and hard to read. You learned the Refactoriamos spell at Hogwarts and thought you could try it out on your api code.

This is all that remained after the spell evaporated many of your lines. And all tests are still running green! What a great spell indeed. By making all functions asynchronous, it removed the helper function completely. Your code is no longer in the complicated swamp of Promise handling.

You cast the spell again, this time on your AddTask action and you get:

On first glance, the spell did not do much. But you can see that it got rid of the chain of thens and the catch function somewhere. You have a nice try catch block instead. You apply the spell to your other actions in the same way. And feel more confident with your codebase.

You also cast the spell on some of your tests, they stop being so hideous.

Again instead of creating Promises you just await a result and use it.

There is also vuex-saga based on redux-saga that takes these ideas even further. But, by the time of writing vuex-saga has a bug that seems to make it harder to handle errors. Also sagas might not be necessary for every team.

That’s it for now. You feel relieved. Finally, you can think about the important topics of web development. Like what color you want for important todos or how many pixels of border radius are necessary for your Textboxes to impress Ginny Weasley.

/

--

--