Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1a5aa7b
test: 新增 AdminPage、LoginPage、DashboardPage 頁面的單元測試,並加入相關測試文件與模擬服務工作者。
SHIHTSUNG63 Mar 9, 2026
5b88c93
feat: 新增登入頁面及其單元測試,包含前端驗證、登入邏輯與錯誤處理。
SHIHTSUNG63 Mar 10, 2026
7929fa5
test: 新增 AdminPage、DashboardPage 及 LoginPage 的單元測試與相關文件。
SHIHTSUNG63 Mar 10, 2026
544938e
ci: 新增 GitHub Actions 工作流程,用於執行測試並上傳覆蓋率與測試報告。
SHIHTSUNG63 Mar 10, 2026
53a3be1
Merge pull request #1 from SHIHTSUNG63/develop
SHIHTSUNG63 Mar 10, 2026
a44259a
feat: 新增登入頁面元件、其單元測試與測試文件
SHIHTSUNG63 Mar 11, 2026
5969046
feat: Add GitHub Actions workflow for automated testing with coverage…
SHIHTSUNG63 Mar 12, 2026
25f72f2
feat: Add GitHub Actions workflow for automated testing with coverage…
SHIHTSUNG63 Mar 12, 2026
83d843b
ci: Add GitHub Actions workflow for automated testing and coverage re…
SHIHTSUNG63 Mar 12, 2026
7603c37
測試程式錯誤狀態
SHIHTSUNG63 Mar 12, 2026
73b14c0
測試程式錯誤上傳
SHIHTSUNG63 Mar 16, 2026
0b9e113
修改正確後再上傳
SHIHTSUNG63 Mar 16, 2026
b5d3f16
Merge pull request #2 from SHIHTSUNG63/develop
SHIHTSUNG63 Mar 16, 2026
fb58a80
錯誤測試
SHIHTSUNG63 Mar 16, 2026
88f6ae3
程式錯誤修改完成
SHIHTSUNG63 Mar 16, 2026
2c5cb93
Merge pull request #3 from SHIHTSUNG63/develop
SHIHTSUNG63 Mar 16, 2026
cf66b86
測試修改
SHIHTSUNG63 Mar 16, 2026
cf1421f
測試
SHIHTSUNG63 Mar 16, 2026
cb88f03
Merge pull request #4 from SHIHTSUNG63/develop
SHIHTSUNG63 Mar 16, 2026
b96a1af
test1
SHIHTSUNG63 Mar 16, 2026
047065c
Merge pull request #5 from SHIHTSUNG63/develop
SHIHTSUNG63 Mar 16, 2026
3622b63
test2
SHIHTSUNG63 Mar 16, 2026
afabe51
Merge pull request #6 from SHIHTSUNG63/develop
SHIHTSUNG63 Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .agent/workflows/gen-test-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ description: 生成測試案例工作流

STEP 1: 檢查專案底下是否建立 `doc/test` 資料夾,若無則建立

STEP 2: 根據選擇範圍撰寫測試案例清單,撰寫格式請參考 `.agent/workflows/test/template.md`,並將發想的結果用 Markdown 格式寫入 `doc/test` 底下,完成後進行 Reivew 不要直接生成測試程式,確認符合預期後再下一步
STEP 2: 根據選擇範圍撰寫測試案例清單,撰寫格式請參考 `.agent/workflows/test/test-doc-template.md`,並將發想的結果用 Markdown 格式寫入 `doc/test` 底下,完成後進行 Reivew 不要直接生成測試程式,確認符合預期後再下一步

STEP 3: 參考上一步完成的 `doc/test` 撰寫測試程式,不同頁面需建立獨立檔案

**重要規則:**

- 第二層 `describe()` 必須為「測試類型」,下面每一個 `it()` 描述必須為對應的測試案例的「測試說明」
- `it()` 內的文字描述請「直接使用 Markdown 的原文,不需翻譯、不需重新命名」


STEP 4: 驗證測試程式,若結果符合預期,請去 doc/test 底下,將 Markdown 打勾

STEP 5: 若測試不符預期,重複 STEP 3–4,最多 5 次,仍失敗就討論原因
STEP 5: 若測試不符預期,重複 STEP 3–4,最多 5 次,仍失敗就討論原因
38 changes: 38 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Automated Testing

on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run tests with coverage
run: npm run test:coverage

- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
retention-days: 7
38 changes: 38 additions & 0 deletions doc/test/AdminPage-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
> 狀態:初始為 [ ]、完成為 [x]
> 注意:狀態只能在測試通過後由流程更新。
> 測試類型:前端元素、function 邏輯、Mock API、驗證權限...

---

## [x] 【前端元素】畫面正常渲染管理後台

**範例輸入**:存取管理後台頁面
**期待輸出**:畫面顯示「🛠️ 管理後台」標題、返回連結、登出按鈕,以及「管理員專屬頁面」的功能介紹區塊

---

## [x] 【前端邏輯】正確顯示管理員身分標籤

**範例輸入**:AuthContext 提供 `user.role` 為 `admin`
**期待輸出**:畫面右上角的身分標籤顯示「管理員」,且帶有多出的 `admin` class

---

## [x] 【前端邏輯】正確顯示一般用戶身分標籤

**範例輸入**:AuthContext 提供 `user.role` 為 `user`
**期待輸出**:畫面右上角的身分標籤顯示「一般用戶」,且帶有多出的 `user` class

---

## [x] 【路由導向】點擊返回按鈕

**範例輸入**:點擊「← 返回」連結
**期待輸出**:導向至 `/dashboard`

---

## [x] 【前端邏輯】點擊登出按鈕

**範例輸入**:點擊「登出」按鈕
**期待輸出**:觸發 `logout()` 函數,並導向至 `/login`(使用 replace,且 state 設為 null)
22 changes: 22 additions & 0 deletions doc/test/AdminPage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# AdminPage 測試案例

> 狀態:初始為 [ ]、完成為 [x]
> 注意:狀態只能在測試通過後由流程更新。

---

## [ ] 【畫面渲染】應該正確渲染管理後台的元素
**範例輸入**:進入 /admin 頁面
**期待輸出**:顯示「管理後台」標題、返回 Dashboard 連結及管理員專屬資訊卡片

---

## [x] 【權限顯示】應正確顯示使用者的角色標籤
**範例輸入**:依據 user.role 分別渲染為 'admin' 或 'user'
**期待輸出**:為 admin 時顯示「管理員」,否則顯示「一般用戶」

---

## [x] 【登出邏輯】點擊登出按鈕應觸發登出並導向登入頁
**範例輸入**:點擊「登出」按鈕
**期待輸出**:呼叫 `logout` 函式,並導向至 `/login` 頁面
59 changes: 59 additions & 0 deletions doc/test/DashboardPage-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
> 狀態:初始為 [ ]、完成為 [x]
> 注意:狀態只能在測試通過後由流程更新。
> 測試類型:前端元素、function 邏輯、Mock API、驗證權限...

---

## [x] 【前端邏輯】管理員看到專屬連結

**範例輸入**:AuthContext 提供 `user.role` 為 `admin`,預設 Mock API 回傳空列表
**期待輸出**:Header 導覽列出現「🛠️ 管理後台」連結

---

## [x] 【前端邏輯】一般用戶看不到專屬連結

**範例輸入**:AuthContext 提供 `user.role` 為 `user`,預設 Mock API 回傳空列表
**期待輸出**:Header 導覽列不應該出現「🛠️ 管理後台」連結

---

## [x] 【前端邏輯】歡迎區塊正常渲染用戶資訊

**範例輸入**:AuthContext 提供 `user.username` 為 `TestUser`,`user.role` 為 `user`
**期待輸出**:歡迎區塊顯示「Welcome, TestUser 👋」,頭像顯示「T」,身分標籤顯示「一般用戶」

---

## [x] 【Mock API】初始載入時顯示 Loading

**範例輸入**:`productApi.getProducts` 設定為延遲回傳
**期待輸出**:商品列表區塊顯示「載入商品中...」與 spinner

---

## [x] 【Mock API】成功取得商品資料並渲染

**範例輸入**:`productApi.getProducts` 成功回傳兩筆商品資料(例如 商品A 100元, 商品B 200元)
**期待輸出**:畫面不再顯示 Loading,並成功渲染出 商品A 與 商品B 的卡片,且價格有正確格式化(例如 `NT$ 100`)

---

## [ ] 【Mock API】取得商品資料失敗且後端有錯誤訊息

**範例輸入**:`productApi.getProducts` 失敗,AxiosError 回傳 500 錯誤與 `{ message: '伺服器發生異常' }`
**期待輸出**:商品列表區塊顯示錯誤圖示與文字「伺服器發生異常」

---

## [ ] 【Mock API】取得商品資料失敗時的預設錯誤訊息

**範例輸入**:`productApi.getProducts` 失敗,AxiosError 回傳 500 錯誤但無自訂 `message`
**期待輸出**:商品列表區塊顯示錯誤區塊與預設訊息「無法載入商品資料」

---

## [ ] 【前端邏輯】點擊登出按鈕

**範例輸入**:點擊 Header 的「登出」按鈕
**期待輸出**:觸發 `logout()` 函數,並導向至 `/login`(使用 replace,且 state 設為 null)
52 changes: 52 additions & 0 deletions doc/test/DashboardPage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# DashboardPage 測試案例

> 狀態:初始為 [ ]、完成為 [x]
> 注意:狀態只能在測試通過後由流程更新。

---

## [ ] 【畫面渲染】初始載入時應顯示載入中狀態
**範例輸入**:進入 /dashboard 頁面,API 正在請求中
**期待輸出**:顯示「載入商品中...」及 Loading Spinner

---

## [x] 【畫面渲染】API 請求成功後應正確顯示商品列表
**範例輸入**:API 回傳包含商品資訊的陣列
**期待輸出**:隱藏 Loading 狀態,並渲染對應數量的商品卡片,顯示商品名稱、描述與價格

---

## [x] 【錯誤處理】API 請求失敗時 (非 401) 應顯示錯誤訊息
**範例輸入**:API 回傳 500 等錯誤,且帶有 message
**期待輸出**:隱藏 Loading 狀態,顯示 API 的錯誤訊息或預設錯誤訊息「無法載入商品資料」

---

## [x] 【錯誤處理】Token 過期或無效 (401) 時不顯示預設錯誤訊息
**範例輸入**:API 回傳 401 錯誤
**期待輸出**:交由 axios interceptor 處理,畫面上不會另外顯示 401 的文字錯誤狀態

---

## [x] 【權限顯示】依據使用者名稱正確顯示歡迎詞與頭像
**範例輸入**:user 資料為 username: 'Alice'
**期待輸出**:顯示「Welcome, Alice 👋」,頭像顯示 'A'

---

## [x] 【權限顯示】為管理員時應顯示前往管理後台的連結
**範例輸入**:user.role 為 'admin'
**期待輸出**:顯示「🛠️ 管理後台」的連結,可導向 /admin

---

## [ ] 【權限顯示】非管理員時不應顯示管理後台連結
**範例輸入**:user.role 不為 'admin' (如 'user')
**期待輸出**:不顯示「🛠️ 管理後台」的連結

---

## [ ] 【登出邏輯】點擊登出按鈕應觸發登出並導向登入頁
**範例輸入**:點擊「登出」按鈕
**期待輸出**:呼叫 `logout` 函式,並導向至 `/login` 頁面
66 changes: 66 additions & 0 deletions doc/test/LoginPage-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
> 狀態:初始為 [ ]、完成為 [x]
> 注意:狀態只能在測試通過後由流程更新。
> 測試類型:前端元素、function 邏輯、Mock API、驗證權限...

---

## [x] 【前端元素】畫面正常渲染登入表單

**範例輸入**:存取登入頁面
**期待輸出**:畫面顯示 Email 輸入框、密碼輸入框、以及「登入」按鈕

---

## [x] 【前端驗證】無效的 Email 格式

**範例輸入**:輸入 Email 為 `invalid`,密碼為 `Valid123`,並點擊登入
**期待輸出**:Email 欄位下方顯示「請輸入有效的 Email 格式」,且不觸發 API 請求

---

## [x] 【前端驗證】密碼長度不足 8 碼

**範例輸入**:輸入 Email 為 `test@example.com`,密碼為 `a1`,並點擊登入
**期待輸出**:密碼欄位下方顯示「密碼必須至少 8 個字元」,且不觸發 API 請求

---

## [x] 【前端驗證】密碼未包含英數混合

**範例輸入**:輸入 Email 為 `test@example.com`,密碼為 `12345678`,並點擊登入
**期待輸出**:密碼欄位下方顯示「密碼必須包含英文字母和數字」,且不觸發 API 請求

---

## [x] 【Mock API】登入成功時顯示載入中並導向

**範例輸入**:輸入正確格式的 Email 與密碼並提交,Mock API 設定為延遲並回傳成功
**期待輸出**:按鈕文字變成「登入中...」並帶有 spinner,API 成功後導向至 `/dashboard`(使用 replace)

---

## [x] 【Mock API】登入失敗時顯示後端自訂錯誤訊息

**範例輸入**:輸入正確格式的 Email 與密碼並提交,Mock API 回傳 401 與錯誤訊息 `帳號或密碼錯誤`
**期待輸出**:按鈕恢復為「登入」,且畫面上方的錯誤區塊 (`error-banner`) 顯示 `帳號或密碼錯誤`

---

## [x] 【Mock API】登入失敗且後端未提供訊息時的預設錯誤

**範例輸入**:輸入正確格式的 Email 與密碼並提交,Mock API 回傳 500(未包含特定 message)
**期待輸出**:錯誤區塊顯示預設訊息「登入失敗,請稍後再試」

---

## [x] 【路由導向】若已登入則自動導回控制台

**範例輸入**:設定 AuthContext 中的 `isAuthenticated` 為 `true`,存取登入頁
**期待輸出**:自動導向至 `/dashboard`(使用 replace)

---

## [x] 【全域狀態】顯示登入過期的快顯訊息

**範例輸入**:設定 AuthContext 中的 `authExpiredMessage` 為 `您的登入已過期`
**期待輸出**:錯誤區塊顯示 `您的登入已過期`,且觸發 `clearAuthExpiredMessage` 清除原訊息
58 changes: 58 additions & 0 deletions doc/test/LoginPage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# LoginPage 測試案例

> 狀態:初始為 [ ]、完成為 [x]
> 注意:狀態只能在測試通過後由流程更新。

---

## [ ] 【畫面渲染】應該正確渲染登入表單與相關元素
**範例輸入**:進入 /login 頁面
**期待輸出**:顯示「歡迎回來」標題、Email 輸入框、密碼輸入框及登入按鈕

---

## [x] 【表單驗證】輸入無效的 Email 格式時應顯示錯誤訊息
**範例輸入**:在 Email 輸入框輸入 `invalid-email` 並提交表單
**期待輸出**:顯示「請輸入有效的 Email 格式」錯誤訊息,且不會觸發登入 API

---

## [x] 【表單驗證】輸入長度不足的密碼時應顯示錯誤訊息
**範例輸入**:在密碼輸入框輸入 `Short1!` 並提交表單
**期待輸出**:顯示「密碼必須至少 8 個字元」錯誤訊息,且不會觸發登入 API

---

## [x] 【表單驗證】輸入未包含大小寫與數字的密碼時應顯示錯誤訊息
**範例輸入**:在密碼輸入框輸入 `alllowercase123` 或 `ALLUPPERCASE123` 等缺乏組成的密碼並提交表單
**期待輸出**:顯示「密碼必須包含大小寫英文字母和數字」錯誤訊息,且不會觸發登入 API

---

## [x] 【登入邏輯】API 回傳錯誤時應顯示錯誤提示
**範例輸入**:輸入正確格式的 Email 與密碼,但 API 回傳登入失敗
**期待輸出**:畫面上方顯示「登入失敗,請稍後再試」或 API 回傳的具體錯誤訊息

---

## [ ] 【登入邏輯】登入成功後應導向至 Dashboard
**範例輸入**:輸入正確格式的 Email 與密碼,API 回傳成功
**期待輸出**:成功調用 login 函式,並導向至 `/dashboard` 頁面

---

## [ ] 【狀態處理】提交表單時按鈕應顯示載入中狀態並禁用
**範例輸入**:點擊登入按鈕提交表單
**期待輸出**:按鈕文字變更為「登入中...」,且輸入框與按鈕皆設定為 disabled

---

## [ ] 【已登入狀態】若使用者已認證應自動導向至 Dashboard
**範例輸入**:在 isAuthenticated 為 true 的狀態下訪問 /login
**期待輸出**:自動導向至 `/dashboard` 頁面

---

## [ ] 【狀態處理】若有 authExpiredMessage 應顯示並清除狀態
**範例輸入**:由 AuthContext 取得 authExpiredMessage 為「登入已過期」
**期待輸出**:顯示對應 API 錯誤訊息,並呼叫 clearAuthExpiredMessage
Loading