Skip to content

Commit b5a4049

Browse files
committed
add workshop
0 parents  commit b5a4049

8 files changed

+603
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_book

Diff for: 004-js-workshop/004001-install.md

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# 運行範例專案
2+
3+
4+
## 範例專案網址
5+
6+
* <https://github.com/agileworks-tw/express-example>
7+
* <https://github.com/agileworks-tw/express-example-vue>
8+
9+
10+
11+
## server side
12+
13+
```
14+
git clone https://github.com/agileworks-tw/express-example.git
15+
```
16+
17+
```
18+
cd express-example
19+
npm install
20+
node_modules/.bin/sequelize db:migrate
21+
npm start
22+
```
23+
24+
運行網址: <http://localhost:3000/>
25+
26+
27+
### 資料結構說明
28+
29+
```
30+
.
31+
├── README.md
32+
33+
├── app.js 程式進入點
34+
35+
├── package.json 此專案用到的套件
36+
├── config 設定檔
37+
38+
├── models 資料表 ORM 定義
39+
├── migrations 資料庫遷移檔
40+
41+
├── routes controller 及 API path 定義
42+
43+
├── views 後台前端頁面
44+
├── public 靜態檔案
45+
46+
├── test 測試案例
47+
48+
49+
```
50+
51+
52+
## client side
53+
54+
```
55+
git clone https://github.com/agileworks-tw/express-example-vue.git
56+
```
57+
58+
```
59+
npm install
60+
npm run dev
61+
```
62+
63+
運行網址: <http://localhost:4000/>
64+
65+
### 資料結構說明
66+
67+
```
68+
.
69+
├── README.md
70+
├── index.html
71+
├── package.json
72+
73+
├── build 建置相關所需檔案
74+
├── config 設定檔
75+
│ ├── dev.env.js development config
76+
│ ├── index.js
77+
│ └── prod.env.js production config
78+
├── src
79+
│ ├── App.vue
80+
│ ├── main.js
81+
│ ├── assets
82+
│ └── components
83+
│ ├── ToDo.vue ToDo 顯示
84+
│ ├── ToDoForm.vue ToDo 新增表單
85+
│ └── TodoList.vue ToDo 清單及 API 呼叫
86+
└── static
87+
88+
```

Diff for: 004-js-workshop/004002-model.md

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# ORM model 定義
2+
3+
## 使用套件
4+
5+
Sequelize: <http://docs.sequelizejs.com/>
6+
7+
8+
## 定義資料庫連線
9+
10+
11+
```
12+
module.exports = {
13+
development: {
14+
dialect: "sqlite",
15+
storage: "./db.development.sqlite"
16+
},
17+
test: {
18+
dialect: "sqlite",
19+
storage: ":memory:"
20+
},
21+
production: {
22+
username: process.env.DB_USERNAME,
23+
password: process.env.DB_PASSWORD,
24+
database: process.env.DB_NAME,
25+
host: process.env.DB_HOSTNAME,
26+
dialect: 'mysql',
27+
use_env_variable: 'DATABASE_URL'
28+
}
29+
};
30+
```
31+
32+
根據不同 mode 給予不同類型的 database server 的連線方式
33+
34+
35+
## 定義資料表
36+
37+
### User
38+
39+
User 有一欄位為 username
40+
41+
與 Task 資料表為 one to many 的關聯
42+
43+
```
44+
module.exports = (sequelize, DataTypes) => {
45+
var User = sequelize.define('User', {
46+
username: DataTypes.STRING
47+
});
48+
49+
User.associate = function(models) {
50+
models.User.hasMany(models.Task);
51+
};
52+
53+
return User;
54+
};
55+
56+
```
57+
58+
59+
### Task
60+
61+
```
62+
module.exports = (sequelize, DataTypes) => {
63+
var Task = sequelize.define('Task', {
64+
title: DataTypes.STRING
65+
});
66+
67+
Task.associate = function (models) {
68+
models.Task.belongsTo(models.User, {
69+
onDelete: "CASCADE",
70+
foreignKey: {
71+
allowNull: false
72+
}
73+
});
74+
};
75+
76+
return Task;
77+
};
78+
```

Diff for: 004-js-workshop/004003-test.md

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# 測試
2+
3+
## 單元測試:驗證 model 設置正確
4+
5+
### 開始測試前準備
6+
7+
```
8+
before(async function () {
9+
// 初始資料庫
10+
await require('../../models').sequelize.sync();
11+
});
12+
13+
beforeEach(function () {
14+
// 載入預計測試的 model,確保 require 可以正確完成
15+
this.User = require('../../models').User;
16+
this.Task = require('../../models').Task;
17+
});
18+
19+
```
20+
21+
### 測試案例
22+
23+
```
24+
describe('create', function () {
25+
it('creates a task',async function () {
26+
let user = await this.User.create({
27+
username: 'johndoe'
28+
});
29+
let task = await this.Task.create({
30+
title: 'a title',
31+
UserId: user.id
32+
});
33+
expect(task.title).to.equal('a title');
34+
35+
});
36+
});
37+
```
38+
39+
執行 `npm run test-unit` 確認運行結果
40+
41+
42+
```
43+
models/task
44+
create
45+
✓ creates a task
46+
47+
```
48+
49+
## 整合測試:定義 API spec
50+
51+
52+
### 開始測試前準備
53+
54+
```
55+
before(async function () {
56+
await require('../../models').sequelize.sync();
57+
});
58+
59+
beforeEach(async function () {
60+
this.models = require('../../models');
61+
await this.models.Task.destroy({ truncate: true })
62+
await this.models.User.destroy({ truncate: true })
63+
64+
});
65+
66+
```
67+
68+
### 測試案例
69+
70+
```
71+
72+
it('透過 api 取得特定 user 之所有 task list 資料', async function () {
73+
// 建立測試資料
74+
let username = 'johndoe';
75+
let user = await this.models.User.create({
76+
username
77+
});
78+
79+
await this.models.Task.create({
80+
title: 'johndoe task',
81+
UserId: user.id
82+
});
83+
84+
// 呼叫 API 取得資料
85+
let response = await request(app).get(`/api/users/${username}/tasks`);
86+
let result = response.body;
87+
88+
// 確認資料結構
89+
expect(result.tasks).to.be.an('array');
90+
expect(result.tasks[0])
91+
.to.be.an('object')
92+
.and.to.have.property("title");
93+
});
94+
95+
it('透過 api 新增特定 user 之 task 資料', async function () {
96+
97+
// 建立測試資料
98+
let username = 'andy';
99+
await this.models.User.create({
100+
username
101+
});
102+
103+
let taskData = {
104+
title: "andy task"
105+
}
106+
107+
// 呼叫 API 新增 task
108+
let response = await request(app)
109+
.post(`/api/users/${username}/tasks/create`)
110+
.send(taskData);
111+
let result = response.body;
112+
113+
// 確認資料結構
114+
expect(result.task)
115+
.to.be.an('object')
116+
.and.to.have.property("title");
117+
});
118+
119+
120+
121+
```
122+
因為是測試先行,尚未實作 API,因此在這邊運作下列指令時
123+
124+
`npm run test-integration`
125+
126+
將會出現下面錯誤訊息
127+
128+
```
129+
1) 透過 api 取得特定 user 之所有 task list 資料
130+
2) 透過 api 新增特定 user 之 task 資料
131+
132+
0 passing (513ms)
133+
2 failing
134+
135+
1) user creation page
136+
透過 api 取得特定 user 之所有 task list 資料:
137+
Error: expected undefined to be an array
138+
at Assertion.assert
139+
2) user creation page
140+
透過 api 新增特定 user 之 task 資料:
141+
Error: expected undefined to be an object
142+
```
143+
144+
下一節將實作 API 並且在前台尚未開始使用 API 時,透過 test case 驗證 API 運作正常。

0 commit comments

Comments
 (0)