# Test Cases: Tính năng Đăng Nhập (Login Feature)

---

## 📋 Thông tin tài liệu

| Thông tin | Chi tiết |
|-----------|----------|
| **Tên tài liệu** | Test Case - Tính năng Đăng Nhập |
| **Phiên bản** | v1.0 |
| **Ngày tạo** | 2025 |
| **Người tạo** | QA Team |
| **Ứng dụng** | Mobile/Web App |
| **Module** | Authentication - Login |
| **Trạng thái** | Ready for Testing |

---

## 🔖 Chú thích trạng thái (Status Legend)

| Status | Ý nghĩa |
|--------|---------|
| ✅ PASS | Test case thực thi thành công |
| ❌ FAIL | Test case thực thi thất bại |
| ⏳ PENDING | Chưa thực thi |
| ⏭️ SKIP | Bỏ qua (có lý do) |
| 🔄 IN PROGRESS | Đang thực thi |

---

## 🧪 Test Cases

---

### TC-LOGIN-001 — Đăng nhập thành công (Happy Path)

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-001 |
| **Title** | Đăng nhập thành công với email và password hợp lệ |
| **Module** | Login |
| **Priority** | 🔴 High |
| **Type** | Functional - Positive |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang chạy và màn hình Login được hiển thị
- Tài khoản `testuser@example.com` đã được đăng ký và kích hoạt trong hệ thống
- Tài khoản không bị khóa hoặc vô hiệu hóa
- Kết nối internet ổn định

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở ứng dụng, điều hướng đến màn hình Đăng nhập | — |
| 2 | Nhập địa chỉ email vào trường "Email" | `testuser@example.com` |
| 3 | Nhập mật khẩu vào trường "Password" | `Test@1234` |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát kết quả hiển thị trên màn hình | — |

**Expected Result (Kết quả mong đợi):**
- ✔ Hệ thống xác thực thành công
- ✔ Người dùng được chuyển hướng đến màn hình **Dashboard/Home**
- ✔ Tên người dùng hoặc avatar hiển thị đúng trên header
- ✔ Không có thông báo lỗi nào xuất hiện
- ✔ Thời gian phản hồi ≤ 3 giây

**Actual Result:** _(Điền sau khi thực thi)_

**Notes:** Đây là luồng cơ bản nhất, cần pass 100%.

---

### TC-LOGIN-002 — Đăng nhập với Email không đúng định dạng

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-002 |
| **Title** | Hiển thị lỗi khi nhập email sai định dạng |
| **Module** | Login - Validation |
| **Priority** | 🟠 Medium |
| **Type** | Functional - Negative |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Kết nối internet ổn định

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập chuỗi không phải định dạng email vào trường "Email" | `invalidemail` |
| 3 | Nhập mật khẩu bất kỳ vào trường "Password" | `Test@1234` |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát thông báo lỗi | — |

**Test Data Variations (Các biến thể dữ liệu):**

| # | Email Input | Mô tả |
|---|-------------|-------|
| a | `invalidemail` | Thiếu ký tự `@` và domain |
| b | `invalid@` | Có `@` nhưng thiếu domain |
| c | `@example.com` | Thiếu phần local trước `@` |
| d | `invalid@.com` | Domain bắt đầu bằng dấu chấm |
| e | `invalid @example.com` | Có khoảng trắng trong email |

**Expected Result (Kết quả mong đợi):**
- ✔ Hệ thống **không** thực hiện call API đăng nhập
- ✔ Hiển thị thông báo lỗi inline: *"Email không đúng định dạng"* hoặc tương đương
- ✔ Thông báo lỗi hiển thị ngay dưới trường Email, màu đỏ
- ✔ Người dùng **không** được chuyển trang
- ✔ Trường Email được highlight border màu đỏ

**Actual Result:** _(Điền sau khi thực thi)_

**Notes:** Validation nên xảy ra ở client-side trước khi gửi request.

---

### TC-LOGIN-003 — Đăng nhập với Password không chính xác

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-003 |
| **Title** | Hiển thị lỗi khi nhập sai mật khẩu |
| **Module** | Login - Authentication |
| **Priority** | 🔴 High |
| **Type** | Functional - Negative |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Tài khoản `testuser@example.com` tồn tại trong hệ thống
- Mật khẩu đúng của tài khoản là `Test@1234` (không dùng trong test này)
- Kết nối internet ổn định

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập email hợp lệ đã tồn tại vào trường "Email" | `testuser@example.com` |
| 3 | Nhập mật khẩu **sai** vào trường "Password" | `WrongPass999` |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát thông báo phản hồi từ hệ thống | — |

**Expected Result (Kết quả mong đợi):**
- ✔ Hệ thống từ chối đăng nhập
- ✔ Hiển thị thông báo lỗi chung: *"Email hoặc mật khẩu không chính xác"*
- ✔ Thông báo **KHÔNG** tiết lộ cụ thể trường nào sai (bảo mật)
- ✔ Người dùng vẫn ở màn hình Login
- ✔ Trường Password được xóa nội dung, trường Email giữ nguyên
- ✔ Nếu thất bại ≥ 5 lần: hiển thị CAPTCHA hoặc thông báo khóa tạm thời

**Actual Result:** _(Điền sau khi thực thi)_

**Notes:** Thông báo lỗi chung là yêu cầu bảo mật — không được reveal thông tin cụ thể.

---

### TC-LOGIN-004 — Đăng nhập với các trường để trống

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-004 |
| **Title** | Hiển thị lỗi validation khi để trống Email và/hoặc Password |
| **Module** | Login - Validation |
| **Priority** | 🟠 Medium |
| **Type** | Functional - Negative |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Không cần kết nối internet (validation ở client-side)

**Test Steps (Các bước thực hiện):**

**Scenario A — Cả hai trường đều trống:**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Để trống trường "Email" | *(bỏ trống)* |
| 3 | Để trống trường "Password" | *(bỏ trống)* |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát thông báo lỗi | — |

**Scenario B — Chỉ trống Email:**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Để trống trường "Email" | *(bỏ trống)* |
| 3 | Nhập mật khẩu hợp lệ | `Test@1234` |
| 4 | Nhấn nút **"Đăng nhập"** | — |

**Scenario C — Chỉ trống Password:**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập email hợp lệ | `testuser@example.com` |
| 3 | Để trống trường "Password" | *(bỏ trống)* |
| 4 | Nhấn nút **"Đăng nhập"** | — |

**Expected Result (Kết quả mong đợi):**

| Scenario | Expected |
|----------|----------|
| A | Hiển thị 2 lỗi: *"Email không được để trống"* + *"Mật khẩu không được để trống"* |
| B | Hiển thị lỗi: *"Email không được để trống"* ngay dưới trường Email |
| C | Hiển thị lỗi: *"Mật khẩu không được để trống"* ngay dưới trường Password |

- ✔ Nút "Đăng nhập" có thể bị disable khi fields trống (tùy thiết kế)
- ✔ Không có API call nào được gửi đi
- ✔ Người dùng vẫn ở màn hình Login

**Actual Result:** _(Điền sau khi thực thi)_

---

### TC-LOGIN-005 — Đăng nhập với ký tự đặc biệt trong các trường

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-005 |
| **Title** | Xử lý đúng khi nhập ký tự đặc biệt trong Email và Password |
| **Module** | Login - Input Handling |
| **Priority** | 🟡 Medium |
| **Type** | Functional - Boundary / Security |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Kết nối internet ổn định

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập chuỗi chứa ký tự đặc biệt vào trường "Email" | `test!#$%^&*()@example.com` |
| 3 | Nhập chuỗi chứa ký tự đặc biệt vào trường "Password" | `P@$$w0rd!#%^&*` |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát phản hồi | — |

**Test Data Variations:**

| # | Email | Password | Mục đích |
|---|-------|----------|----------|
| a | `test!#$%@example.com` | `P@$$w0rd!` | Ký tự đặc biệt phổ biến |
| b | `"test"@example.com` | `pass"word` | Dấu ngoặc kép |
| c | `tëst@éxample.com` | `pässwörд` | Ký tự Unicode/quốc tế |
| d | `test@example.com` | `<script>alert(1)</script>` | XSS attempt trong password |
| e | `test😀@example.com` | `pass😀word` | Emoji |

**Expected Result (Kết quả mong đợi):**
- ✔ Hệ thống xử lý input mà **không bị crash hoặc lỗi hệ thống**
- ✔ Ký tự đặc biệt được encode/escape đúng cách trước khi xử lý
- ✔ Nếu email không tồn tại → hiển thị thông báo lỗi đăng nhập bình thường
- ✔ Không có script nào được thực thi (XSS prevention)
- ✔ Không hiển thị stack trace hay lỗi hệ thống ra UI
- ✔ Trường Password vẫn hiển thị dạng masked (ký tự `•`)

**Actual Result:** _(Điền sau khi thực thi)_

**Notes:** Test case này liên quan đến cả bảo mật lẫn UX.

---

### TC-LOGIN-006 — SQL Injection cơ bản qua form Đăng nhập

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-006 |
| **Title** | Hệ thống không bị bypass xác thực khi nhập SQL Injection |
| **Module** | Login - Security |
| **Priority** | 🔴 High |
| **Type** | Security Testing - Negative |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Kết nối internet ổn định
- Người thực hiện test có quyền thực hiện security testing

> ⚠️ **Lưu ý:** Test case này chỉ được thực hiện trên môi trường **Development/Staging**, KHÔNG thực hiện trên Production.

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập payload SQL Injection vào trường "Email" | `' OR '1'='1` |
| 3 | Nhập payload SQL Injection vào trường "Password" | `' OR '1'='1' --` |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát phản hồi và kiểm tra xem có bị bypass không | — |

**SQL Injection Payloads cần test:**

| # | Email Payload | Password Payload | Mục đích |
|---|---------------|------------------|----------|
| a | `' OR '1'='1` | `' OR '1'='1' --` | Classic bypass |
| b | `admin'--` | `anything` | Comment out password check |
| c | `' OR 1=1--` | `''` | Always-true condition |
| d | `'; DROP TABLE users;--` | `test` | Destructive injection |
| e | `" OR "1"="1` | `" OR "1"="1"` | Double quote variant |
| f | `' UNION SELECT 1,1,1--` | `test` | UNION-based injection |

**Expected Result (Kết quả mong đợi):**
- ✔ Hệ thống **KHÔNG** cho phép đăng nhập với bất kỳ payload nào trên
- ✔ Hiển thị thông báo lỗi thông thường: *"Email hoặc mật khẩu không chính xác"*
- ✔ **KHÔNG** hiển thị thông báo lỗi SQL (VD: `SQL syntax error near...`)
- ✔ **KHÔNG** có dữ liệu hệ thống bị lộ ra trong response
- ✔ Database không bị thay đổi (kiểm tra sau khi test scenario `d`)
- ✔ Server trả về HTTP 401 hoặc 400, không phải 500
- ✔ Hành vi injection được ghi log lại trong hệ thống (security log)

**Actual Result:** _(Điền sau khi thực thi)_

**Notes:**
> Sử dụng **Prepared Statements / Parameterized Queries** ở backend là biện pháp phòng chống chính. Test case này xác nhận biện pháp đó hoạt động đúng.

---

### TC-LOGIN-007 — Chức năng hiện/ẩn mật khẩu

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-007 |
| **Title** | Toggle hiện/ẩn mật khẩu hoạt động đúng |
| **Module** | Login - UI/UX |
| **Priority** | 🟡 Low |
| **Type** | Functional - UI |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Trường Password có icon con mắt (show/hide toggle)

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập mật khẩu vào trường "Password" | `Test@1234` |
| 3 | Quan sát trạng thái mặc định của trường Password | — |
| 4 | Nhấn icon **"con mắt"** (👁) bên cạnh trường Password | — |
| 5 | Quan sát trường Password thay đổi | — |
| 6 | Nhấn lại icon **"con mắt"** lần nữa | — |
| 7 | Quan sát trường Password lần 2 | — |

**Expected Result (Kết quả mong đợi):**

| Bước | Expected |
|------|----------|
| Sau bước 3 | Password hiển thị dạng `••••••••` (masked) |
| Sau bước 4 | Password hiển thị dạng plain text: `Test@1234`, icon đổi thành 👁‍🗨 |
| Sau bước 6 | Password trở lại dạng `••••••••`, icon trở về 👁 |

- ✔ Nội dung password không bị thay đổi sau khi toggle
- ✔ Cursor vẫn ở vị trí cuối chuỗi
- ✔ Toggle hoạt động mượt mà, không delay

**Actual Result:** _(Điền sau khi thực thi)_

---

### TC-LOGIN-008 — Đăng nhập với tài khoản bị khóa

| Trường | Nội dung |
|--------|----------|
| **Test Case ID** | TC-LOGIN-008 |
| **Title** | Hiển thị thông báo phù hợp khi tài khoản bị khóa/vô hiệu hóa |
| **Module** | Login - Authentication |
| **Priority** | 🔴 High |
| **Type** | Functional - Negative |
| **Status** | ⏳ PENDING |

**Precondition (Điều kiện tiên quyết):**
- Ứng dụng đang hiển thị màn hình Login
- Tài khoản `locked.user@example.com` đã bị khóa bởi Admin trong hệ thống
- Kết nối internet ổn định

**Test Steps (Các bước thực hiện):**

| # | Bước thực hiện | Test Data |
|---|----------------|-----------|
| 1 | Mở màn hình Đăng nhập | — |
| 2 | Nhập email của tài khoản bị khóa | `locked.user@example.com` |
| 3 | Nhập mật khẩu đúng của tài khoản | `CorrectPass@123` |
| 4 | Nhấn nút **"Đăng nhập"** | — |
| 5 | Quan sát thông báo phản hồi | — |

**Expected Result (Kết quả mong đợi):**
- ✔ Hệ thống từ chối đăng nhập
- ✔ Hiển thị thông báo rõ ràng: *"Tài khoản của bạn đã bị khóa. Vui lòng liên hệ hỗ trợ."*
- ✔ Thông báo **khác biệt** so với thông báo sai mật khẩu thông thường
- ✔ Người dùng vẫn ở màn hình Login
- ✔ Có thể cung cấp link hoặc thông tin liên hệ hỗ trợ
- ✔ Server trả về HTTP 403 (Forbidden)

**Actual Result:** _(Điền sau khi thực thi)_

**Notes:** Quan trọng về mặt UX — người dùng cần biết lý do cụ thể tại sao không đăng nhập được.

---

## 📊 Tổng kết Test Cases

| Test Case ID | Tiêu đề | Priority | Type | Status |
|-------------|---------|----------|------|--------|
| TC-LOGIN-001 | Đăng nhập thành công (Happy Path) | 🔴 High | Positive | ⏳ PENDING |
| TC-LOGIN-002 | Email không đúng định dạng | 🟠 Medium | Negative | ⏳ PENDING |
| TC-LOGIN-003 | Password không chính xác | 🔴 High | Negative | ⏳ PENDING |
| TC-LOGIN-004 | Các trường để trống | 🟠 Medium | Negative | ⏳ PENDING |
| TC-LOGIN-005 | Ký tự đặc biệt trong input | 🟡 Medium | Boundary | ⏳ PENDING |
| TC-LOGIN-006 | SQL Injection cơ bản | 🔴 High | Security | ⏳ PENDING |
| TC-LOGIN-007 | Toggle hiện/ẩn mật khẩu | 🟡 Low | UI/UX | ⏳ PENDING |
| TC-LOGIN-008 | Tài khoản bị khóa | 🔴 High | Negative | ⏳ PENDING |

---

## 📌 Ghi chú chung

> **Môi trường test:** Development / Staging — KHÔNG chạy Security test cases trên Production
>
> **Công cụ đề xuất:** Postman (API testing), Browser DevTools (network), OWASP ZAP (security scanning)
>
> **Reviewer:** Lead QA phải review trước khi chạy TC-LOGIN-006
>
> **Tần suất chạy:** Regression suite nên chạy TC-001, 002, 003, 004 sau mỗi build mới