NỘI DUNG BÀI HỌC
✅ Nắm được lý do – mục đích – trường hợp thực tế cần xử lý:
-
- Tab mới mở từ thao tác click.
- Iframe chứa nội dung nhúng.
- Local storage lưu token/session/setting phía client.
✅ Xây dựng BasePage hỗ trợ tính năng nâng cao (multi-tab).
✅ Xây dựng Page Object có khả năng:
-
-
Mở tab mới
-
Trả về PO của tab mới
-
Xử lý iFrame (nếu có)
-
Tương tác với LocalStorage
-
✅ Hoàn thiện kịch bản E2E thực tế dựa trên hệ thống HRM.
1️⃣ KIẾN TRÚC TRÌNH DUYỆT TRONG PLAYWRIGHT
Trước khi học multi-tab, iFrame hay storage, cần hiểu mô hình trình duyệt trong Playwright:
Tại sao phải hiểu cấu trúc này?
-
Để biết tại sao click vào link lại mở Page mới, gọi là tab.
-
Để biết tại sao không thể locate được element trong iframe.
-
Để biết tại sao dữ liệu vẫn giữ lại sau khi reload (vì nó nằm trong storage).
2️⃣ MULTI-TABS (XỬ LÝ TAB MỚI)
⭐ 2.1. Lý do cần học Multi-tab?
Một số website mở tab mới khi:
-
Click vào “Help”, “Detail”, “Policy”, “Settings…”
-
Click vào liên kết có
target="_blank" -
Click vào script mở popup bằng
window.open()
Trên HRM, trang Settings hoặc Help thường được thiết kế theo mô hình này (nếu thực tế không mở tab → giáo án mô phỏng tình huống thực tế cho automation cấp cao).
Nếu không xử lý đúng, test sẽ:
❌ Bị kẹt ở tab cũ
❌ Không biết tab mới đã xuất hiện
❌ Không điều khiển được tab mới → locator fail
⭐ 2.2. Nguyên tắc xử lý Multi-Tab
Playwright cung cấp sự kiện:
Quy tắc vàng: Lắng nghe trước → Click để mở tab → Nhận đối tượng Page mới.
Nếu click xong mới expect → sẽ miss event vì tab đã mở trước khi Playwright lắng nghe.
⭐ 2.3. BasePage hỗ trợ mở tab mới
📌 core/base_page.py
⭐ 2.4. Dashboard PO trả về Settings PO (tab mới)
📌 pages/dashboard_page.py
⭐ 2.5. SettingsPage (tab mới)
📌 pages/settings_page.py
⭐ 2.6. Test case Multi-tab hoàn chỉnh
📌 tests/test_multi_tab_hrm.py
3️⃣ iFRAME
⭐ 3.1. Lý do phải học iFrame?
iFrame xuất hiện trong:
-
Form embed
-
Captcha
-
Chat widget
-
Video nhúng
-
Dashboard của HRM hoặc phần báo cáo (tùy phiên bản)
Đặc biệt, khi inspect thấy <iframe> → mọi element bên trong KHÔNG thuộc page hiện tại.
Vì vậy:
-
page.locator()KHÔNG tìm được element -
Cần truy cập qua
Frameobject
⭐ 3.2. Cách truy cập iFrame
Lấy tất cả frame:
Lấy bằng name / url / index:
Click element trong iFrame:
frame.locator("#submit").click()
⭐ 3.3. Ứng dụng trực tiếp trên HRM (có hoặc mô phỏng)
Một số trang HRM nội bộ có phần biểu đồ/báo cáo hiển thị qua iframe.
Nếu trang không có sẵn iframe → phần này vẫn là nền tảng bắt buộc
vì học Playwright cấp cao luôn phải xử lý iframe khi gặp.
Ví dụ minh họa:
dashboard_page.page.goto("https://www.w3schools.com/html/html_iframe.asp")
frame = dashboard_page.page.frame(name="iframeResult")
frame.locator("a:has-text('HTML Tutorial')").click()
4️⃣ LOCAL STORAGE
⭐ 4.1. Lý do cần học Local Storage?
Website hiện đại lưu rất nhiều dữ liệu trên client:
-
Token đăng nhập
-
Trạng thái toggle
-
Màu theme
-
Dữ liệu session
-
Ngôn ngữ đã chọn
Trên HRM, sau khi login, localStorage chứa dữ liệu version, theme, user info (tùy bản).
Tác dụng trong automation:
-
Có thể đọc token
-
Có thể lưu/restore state
-
Có thể kiểm tra UI theo trạng thái người dùng
-
Có thể reset hoặc chỉnh data phục vụ test
⭐ 4.2. Đọc Local Storage trong Playwright
local_data = page.evaluate("() => Object.entries(localStorage)")
print(local_data)
⭐ 4.3. Ghi Local Storage
page.evaluate("() => localStorage.setItem('theme', 'dark')")
⭐ 4.4. Xóa Local Storage
⭐ 4.5. Ứng dụng trực tiếp với HRM
Sau khi login HRM:
📌 tests/test_local_storage.py
def test_local_storage_after_login(dashboard_page):
entries = dashboard_page.page.evaluate("() => Object.entries(localStorage)")
print("LocalStorage:", entries)
assert len(entries) > 0
5️⃣ FIXTURES DÙNG CHUNG (LOGIN SẴN)
📌 conftest.py
6️⃣ KỊCH BẢN TỔNG HỢP CUỐI BUỔI
-
Đăng nhập vào HRM qua fixture.
-
Truy cập Dashboard.
-
Mở tab Settings → thao tác → đóng tab.
-
Đọc localStorage để xem dữ liệu lưu lại.
-
Truy cập iFrame demo (nếu HRM không có iframe).
-
Quay lại Dashboard và xác nhận vẫn còn trong session.
7️⃣ TÓM TẮT KIẾN THỨC CỐT LÕI
| Mảng | Cần hiểu | Công cụ | Ý nghĩa |
|---|---|---|---|
| Multi-Tab | Vì sao tab mới mở ra? | context.expect_page() |
Điều khiển được tab mới |
| iFrame | Element nằm trong frame con | page.frame() |
Tránh lỗi “locator not found” |
| LocalStorage | Dữ liệu client-side | page.evaluate() |
Kiểm soát token/theme/session |
| POM | Mỗi trang = 1 class | BasePage / Page Objects | Code rõ ràng, dễ bảo trì |
| Fixtures | Chuẩn bị state | pytest fixtures | Login 1 lần dùng nhiều nơi |
