Tests first

Photo by Thomas Kelley on Unsplash

Following the TDD approach, let’s write tests for our entities first. I will dedicate a folder for every Entity: “article” and “comment”. Each folder will follow a similar structure: it will contain a file for an entity itself, file for its types, file for its spec and a barrel index file:

src/entities/article/article.ts

src/entities/article/article.types.ts

src/entities/article/article.spec.ts

src/entities/article/index.ts

Let’s create these files and fill them in with some boilerplate code:

Boilerplate code for Article, Article types, and Article specs

Similar for Comment:

src/entities/comment/comment.ts

src/entities/comment/comment.types.ts

src/entities/comment/comment.spec.ts

src/entities/comment/index.ts

Boilerplate code for Comment, Comment types, and Comment specs

And let’s update barrel file

/src/entity/index.ts

and export everything from Article and Comment:

Article barrel file

Now, what can we test? Testing of fields doesn’t bring too much value, and besides, TypeScript got us covered on this. But what we can check is validation rules for Comment.

Testing Validation rules

Let’s assume the Comment entity has a method “validate” that will check if this particular Entity is valid and return true or false. It should take into consideration rules that we received from the Business team: 10 max for a title, 10 max for the author’s name, and 255 for content. Let’s add this method to the interface. As for “max character numbers,” we cannot put them as fields to the Entity since they don’t depend on a particular instance of the Entity. We can use static fields, however, or simply create the independent constants:

Comment validation types

Now, let’s write the tests:

Comment validation spec

Of course, TS keeps yelling at us. After all, IComment and Comment provide zero information about “title”, “author” or “content”. But before we jump into fixing our code, there is one more thing I’d like to discuss.

Data vs. Entity

Data we receive from API (or, in our case, data.json) is not strictly Comment or Article entities. At least, not yet. It’s a plain data that by itself has no notion of “validate” or any other functionality. It’s pure data, not a class instance. So, it’s not enough to have only IComment and IArticle. We need a dedicated interface ICommentData and IArticleData. They represent this pure, quintessential data we receive from an external resource, and we can use them to instantiate an actual Entity. I will take a step ahead and predict that we will also use these interfaces to represent pure data that we store in the Vuex store (for its recommended not to store objects with methods in Vuex).

So, let’s define these interfaces and also define fields they must contain as per data.json:

Pure data and Entity

Here are a few things to note: