My first experience with Jest

How I wrote tests for Telescope project

Ilya Zhuravlev
6 min readDec 15, 2019

Greetings everyone!
It is finally the end of the Fall 2019 semester!
Christmas music has been in the playlist of almost every shopping mall since the end of November, and most of the college and university students have already finished their projects and (I hope) killed their final exams.

So (again, I hope) did I.

And between finalizing the projects for my other courses and preparing for my Finals I was contributing to the Telescope project, that my groupmates and I have started and which I described in my previous post:

This time, I was to test what we have already — that’s how I met Jest.

Jest

Credit: https://codeburst.io/jest-the-next-generation-testing-8a6ee7c14656

Jest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!” — stated on the home page of the Jest’s website.

And it is true! Aside from using a pretty straight-forward logic of testing (will elaborate on it a little later), it is also very convenient to use.
Every time tests are run, the “test coverage” is being produced. What is it?
Jest automatically creates a table, that lists all of the code files in the project folder and displays statistics on how well are they being tested: which lines of code are covered and which are not, what percentage of the file overall is being tested and what time did it take to run this test.

All of the failures and errors are listed with the explanation of what was expected to happen and what has happened in reality.

Credit: https://devrant.com/search?term=unit+tests

Here is an example of a created in the terminal table after running tests on Telescope:

What Did I do?

My task for this Pull Request was to implement testing for the post/:guid route for Telescope’s Back-End. This route sends a guid of the post, desired to be received, and the server should send an appropriate response. We needed to test the following cases:

  • 200 — a post with a guid, received by the server, exists, and the server returned it with a 200 status;
  • 404 — a post with a guid, received by the server, does not exist, and the server returned an error message with a 404 status;
  • two previous cases should be working with encoded and not encoded guids.

The logic of testing itself is very simple: do the action we want to test and then compare the results of this action with the expected results.

To test the following cases, we had to add a dummy Post object on our server’s storage and then try to get them with the route provided.

Code Writing

Let’s call our test router.post.test.js — as soon as it tests the post/ route.

Import supertest — it is a NodeJs library for testing HTTP requests.
Import app — this is where we are sending our requests.
Import class Post — includes constructor to create a dummy Post object.

const request = require('supertest');
const app = require('../src/backend/web/app');
const Post = require('../src/backend/post');

Our “Main” function for testing is named describe and receives a string, describing what this test does as a parameter in its call.

Now we want to declare the variables we will be using throughout our test cases.

For every test-case that we are covering we will need a unique guid — post identifier. Four in total, but for this blog post I would like to concentrate only on one of the test cases — status 200 with an encoded guid.

const existingNeedingEncoding = 'guid needing/encoding';

After the guid declaration, we create our dummy Post:

//Post object constructor receives the parameters in the following order:
(author, title, html, text, datePublished, dateUpdated, postUrl, siteUrl, guid)
const addedPost = new Post(
'bar',
'bar',
'',
'bar',
new Date('2010-09-07T22:20:00.000Z'),
new Date('2010-09-07T22:23:00.000Z'),
'bar',
'bar',
existingNeedingEncoding
);

Let’s also create an example of what we should receive:

// an object, expected to be returned by a correct queryconst receivedPost = {
author: 'bar',
title: 'bar',
html: '',
text: 'bar',
published: '2010-09-07T22:20:00.000Z',
updated: '2010-09-07T22:23:00.000Z',
url: 'bar',
site: 'bar',
guid: 'guid needing/encoding',
};

We are ready to test! Wait, we still want to add our Post to the storage. How do we do that?

We can use beforeAll method if we want to do certain actions before each of our test cases.

// .save() is a Post object's method that will add it to the
// server's storage
beforeAll(async () => {
addedPost.save();
});

Our test is constructed with the help of the method it. It receives a string description of what the following test case does and the lambda function with the actions to be tested.

it('pass an encoded guid that exists', async () => {
const res = await
request(app).get(
`/post/${encodeURIComponent(existingNeedingEncoding)}`);
expect(res.status).toEqual(200);
expect(res.get('Content-type')).toContain('application/json');
expect(res.body).toEqual(receivedPost);
});

What happens in the code snippet above is:

  • we encode our guid with the encodeURIComponent() method;
  • we query our server ( app ) with a Get HTTP request;
  • the server decodes the received guid, looks for a post that has received guid and returns it in the response;
  • we check the received response status to be 200;
  • we check the server’s response header to contain
    'Content-type': 'application/json';
  • we compare the received object to the receivedPost JSON object that we’ve declared above.

And, this is it! The test now will do what we stated in the test and will fail the test if any of the deep comparisons will not return true.

Simple, right?

Conclusion

In conclusion for this article, I wanted to talk a little bit about this semester.

I believe that it is important to sometimes take a look back and compare ourselves right now to ourselves some time ago.

This summer I knew very little about GitHub, and I for sure used it not even for 10 percent of its capabilities. My groupmate and I have already tried to work together on one project using a GitHub repository at that time— and it was pure hell. Now we are jumping between branches and rebasing commits as gracefully and confident as squirrels.

I was not very knowledgable and skilled in web development, JavaScript and React in particular. I am not a Gury of both yet, but I have significantly improved in both.

The most important thing — I am now a real Open-Source Developer!
I contribute to various repositories all over the world and my work is being accepted and appreciated! My work and I are valued by the community of the Software Developers!

I am also fascinated by how fast the Telescope project grows and amazed by what a great project we are creating. This would not be as awesome without the person, who introduced us to the world of Open-Source, explained how the GitHub is working, taught how to use it and led us through the entire path of creating Telescope.

Thank you very much David for all of the classes you taught us.

Merry Christmas and Happy New Year!

My GitHub: https://github.com/izhuravlev
The Telescope Project: https://github.com/Seneca-CDOT/telescope

Happy Coding in 2020!

--

--