indigotech / onboard-rodrigo-magaldi

0 stars 0 forks source link

[Track 5/9] The tests 🤓 #17

Open taki-tiler-server[bot] opened 3 years ago

taki-tiler-server[bot] commented 3 years ago

Step 1/6 - First test setup

Estimated time: 1 hour

Now you're going to work on another super-important concept on the process of building your own server. Have you ever stopped to think about how you would test if your code works? 🤔 If you thought about performing the query/mutation on one of those applications (browser, graphiql, graphql playground) and checking if it works as expected, that's one way of doing it. But we have a more solid proposal: writing more code for tests! The principle is simple: you give an input and check if the response is the expected. Why is it better? Well, some advantages:

  1. The time gain: you write your test once, and then you can run it whenever you want.
  2. While you develop other features, you can keep running the tests for all the previous implemented queries/mutation to make sure they are still working.
  3. Test codes can serve as a kind of documentation as well. People who read them are able to know all the particular scenarios of a query/mutation.

If you search on the Internet, you'll find out there are many ways to test a code. Depending on the project, people decide to use one, or several of them. Here, we're going to write Integration tests, or E2E tests (end-to-end). For each query/mutation of your server, you're going to setup the database for them, provide some input scenarios, and then check if the response is given as expected. Take some minutes to read about them on the Internet.

Setting up tests on your server is not an easy task. There are a couple of things to learn and prepare first. We're going to create a step-by-step to help.

As you can imagine, giving the previous steps, there are more cool libraries to help us on this process. We're going to present them one at a time.

The first one is the main library to write the tests codes: mocha. Take a look at their docs. It's important to know that mocha provides some methods that can be executed like a timeline. This is very useful to handle tasks in specific orders.

Your task is very simple in this first step:

rodmagaldi commented 3 years ago

Finish

taki-tiler-server[bot] commented 3 years ago

Step 2/6 - Libraries everywhere: supertest

Estimated time: 1 hour

Another of those cool libraries is supertest. This library makes our work of performing requests to the server easier. Take a look at their docs.

Now, let's increment our step-by-step for the test execution:

  1. Start the server
  2. Run a single test

In order to acomplish this new first step, your task is to:

  1. Install the library
  2. Change your code to start the server before(() => {}) beginning the test... (🤣)
  3. Use the request function of supertest to communicate with the server you just started. You can use the localhost:port for this.
  4. Try to perform your previously implemented Hello query, from the apllo-server setup. For now, just check if it's working with console.log

NOTE: you can open a pull request after this step, so we can check if your setup is going ok for now.

rodmagaldi commented 3 years ago

Finish

taki-tiler-server[bot] commented 3 years ago

Step 3/6 - The last library (for now): chai

Estimated time: 30 minutes

The last library for tests is chai. Chai is a very complete library that handles assertion, i.e., checking if the result has the values that were expected to have. As usual, take a look at theis docs, install it on your project and try to use the expect function to compare the return of your Hello query with the expected value.

Try to use these functions as if you were writing a sentence, to improve readability. For example:

expect(queryResponseField).to.be.eq('Hello, Taqtiler!');
rodmagaldi commented 3 years ago

Finish

taki-tiler-server[bot] commented 3 years ago

Step 4/6 - Database and environments

Estimated time: 1 hour

Now we're going to include the database on our tests. After all, we should test if our queries will be returning what is on the database correctly, and if our mutations are changing the database accordingly.

Do you remember we talked about setting up 2 containers because we were going to use 2 databases? Yeah, the north remembers 🐺! As a preparation for this step, you're going to prepare 2 environments: the one you're already using to develop with npm start and one additional to run the tests. Do some research about the importance of having separate environments on our development workflow. We will talk about it on our meetings too.

One way of handling separate environments is to use environment variables. They are variables that can be set for each environment, so when we start our server on that environment, we use the specific values for it. We could have as environment variables, for example, our database host, user, url, etc...

Your task now is to set some environment variables to connect with the right database for each environment: localhost and test. Create a .env and a .env.test file to store the values of these variables. This package can help you on reading the right file depending on the environment you're running.

Now, our step-by-step for the tests is incremented again:

  1. Connect to database (the test one)
  2. Start the server
  3. Run a single test
rodmagaldi commented 3 years ago

Finish

taki-tiler-server[bot] commented 3 years ago

Step 5/6 - The Login Mutation test

Estimated time: 3 hours

Now it's time to (finally) write the tests for your recently implemented LoginMutation. But first, some theory: unlike our simple Hello query, this mutation is integrated with database. How should be these tests? Well, some general good practices every test you're going to perform: replace your current 3. run a single test step with:

Write some tests to your LoginMutation. Try to follow those good practices above. If you finished the challenge, you can also check if the token duration is behaving as expected according to rememberMe input

NOTE: don't forget that you should connect to the database before (not that joke again) beginning the tests. And it should be the right one.

NOTE 2: don't forget to open a PR with your tests.

rodmagaldi commented 3 years ago

Finish

taki-tiler-server[bot] commented 3 years ago

Step 6/6 - Error handling

Estimated time: 2 hours

Now it's time to make our LoginMutation as complete as possibile, and for that we're going to predict and treat some possible errors. Take some time to think about what are the possible errors that can happen on this operation, and how your server should proceed on each of them. And after that, take a look at our scenarios:

  1. The client sends on the e-mail field something random that is not an e-mail
  2. The client sends an e-mail that doesn't exist on our database
  3. The client sends an existing e-mail but the password is wrong

There are more possibilities but these 3 are enough for the onboard. What do you think we should do on these scenarios? Well, if you thought about returning something on the errors field, that is indeed a good approach. You should be able to research and find how you can treat errors when you find one on your code, but it's basically throwing an error and treating it on a proper function that the apollo-server library receives on the server setup. Check their docs 😝

But how should we return these errors to the client? Well, there are multiple solutions to that, but we have a suggestion:

{
  code: number;  // Conveniently equal to the HTTP Status Code 
  message: string;  // Message to describe the error
  additionalInfo?: string;   // Additional info, generally good for the client developer to know more of what happened
  // ... GraphQL default fields
}

Your task now is:

  1. Implement the formatError function.
  2. Crete a Typescript interface to represent how your error object will look like. You can follow our suggestion.
  3. Create a class that extends Error and receives the code, the message, and optionally, the additionalInfo.
  4. When you identify the errors on the scenarios described above, throw an error of this class you created with the proper info.
  5. Now, create one additional test for your LoginMutation with those 3 (or more) scenarios, checking if the return is as expected.
rodmagaldi commented 3 years ago

Finish

taki-tiler-server[bot] commented 3 years ago

Click here for your next track