# CẤP ĐỘ 1.5 — Codegen: Nhìn Thao Tác Của Bạn Biến Thành Code

> **Điều kiện:** Đã hoàn thành Cấp độ 1 (chạy được test có sẵn, đọc được kết quả pass/fail).
> **Mục tiêu của cấp độ này:** Dùng **Codegen** — công cụ ghi lại thao tác chuột/bàn phím và tự sinh code — để **hiểu rằng mỗi click, mỗi lần gõ phím đều được mô tả lại bằng 1 dòng code**. Bạn vẫn **chưa cần viết code**; nhiệm vụ là **quan sát và đọc hiểu**.
> Đây là cây cầu giữa Cấp độ 1 (xem máy chạy) và Cấp độ 2 (tự viết): sau cấp độ này, code Playwright không còn là "chữ tượng hình" nữa.

## ✅ Bạn hoàn thành Cấp độ 1.5 khi:

- [ ] Mở được Codegen bằng lệnh `npx playwright codegen`
- [ ] Thao tác login trên saucedemo và **chỉ ra được dòng code nào ứng với thao tác nào**
- [ ] Đọc 1 dòng code do Codegen sinh ra và nói được bằng lời: "dòng này làm gì"
- [ ] Dùng được nút **Pick locator** để xem "địa chỉ" của một phần tử bất kỳ
- [ ] Thêm được 1 **assertion** (kiểm tra) bằng thanh công cụ của Codegen
- [ ] Lưu code ghi được vào file `.spec.ts` và **chạy lại thành công** — máy lặp lại chính xác những gì bạn vừa làm
- [ ] Kể được ít nhất 2 lý do vì sao code Codegen chưa dùng ngay được cho dự án thật

Tick đủ → chuyển sang **Cấp độ 2**.

---

## Phần 0 — Codegen Là Gì, Và Vì Sao Học Nó Trước Khi Viết Code?

**Codegen** (code generator) là công cụ có sẵn của Playwright: nó mở một trình duyệt, bạn thao tác bình thường như người dùng thật, và **từng thao tác được "phiên dịch" ngay lập tức thành một dòng code** ở cửa sổ bên cạnh.

Vì sao học nó ở đây:

1. **Phá tan cảm giác sợ code.** Bạn sẽ thấy code test chỉ là *bản ghi chép lại thao tác* — click là `.click()`, gõ chữ là `.fill()`. Không có phép thuật nào cả.
2. **Học bằng mắt trước, bằng tay sau.** Ở Cấp độ 2 bạn sẽ tự viết những dòng này; sẽ dễ hơn rất nhiều nếu bạn đã *nhìn thấy chúng được sinh ra* hàng chục lần.
3. **Công cụ thật, dùng cả khi đi làm.** Tester chuyên nghiệp vẫn dùng Codegen để lên nháp nhanh hoặc tra selector.

> **Quy ước:** như Cấp độ 1 — dòng trong ô code màu xám bắt đầu bằng lệnh là để **gõ vào terminal**; các khối code TypeScript là để **đọc hiểu**, chưa cần gõ lại.

---

## Phần 1 — Mở Codegen Lần Đầu

Mở terminal trong VSCode (**Ctrl+`**) và gõ:

```bash
npx playwright codegen https://www.saucedemo.com
```

Hai cửa sổ xuất hiện:

| Cửa sổ | Vai trò |
| --- | --- |
| **Trình duyệt** (trang saucedemo) | Nơi bạn thao tác như người dùng bình thường |
| **Playwright Inspector** | Nơi code tự sinh ra, mỗi thao tác = 1 dòng, dòng mới nhất ở cuối |

Hãy sắp 2 cửa sổ **cạnh nhau** (trái - phải) để vừa thao tác vừa nhìn code sinh ra. Đây chính là cách học của cả cấp độ này.

> **Lỗi hay gặp:** gõ lệnh báo `command not found` hoặc không mở gì → bạn đang đứng sai thư mục project, hoặc chưa chạy `npm install` (quay lại Cấp độ 1, phần cài đặt).

---

## Phần 2 — Bài Thực Hành Chính: Ghi Lại Thao Tác Login

Làm **chậm rãi từng bước** — sau mỗi bước, dừng lại nhìn sang cửa sổ Inspector xem dòng code nào vừa xuất hiện.

### 2.1 Thao tác và đối chiếu

| # | Bạn làm gì (trình duyệt) | Code sinh ra (Inspector) | Đọc bằng lời |
| --- | --- | --- | --- |
| 1 | (Codegen tự mở trang) | `await page.goto('https://www.saucedemo.com/');` | "Mở trang saucedemo" |
| 2 | Click vào ô **Username** | `await page.locator('[data-test="username"]').click();` | "Tìm ô có địa chỉ `username`, click vào nó" |
| 3 | Gõ `standard_user` | `await page.locator('[data-test="username"]').fill('standard_user');` | "Điền chữ standard_user vào ô đó" |
| 4 | Click ô **Password**, gõ `secret_sauce` | `await page.locator('[data-test="password"]').fill('secret_sauce');` | "Điền mật khẩu" |
| 5 | Click nút **Login** | `await page.locator('[data-test="login-button"]').click();` | "Click nút Login" |

> Tuỳ phiên bản Playwright, code có thể hiện `page.getByTestId(...)` hoặc `page.getByPlaceholder(...)` thay cho `page.locator(...)` — **cùng một ý nghĩa**: "tìm phần tử theo địa chỉ rồi thao tác".

### 2.2 Nhận mặt 3 bộ phận của một dòng code

Mọi dòng Codegen sinh ra đều có cùng khung xương:

```
await  page.locator('[data-test="username"]')  .fill('standard_user');
─────  ──────────────────────────────────────  ───────────────────────
 (1)                  (2)                                (3)
```

| Bộ phận | Hiểu đơn giản là |
| --- | --- |
| (1) `await` | "Làm xong bước này rồi mới sang bước sau" — thao tác trên web cần thời gian, chữ này bắt máy chờ. Gần như dòng nào cũng có. |
| (2) `page.locator(...)` | "Tìm phần tử này trên trang" — phần trong ngoặc là **selector** (địa chỉ). |
| (3) `.click()` / `.fill('...')` | "Làm gì với phần tử đó" — click, điền chữ, nhấn phím... |

Chỉ cần nhận ra 3 bộ phận này là bạn đã **đọc được** 90% code test. (Cấp độ 2 sẽ giải thích kỹ `await` và biến.)

### 2.3 Tự kiểm tra

Không nhìn bảng trên, trả lời:

1. Dòng `await page.locator('[data-test="login-button"]').click();` làm gì?
2. Muốn máy điền chữ `abc` vào một ô, phần (3) sẽ là gì?
3. Trong dòng ở câu 1, đâu là selector?

<details>
<summary>Đáp án</summary>

1. Tìm nút có địa chỉ `login-button` rồi click vào nó.
2. `.fill('abc')`
3. `[data-test="login-button"]`

</details>

---

## Phần 3 — Thanh Công Cụ Của Inspector: Pick Locator & Assertion

Codegen không chỉ ghi thao tác — thanh công cụ phía trên trình duyệt có mấy nút rất đáng học:

### 3.1 Pick locator — tra "địa chỉ" của bất kỳ phần tử nào

1. Click nút **Pick locator** (biểu tượng ô ngắm) trên thanh công cụ
2. Di chuột trên trang — từng phần tử được highlight kèm địa chỉ của nó
3. Click vào phần tử → địa chỉ hiện ra ở ô phía dưới, copy được

Đây chính là việc bạn sẽ làm bằng F12 ở Cấp độ 2 — Codegen cho bạn cách "tra từ điển" nhanh hơn để làm quen trước.

### 3.2 Assert — ghi lại cả bước "kiểm tra"

Test không chỉ là thao tác — phải có bước **kiểm tra kết quả** (assertion). Codegen ghi được cả bước này:

1. Sau khi login thành công (đang ở trang Products), click nút **Assert visibility** (biểu tượng con mắt)
2. Click vào tiêu đề **Products** trên trang
3. Inspector sinh ra:

```typescript
await expect(page.locator('.title')).toBeVisible();
```

Đọc bằng lời: *"Kỳ vọng rằng phần tử tiêu đề phải đang hiển thị"* — nếu không hiển thị, test **fail**. Thử thêm:

- **Assert text** (biểu tượng chữ): click tiêu đề Products → sinh `await expect(...).toContainText('Products');`
- **Assert value**: kiểm tra giá trị trong ô input

> Đây là lần đầu bạn gặp `expect` — nhân vật chính của Cấp độ 2. Mọi test đều kết thúc bằng ít nhất 1 dòng `expect`: không có kiểm tra thì không gọi là test.

---

## Phần 4 — Vòng Lặp Trọn Vẹn: Ghi → Lưu → Chạy Lại

Giờ làm trọn một vòng: ghi thao tác, lưu thành file, và xem máy **lặp lại chính xác** những gì bạn vừa làm.

### 4.1 Ghi một lượt sạch

Đóng Codegen cũ (nếu đang mở), chạy lại từ đầu:

```bash
npx playwright codegen https://www.saucedemo.com
```

Thao tác lần lượt: điền username → điền password → click Login → **Assert visibility** vào tiêu đề Products.

### 4.2 Lưu vào file

1. Ở cửa sổ Inspector, bấm nút **Copy** (hoặc Ctrl+A rồi Ctrl+C trong khung code)
2. Trong VSCode, tạo file mới: `tests/demo/ghi-tu-codegen.spec.ts`
3. Dán code vào, lưu file (**Ctrl+S**)

Code dán vào sẽ có dạng đầy đủ như sau (Codegen tự sinh cả phần khung `import` và `test(...)`):

```typescript
import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
  await page.goto('https://www.saucedemo.com/');
  await page.locator('[data-test="username"]').fill('standard_user');
  await page.locator('[data-test="password"]').fill('secret_sauce');
  await page.locator('[data-test="login-button"]').click();
  await expect(page.locator('.title')).toBeVisible();
});
```

### 4.3 Chạy lại

```bash
npx playwright test tests/demo/ghi-tu-codegen.spec.ts --headed
```

Trình duyệt bật lên và **tự lặp lại từng thao tác bạn đã ghi** — điền chữ, click, kiểm tra — rồi báo `1 passed`.

> **Khoảnh khắc cần cảm nhận:** bạn vừa tạo ra một test tự động hoàn chỉnh **mà chưa viết một dòng code nào**. Và bạn đọc hiểu được từng dòng trong đó.

---

## Phần 5 — Bài Tập Tự Luyện

Tự làm 3 bài sau bằng Codegen (mỗi bài: ghi → đọc lại code → lưu file → chạy pass):

| Bài | Kịch bản ghi | Gợi ý assertion cuối |
| --- | --- | --- |
| 1 | Login **sai mật khẩu** (gõ bừa password) | Assert visibility vào thông báo lỗi đỏ |
| 2 | Login đúng → click **Add to cart** ở sản phẩm đầu tiên | Assert text vào biểu tượng giỏ hàng (số `1`) |
| 3 | Login đúng → click vào **tên một sản phẩm** | Assert visibility vào nút "Back to products" |

Sau mỗi bài, tự hỏi: *"Nếu che cửa sổ trình duyệt đi, chỉ đọc code — tôi có kể lại được mình đã làm gì không?"* Trả lời được là đạt.

---

## Phần 6 — Vì Sao Chưa Dừng Ở Đây? (Giới Hạn Của Codegen)

Nếu Codegen tiện thế, sao còn phải học viết code ở Cấp độ 2? Vì code ghi tự động có những giới hạn mà dự án thật không chấp nhận được:

| Giới hạn | Ví dụ |
| --- | --- |
| **Selector chưa tối ưu** | Có lúc sinh `.locator('div > div:nth-child(3) > button')` — vỡ ngay khi giao diện đổi. Người viết sẽ chọn `data-test` ổn định hơn. |
| **Không có logic** | Codegen không biết tạo dữ liệu unique (`Date.now()`), không biết lặp, không biết "nếu... thì..." |
| **Code lặp lại, khó bảo trì** | Ghi 7 case login = 7 lần ghi nguyên đoạn điền form. Người viết tách thành hàm dùng chung, sửa 1 chỗ là xong. |
| **Assertion nghèo** | Chỉ assert được cái đang nhìn thấy; các kiểm tra như "URL phải đổi", "phần tử phải BIẾN MẤT" phải tự viết. |
| **Không theo chuẩn dự án** | Dự án thật có quy ước đặt tên, `test.step`, fixture đăng nhập sẵn (Cấp độ 3) — Codegen không biết những thứ đó. |

**Vai trò đúng của Codegen từ giờ trở đi:** công cụ lên nháp và tra selector — không phải công cụ tạo test hoàn chỉnh.

---

## Tổng kết Cấp độ 1.5

Bạn đã nhìn thấy điều quan trọng nhất của automation: **code test = thao tác người dùng được ghi lại bằng chữ**, mỗi dòng có 3 bộ phận (chờ — tìm — làm), và test luôn kết thúc bằng `expect`. Quay lại checklist đầu tài liệu, tick đủ 7 ô.

**Tiếp theo:** mở tài liệu **Cấp độ 2 — Tự Viết Test Đầu Tiên**. Bạn sẽ học 6 khái niệm lập trình tối thiểu rồi tự tay viết lại — không cần Codegen — đúng những dòng code mà cấp độ này bạn mới chỉ đọc.

---

_Phiên bản 1.0 — cấp độ trung gian bổ sung giữa Cấp độ 1 và 2, tập trung Codegen và đọc hiểu code._
