Skip to content

Commit 8dc9171

Browse files
committed
update L9 script
1 parent 034475d commit 8dc9171

File tree

7 files changed

+302
-172
lines changed

7 files changed

+302
-172
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@ This work is licensed under a
117117
3. [Deleting a to-do with help of form](./html-forms/delete-todo/README.md)
118118

119119
### CSRF token
120-
4. [What is Cross Site Request Forgery (CSRF) and why should we care?](./html-forms/why-csrf/README.md)
121-
5. [Use csurf package in express.js application](./html-forms/use-csurf/README.md)
122-
6. [What are APIs](./html-forms/what-are-apis/README.md)
123-
7. [Send JSON or HTML response based on request headers](./html-forms/html-or-json-response/README.md)
120+
4. [What are APIs](./html-forms/what-are-apis/README.md)
121+
5. [Send JSON or HTML response based on request headers](./html-forms/html-or-json-response/README.md)
122+
6. [What is Cross Site Request Forgery (CSRF) and why should we care?](./html-forms/why-csrf/README.md)
123+
7. [Use csurf package in express.js application](./html-forms/use-csurf/README.md)
124124
8. [Milestone](./html-forms/milestone/README.md)
125125

126126
## L10. User Authentication and final wrap-up

backend-dev-with-express/add-tests/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
## Text
22

3-
In this lesson, we will look into how to test the routes that we have created for our Todo web application. First, we need to install a npm package `supertest` to help us with the testing. We will install it as a development dependency.
3+
In this lesson, we will learn, how to test the web endpoints of our application. But before doing that, make sure you have configured the pre-commit hook to run tests and lint-staged using husky.
4+
5+
To run the tests, we use jest. Along with jest, we will also install another npm package called `supertest`. We will use `supertest` to send request to our express.js routes.
46

57
```sh
6-
npm install -D supertest
8+
npm install -D jest supertest
79
```
810

9-
We will use `supertest` to send request to our express.js routes.
10-
1111
Next, we will edit the test scripts in `package.json` to drop and create the database before running the tests. We will use the `db:drop` command available with `sequelize-cli` to destroy the test database. Then we create a clean slate by using the `db:create` command.
1212

1313
```json

html-forms/add-new-todo/README.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,41 @@ Edit the `app.js` with following contents.
77
First, we need to import the database models.
88

99
```js
10-
const db = require("../models/index");
10+
const { Todo } = require("../models");
1111
```
1212

1313
Next, we can add the endpoint to display todo list in the browser.
1414

1515
```js
16-
app.get("/todos", async function (req, res, next) {
17-
const overdue = await db.Todo.overdue();
18-
const dueToday = await db.Todo.dueToday();
19-
const dueLater = await db.Todo.dueLater();
16+
app.get("/", async function (request, response) {
17+
const overdue = await Todo.overdue();
18+
const dueToday = await Todo.dueToday();
19+
const dueLater = await Todo.dueLater();
2020
res.render("index", { overdue, dueToday, dueLater });
2121
});
2222
```
2323

24-
To create a new todo, web browser should send a `POST` request. The required parameters like `title` and `dueDate` are sent as body of the `POST` request. To create such a handler we need to declare it using `router.post`. Express.js would parse the body of the request and make them available at `req.body`. And we would be able to extract `title` and `dueDate` from `req.body`.
24+
To create a new todo, web browser should send a `POST` request. The required parameters like `title` and `dueDate` are sent as body of the `POST` request. To create such a handler we need to declare it using `app.post`. Express.js would parse the body of the request and make them available at `request.body`. And we would be able to extract `title` and `dueDate` from `request.body`.
2525

2626
```js
27-
app.post("/todos", async function (req, res, next) {
28-
await db.Todo.addTask({
29-
title: req.body.title,
30-
dueDate: new Date(req.body.dueDate),
31-
});
32-
res.redirect("/todos");
27+
app.post("/todos", async (request, response) => {
28+
console.log("Creating a todo", request.body);
29+
try {
30+
await Todo.addTodo({
31+
title: request.body.title,
32+
dueDate: request.body.dueDate,
33+
});
34+
return response.redirect("/");
35+
} catch (error) {
36+
console.log(error);
37+
return response.status(422).json(error);
38+
}
3339
});
3440
```
3541

3642
Now we have the backend functioning. We will now adapt this functionality to the frontend.
3743

38-
Let's edit the `todos.ejs` file to make sure the new todo item form has an `action` and `method` attribute.
44+
Let's edit the `index.ejs` file to make sure the new todo item form has an `action` and `method` attribute.
3945

4046
```html
4147
<form action="/todos" method="POST">...</form>
@@ -48,27 +54,26 @@ Next, we need to make sure the todo text is sent to server using the key `title`
4854
```html
4955
<form action="/todos" method="POST">
5056
<div class="flex gap-2 py-4">
51-
<div class="flex-auto w-64">
57+
<div class="flex-auto">
5258
<input
5359
type="text"
54-
class="border border-gray-300 text-gray-900 text-sm rounded w-full p-2"
5560
placeholder="What's next?"
5661
name="title"
57-
autofocus
62+
class="border border-gray-300 rounded text-gray-900 w-full p-2 text-sm"
5863
required
5964
/>
6065
</div>
61-
<div class="flex-auto w-32">
66+
<div class="flex-auto">
6267
<input
6368
type="date"
6469
name="dueDate"
65-
class="border border-gray-300 text-gray-900 text-sm rounded w-full p-2 leading-4 "
70+
class="border border-gray-300 rounded text-gray-900 w-full p-2 text-sm leading-4 "
6671
/>
6772
</div>
6873
<div class="flex-none">
6974
<button
7075
type="submit"
71-
class="text-white bg-green-600 hover:bg-green-700 font-medium rounded text-sm px-5 py-2 mr-2 mb-2"
76+
class="bg-green-600 text-white px-5 py-1.5 rounded font-medium mr-2 mb-2"
7277
>
7378
Add
7479
</button>

html-forms/delete-todo/README.md

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,79 +2,81 @@
22

33
In this lesson, we will add capability to delete to-do item.
44

5-
First, let's edit the `todos.js` file in `router` folder to add this capability. To delete an entry in database, we use `delete` request. So let's add such a route.
5+
We will first add capability to remove an item to our model. Edit the `models/todo.js` to have a `remove` method.
66

77
```js
8-
app.delete('/todos/:id', async function (req, res, next) {
9-
await db.Todo.removeTask(req.params.id);
10-
res.json({ success: true })
11-
});
8+
static async remove(id) {
9+
return this.destroy({
10+
where: {
11+
id,
12+
},
13+
});
14+
}
1215
```
1316

14-
Here, the `id` of the todo item which is to be deleted is passed in the url. We just need to invoke the `removeTask` method which we have already implemented earlier.
15-
16-
To add this capability to the front end, let's open the `todos.ejs` file in the `views` folder. Now, we need to add capability to delete the to-do when clicked on the trash icon.
17+
Next, let's edit the `app.js` file to add this capability. To delete an entry in database, we use `delete` request. So let's add such a route.
1718

18-
We will wrap the `<a>` tags in its own `form`. Then invoke `deleteTodo` when clicked on it. Here we also pass the id to `deleteTodo` to identify which item was invoked.
19-
20-
```html
21-
<form>
22-
<a class="hidden trash-icon" href="#!" onclick="deleteTodo(<%= dueToday[i].id %>)">
23-
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
24-
stroke="currentColor" stroke-width="2">
25-
<path stroke-linecap="round" stroke-linejoin="round"
26-
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
27-
</svg>
28-
</a>
29-
</form>
19+
```js
20+
app.delete("/todos/:id", async (request, response) => {
21+
try {
22+
await Todo.remove(request.params.id);
23+
return response.json({ success: true });
24+
} catch (error) {
25+
return response.status(422).json(error);
26+
}
27+
});
3028
```
3129

32-
We will do the same for `dueLater` items also
30+
Here, the `id` of the todo item which is to be deleted is passed in the url. We just need to invoke the `remove` method which we have already implemented earlier.
3331

34-
```html
35-
<form>
36-
<a class="hidden trash-icon" href="#!" onclick="deleteTodo(<%= dueLater[i].id %>)">
37-
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
38-
stroke="currentColor" stroke-width="2">
39-
<path stroke-linecap="round" stroke-linejoin="round"
40-
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
41-
</svg>
42-
</a>
43-
</form>
44-
```
32+
To add this capability to the front end, let's open the `todos.ejs` file in the `views` folder. Now, we need to add capability to delete the to-do when clicked on the trash icon.
4533

46-
Next, we have to update the `overdue` items.
34+
We will add `onClick` handler to invoke a `deleteTodo` function when clicked on it. Here we also pass the id to `deleteTodo` to identify which item was invoked.
4735

4836
```html
49-
<form>
50-
<a class="hidden trash-icon" href="#!" onclick="deleteTodo(<%= overdue[i].id %>)">
51-
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
52-
stroke="currentColor" stroke-width="2">
53-
<path stroke-linecap="round" stroke-linejoin="round"
54-
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
55-
</svg>
56-
</a>
57-
</form>
37+
<a
38+
href="#"
39+
class="hidden trash-icon ml-2"
40+
onclick="deleteTodo(<%= data[i].id %>)"
41+
>
42+
<svg
43+
xmlns="http://www.w3.org/2000/svg"
44+
fill="none"
45+
viewBox="0 0 24 24"
46+
stroke-width="1.5"
47+
stroke="currentColor"
48+
class="w-4 h-4"
49+
>
50+
<path
51+
stroke-linecap="round"
52+
stroke-linejoin="round"
53+
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
54+
/>
55+
</svg>
56+
</a>
5857
```
5958

6059
Now, we have to implement the actual JavaScript function `deleteTodo` which actually sends the delete request to the server.
6160

6261
```js
6362
function deleteTodo(id) {
64-
fetch(`/todos/${id}`, {
65-
method: 'delete',
66-
headers: { 'Content-Type': 'application/json' },
67-
}).then((res) => {
68-
window.location.reload();
69-
}).catch(err => console.error(err))
70-
}
63+
fetch(`/todos/${id}`, {
64+
method: "delete",
65+
headers: { "Content-Type": "application/json" },
66+
})
67+
.then((res) => {
68+
window.location.reload();
69+
})
70+
.catch((err) => console.error(err));
71+
}
7172
```
7273

7374
Here, We have used the built in `fetch` to do the network request of type `delete`.
7475

7576
Now, let's run the express server.
7677

7778
```sh
78-
DEBUG=todo-manager:* npm start
79+
npm start
7980
```
80-
Open the browser and visit `http://localhost:3000/todos` to view our to-do application. Now we should be able to click on thrash icon of the todo items and delete it.
81+
82+
Open the browser and visit `http://localhost:3000/` to view our to-do application. Now we should be able to click on thrash icon of the todo items and delete it.

html-forms/html-or-json-response/README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,21 @@ Accept: application/json
2525
Let's modify the listing of Todos to return html when visited using browser and return a `JSON` response when it is invoked using Postman.
2626

2727
```js
28-
app.get("/todos", async function (req, res, next) {
29-
const overdue = await db.Todo.overdue();
30-
const dueToday = await db.Todo.dueToday();
31-
const dueLater = await db.Todo.dueLater();
32-
if (req.accepts("html")) {
33-
res.render("index", {
28+
app.get("/", async (request, response) => {
29+
const overdue = await Todo.overdue();
30+
const dueToday = await Todo.dueToday();
31+
const dueLater = await Todo.dueLater();
32+
const completed = await Todo.completed();
33+
if (request.accepts("html")) {
34+
response.render("index", {
3435
title: "Todo application",
3536
overdue,
3637
dueToday,
3738
dueLater,
38-
csrfToken: req.csrfToken(),
39+
completed,
3940
});
4041
} else {
41-
res.json({
42+
response.json({
4243
overdue,
4344
dueToday,
4445
dueLater,
@@ -47,15 +48,15 @@ app.get("/todos", async function (req, res, next) {
4748
});
4849
```
4950

50-
Here, we check whether the client accepts `html` response using `req.accept()`. If the client can accept html response, we render the html page. If it doesn't then we send back a `JSON` reponse.
51+
Here, we check whether the client accepts `html` response using `request.accept()`. If the client can accept html response, we render the html page. If it doesn't then we send back a `JSON` reponse.
5152

5253
Let's save the file and start the app.
5354

5455
```sh
55-
DEBUG=todo-manager:* npm start
56+
npm start
5657
```
5758

58-
If we visit `http://localhost:3000/todos`, we can see the todo list being rendered as HTML. Next, send a request from API client like _Postman_, but also add a HTTP header with key `Accept` and value `application/json` to the same url. You will get a json reponse similar to this:
59+
If we visit `http://localhost:3000/`, we can see the todo list being rendered as HTML. Next, send a request from API client like _Postman_, but also add a HTTP header with key `Accept` and value `application/json` to the same url. You will get a json reponse similar to this:
5960

6061
```json
6162
{

0 commit comments

Comments
 (0)