To test the endpoints of task’s resource, we are going to cheat the JWT authentication. After all, will be necessary to correctly test the results of this resource and also the others resources which involves user’s authentication. To start it, let’s create the structure for the tasks tests.
Create the filetest/routes/tasks.jswith the following code:
1 import jwt from "jwt-simple";
2
3 describe("Routes: Tasks", () => {
4 const Users = app.db.models.Users;
5 const Tasks = app.db.models.Tasks;
6 const jwtSecret = app.libs.config.jwtSecret;
7 let token;
8 let fakeTask;
9 beforeEach(done => {
10 // Runs before each test...
11 });
12 describe("GET /tasks", () => {
13 describe("status 200", () => {
14 it("returns a list of tasks", done => {
15 // Test's logic...
16 });
17 });
18 });
19 describe("POST /tasks/", () => {
20 describe("status 200", () => {
21 it("creates a new task", done => {
22 // Test's logic...
23 });
24 });
25 });
26 describe("GET /tasks/:id", () => {
27 describe("status 200", () => {
28 it("returns one task", done => {
29 // Test's logic...
30 });
31 });
32 describe("status 404", () => {
33 it("throws error when task not exist", done => {
34 // Test's logic...
35 });
36 });
37 });
38 describe("PUT /tasks/:id", () => {
39 describe("status 204", () => {
40 it("updates a task", done => {
41 // Test's logic...
42 });
43 });
44 });
45 describe("DELETE /tasks/:id", () => {
46 describe("status 204", () => {
47 it("removes a task", done => {
48 // Test's logic...
49 });
50 });
51 });
52 });
Detailing how to cheat the authentication part, we are going to reuse the module jwt-simple to
create a valid token which will be used in the header of all the tests. This token will be repeatedly generated within the callback of the function beforeEach(done). But, to generate it, we have to
delete all users first using the functionUsers.destroy({where: {}}) and then, create a new one
viaUsers.create()function.
We’ll do the same with tasks creation, but instead of using the functionTasks.create()it will be
used the functionTasks.bulkCreate()which allows sending an array of tasks to be inserted in a
single execution (this function is very useful for inclusion in a plot of data).
The tasks are going to use theuser.idfield, created to ensure that they are from the authenticated
user. In the end, let’s use the first task created by the piecefakeTask = tasks[0]to reuse itsidon
the tests that need a taskidas a route parameter. We’ll generate a valid token using the function
jwt.encode({id: user.id}, jwtSecret).
so they can be reused on the tests. To understand in detail, you need to write the following implementation: 1 beforeEach(done => { 2 Users 3 .destroy({where: {}}) 4 .then(() => Users.create({ 5 name: "John", 6 email: "[email protected]", 7 password: "12345" 8 })) 9 .then(user => { 10 Tasks 11 .destroy({where: {}}) 12 .then(() => Tasks.bulkCreate([{ 13 id: 1, 14 title: "Work", 15 user_id: user.id 16 }, { 17 id: 2, 18 title: "Study", 19 user_id: user.id 20 }])) 21 .then(tasks => { 22 fakeTask = tasks[0];
23 token = jwt.encode({id: user.id}, jwtSecret);
24 done();
25 });
26 });
27 });
With the pre-test routine ready, we are going to write all the tasks tests, starting with theGET /
route. On it, it is performed a request viarequest.get("/tasks")function, using also the function set("Authorization", JWT ${token})to allows sending a header on the request, which in this case,
the headerAuthorizationis sent along with the value of a valid token.
To make sure the test is successfully accomplished:
1. We check thestatus 200viaexpect(200)function;
2. We apply a simple validation to ensure that the array of size 2 will be returned via
expect(res.body).to.have.length 2) function;
3. We compare if the titles of the first two tasks are the same as those created by the function
1 describe("GET /tasks", () => {
2 describe("status 200", () => {
3 it("returns a list of tasks", done => {
4 request.get("/tasks")
5 .set("Authorization", `JWT ${token}`)
6 .expect(200)
7 .end((err, res) => {
8 expect(res.body).to.have.length(2);
9 expect(res.body[0].title).to.eql("Work");
10 expect(res.body[1].title).to.eql("Study");
11 done(err);
12 });
13 });
14 });
15 });
To test the successful case of the routePOST /tasks, there is no secret: basically is informed a header
with an authentication token and a title for a new task. As result, we test if the answer returns200
status code and if the objectreq.bodyhas the same title as the one which was sent to register a new
task.
1 describe("POST /tasks", () => {
2 describe("status 200", () => {
3 it("creates a new task", done => {
4 request.post("/tasks")
5 .set("Authorization", `JWT ${token}`)
6 .send({title: "Run"}) 7 .expect(200) 8 .end((err, res) => { 9 expect(res.body.title).to.eql("Run"); 10 expect(res.body.done).to.be.false; 11 done(err); 12 }); 13 }); 14 }); 15 });
Now we are going to test two simple flows of the route GET /tasks/:id. In the successful case
we’ll use theidof the objectfakeTaskto make sure a valid task will be returned. To test how the
application behaves when a id of an invalid task is informed, we are going to use the function expect(404)to test thestatus 404that indicates if the request did not find a resource.
1 describe("GET /tasks/:id", () => {
2 describe("status 200", () => {
3 it("returns one task", done => {
4 request.get(`/tasks/${fakeTask.id}`)
5 .set("Authorization", `JWT ${token}`)
6 .expect(200) 7 .end((err, res) => { 8 expect(res.body.title).to.eql("Work"); 9 done(err); 10 }); 11 }); 12 }); 13 describe("status 404", () => {
14 it("throws error when task not exist", done => {
15 request.get("/tasks/0")
16 .set("Authorization", `JWT ${token}`)
17 .expect(404)
18 .end((err, res) => done(err));
19 });
20 });
21 });
To finish the tests, we are going to test the successful behavior of the routesPUT /tasks/:idand DELETE /tasks/:id. Both of them will use the same functions, except that a test is going to execute
the functionrequest.put()and the other one is going to executerequest.delete(). But, both of
them expect that the request returns a204status code viaexpect(204)function.
1 describe("PUT /tasks/:id", () => {
2 describe("status 204", () => {
3 it("updates a task", done => {
4 request.put(`/tasks/${fakeTask.id}`)
5 .set("Authorization", `JWT ${token}`)
6 .send({
7 title: "Travel",
8 done: true
9 })
10 .expect(204)
11 .end((err, res) => done(err));
12 });
13 });
14 });
16 describe("status 204", () => {
17 it("removes a task", done => {
18 request.delete(`/tasks/${fakeTask.id}`)
19 .set("Authorization", `JWT ${token}`)
20 .expect(204)
21 .end((err, res) => done(err));
22 });
23 });
24 });
We have finished the tests of tasks resources. In case you execute the commandnpm testagain, you
Testing task’s resource