# Báo cáo kiểm thử — Luyện kỹ năng (R5)

> Prototype tĩnh, dữ liệu minh họa. Kiểm thử bằng script trong Chromium của ứng dụng (iframe cùng gốc, đổi độ rộng, `?lang=`) và bằng phím thật cho vài thao tác. **Chưa kiểm trên thiết bị thật, chưa dùng trình đọc màn hình, chưa kiểm Safari/Firefox.** Không tự đánh dấu là đã duyệt.

## 1. Ma trận đã chạy (kiểm tự động: tràn ngang trang, phần tử vượt mép, chữ bị cắt, tương phản chữ ≥4.5:1 tính từ màu thực, khóa dịch hiện thô, tham số chưa thay)
| Phạm vi | Chi tiết | Kết quả |
|---|---|---|
| `skill-library.html` | 5 ngôn ngữ × 375px và 1024px × 7 chế độ xem (hub, TOPIK I, TOPIK II, Nghe I, Đọc II, Viết II, Nghe II mức “Thử thách”) × dữ liệu bình thường/đang tải/chưa có bài tập/lỗi (ba trạng thái sau chỉ ở trang kỹ năng) × người dùng có lịch sử | 0 lỗi (vi, th ở cả hai độ rộng; en, ko, zh-Hans cũng 0 lỗi) |
| `skill-practice.html` | 5 ngôn ngữ × 375/1024px × 3 bộ (Nghe, Đọc có nhóm đề chung, Viết) × lời giải đã duyệt/thiếu; **mọi câu**: trước khi trả lời, sau khi trả lời, sau khi xem đáp án | 0 lỗi; thêm 768px (vi): 0 lỗi |
| Homepage | 5 ngôn ngữ × 375/1024px sau khi sửa điều hướng và thẻ Luyện kỹ năng | 0 lỗi |
| Hồi quy | Trang danh mục thư viện (TOPIK II từ kỳ 35), Kết quả, Xem lại: vi, th × 375/1024px | 0 lỗi |
| Header 961 / 1000 / 1100px | Skill library, Homepage, Thư viện đề × 5 ngôn ngữ (hai mục có mega menu: “Thư viện đề” và “Luyện kỹ năng”) | Một hàng cao 64px, không tràn, mọi mục cùng hàng |
| Mobile 375px | Menu: accordion “Luyện kỹ năng” tự mở trên trang thuộc mục này, “Thư viện đề” đóng; mục hiện tại có `aria-current` | Đạt, không tràn ngang |
Bộ kiểm tra từng được kiểm chứng ở vòng R4 bằng cách chèn lỗi giả (tràn 600px, tương phản 2.2:1) và bắt được cả hai.

## 2. Hành vi đã xác nhận
- **Không lộ lời giải trước thời điểm:** trước khi bấm “Xem đáp án”, DOM của câu không có khối lời giải/đáp án/bản dịch/lời thoại, thẻ tóm tắt, hay nhãn “Đáp án đúng” (kiểm ở mọi câu × 5 ngôn ngữ × 2 độ rộng × 3 bộ). Nút “Xem đáp án” bị vô hiệu cho tới khi đã chọn đáp án (hoặc đã có chữ ở câu Viết). Lưu ý giới hạn: ở prototype, khóa đáp án vẫn nằm trong JavaScript của trang (production phải trả sau khi xem đáp án).
- **Không render nháp AI:** dữ liệu mẫu có một lời giải nháp (Nghe, câu 3); chuỗi đó không xuất hiện trong DOM ở trước hay sau khi xem đáp án, mọi tổ hợp đã quét. Câu đó hiện ô “chưa có lời giải đã được duyệt”.
- **Chuyển câu không mất bài làm / trạng thái đã xem đáp án được giữ:** chọn đáp án → Câu sau → Câu trước: lựa chọn còn; xem đáp án → chuyển đi và quay lại: vẫn khóa, chip “Đã xem đáp án”, ô điều hướng giữ kiểu “đã xem”; câu Viết giữ nguyên văn bản và trạng thái đã xem. Sau khi duyệt hết các câu và xem đáp án từng câu, số ô “đã xem” bằng số câu.
- **Bàn phím (phím thật):** mũi tên chuyển lựa chọn trong nhóm radio (focus giữ đúng ô sau mỗi lần vẽ lại), Tab tới “Xem đáp án”, Enter hiện đáp án và đưa focus vào khối kết quả; chuyển câu đưa focus về tiêu đề câu và thông báo `aria-live`; focus nhìn thấy (viền xanh 3px) ở nút, ô chọn, vùng nhập. Chưa đi hết thứ tự Tab của cả trang.
- **Không nhầm với Exam Taking:** không có đồng hồ, không nút “Nộp bài”, không hộp thoại nộp, không khóa ngôn ngữ; có huy hiệu “Luyện kỹ năng”, ô giải thích “không phải thi thử” và dùng header website (có bộ chuyển ngôn ngữ). Câu trước/Câu sau và ô điều hướng dùng cùng ngôn ngữ thiết kế nhưng trạng thái khác (đã xem đáp án).
- **SEO mô phỏng (kiểm trên head):** hub và trang kỹ năng có dữ liệu: `index,follow`, canonical sạch, 5 hreflang + `x-default`; trang kỹ năng không có dữ liệu hoặc có bộ lọc: `noindex,follow`; trang phiên luyện tập: `noindex,nofollow`, không canonical/hreflang.
- **Ngôn ngữ:** đổi ngôn ngữ trong trang giữ nguyên câu, bài làm và trạng thái; nội dung đề giữ tiếng Hàn (`lang="ko"`); khi lời giải/bản dịch chưa có theo ngôn ngữ giao diện, hiện ô giữ chỗ nêu ngôn ngữ đã có và nút để người dùng chủ động xem (kiểm tiếng Hàn: có vi, en).
- `exam-taking.html` không đổi (md5 `cb434bc65c2a65b92c84dde4fb5de09c`). `exam-results.html`, `answer-review.html`, `results.js/css`, `library.*`, `catalog.js`, `tokens.css`, `site.css` không đổi. **`site.js` đã sửa** (menu Luyện kỹ năng, nhãn, footer) và `homepage.html` sửa tối thiểu.

## 3. Phát hiện / giới hạn
1. **Trạng thái 2 của Kết quả (R4) mâu thuẫn quyết định review mới:** prototype R4 hiển thị điểm Nghe/Đọc khi Viết chưa chấm; quyết định mới là *không mặc định công bố điểm riêng*. Chưa sửa vì ngoài phạm vi R5 (chỉ ghi nhận). Cần sửa ở vòng sau.
2. **Giấy 원고지 cho Viết:** phiên luyện viết dùng ô nhập văn bản thường (`<textarea>`) và đếm ký tự theo quy tắc Exam Taking, không dùng lưới 원고지; chưa quyết định có dùng lưới trong luyện tập không.
3. **Âm thanh, hình ảnh:** không có tệp thật; khung giữ chỗ nét đứt ghi rõ.
4. **Ghim đề dùng chung trên mobile:** chiếm tối đa 24% chiều cao màn hình, có nút Thu gọn; khi cuộn, khung che đầu thẻ câu (đúng bản chất ghim). Cần xem trên thiết bị thật.
5. **Tiến độ không được lưu** khi rời trang hoặc tải lại (prototype); lưu/tiếp tục/làm lại là quyết định mở.
6. **320px:** header dùng chung tràn ~18–25px (có sẵn từ R3/R4, không sửa); 375px đạt.
7. Chỉ Chromium; chưa kiểm bàn phím trên Safari; chưa kiểm cỡ chữ hệ thống lớn; chưa đo tương phản viền/biểu tượng; bản dịch UI (~150 chuỗi mới × 5 ngôn ngữ) và nội dung tiếng Hàn minh họa chưa có người bản ngữ duyệt.
8. Tất cả bộ, số câu, mức, trạng thái là dữ liệu minh họa; không giả định số bộ, số câu hay thời lượng thật.

## 4. Ảnh chụp (`screenshots-skills/`)
L1–L7: Skill library (hub, cấp, kỹ năng có lịch sử en, chưa có bài tập, lỗi, đang tải, submenu zh) · P1–P5: Practice (chưa xem đáp án, đã xem kèm lời giải + bản dịch, Viết, ô giữ chỗ ngôn ngữ ko, thiếu lời giải đã duyệt) · M1–M3: mobile 375 (th, accordion ko, practice) · H1: thẻ Luyện kỹ năng trên Homepage. Ảnh từ khung xem trước (độ phân giải thấp, đôi khi bị co).

> **Cập nhật R6:** thêm lớp “cấp độ mục tiêu” tách khỏi “độ khó bộ”; khóa câu trả lời sau khi xem đáp án nay là quyết định đã khóa; mục phát hiện số 1 (trạng thái 2 của Kết quả) đã được sửa. Xem `TEST-REPORT-DASHBOARD.md`.
