$npx -y skills add anhtester/codex-testing-kit --skill ui-debug-agentSkill inspect web/mobile applications bằng browser tools, phân tích DOM elements, xác định locators ổn định, debug UI automation failures, và hỗ trợ sinh Page Object classes.
| 1 | # UI Debug Agent |
| 2 | |
| 3 | ## Description |
| 4 | |
| 5 | Skill chuyên biệt giúp agent inspect ứng dụng web/mobile trực tiếp trên browser thật, phân tích DOM, thu thập locators ổn định, và debug các vấn đề UI automation. |
| 6 | |
| 7 | Agent có thể: |
| 8 | |
| 9 | - Mở browser thật, navigate đến bất kỳ URL nào |
| 10 | - Inspect DOM elements — xác định attributes, hierarchy, state |
| 11 | - Thu thập locators ổn định cho Playwright, Selenium, Appium |
| 12 | - Debug automation failures (element not found, click intercepted, timeout) |
| 13 | - Capture UI state (snapshot, screenshot) để phân tích |
| 14 | - Phân tích dynamic content, iframe, shadow DOM, SPA navigation |
| 15 | |
| 16 | --- |
| 17 | |
| 18 | ## When to Use |
| 19 | |
| 20 | Sử dụng skill này khi: |
| 21 | |
| 22 | - Cần **khám phá UI** của một trang web/module mới |
| 23 | - Cần **tìm locator** cho element cụ thể |
| 24 | - Cần **debug** test automation fail do UI thay đổi |
| 25 | - Cần **verify** locator có hoạt động trên DOM thực tế không |
| 26 | - Cần **phân tích DOM** để hiểu cấu trúc UI (forms, tables, modals) |
| 27 | - Cần **capture evidence** (screenshot) cho test report |
| 28 | |
| 29 | Trigger keywords: "inspect UI", "tìm locator", "debug element", "mở browser xem", "kiểm tra DOM" |
| 30 | |
| 31 | --- |
| 32 | |
| 33 | ## MCP Command Sequence (BẮT BUỘC) |
| 34 | |
| 35 | Khi sử dụng Playwright MCP để debug UI, **LUÔN** tuân theo thứ tự: |
| 36 | |
| 37 | ``` |
| 38 | 1. browser_navigate(url) → Mở trang |
| 39 | 2. browser_resize(1920, 1080) → Desktop viewport |
| 40 | 3. browser_wait_for(text/time) → Chờ page load |
| 41 | 4. browser_snapshot() → Thu thập DOM (dùng để phân tích + tìm locator) |
| 42 | 5. browser_click/type/hover(ref) → Tương tác (nếu cần) |
| 43 | 6. browser_take_screenshot() → Chụp ảnh (evidence khi fail hoặc milestone) |
| 44 | ``` |
| 45 | |
| 46 | ### Quy tắc quan trọng: |
| 47 | |
| 48 | | Quy tắc | Chi tiết | |
| 49 | |---|---| |
| 50 | | **KHÔNG navigate lại** nếu đã ở đúng trang | Tránh reload ngoài ý muốn | |
| 51 | | **LUÔN resize** ngay sau navigate | `browser_resize(1920, 1080)` — đảm bảo desktop viewport | |
| 52 | | **LUÔN wait** trước khi snapshot | Chờ page load hoàn tất | |
| 53 | | **Dùng snapshot để phân tích** | Snapshot trả về accessibility tree — nhanh, chính xác, có `ref` để tương tác | |
| 54 | | **Dùng screenshot để báo cáo** | Screenshot là hình ảnh — dùng khi cần evidence visual | |
| 55 | |
| 56 | --- |
| 57 | |
| 58 | ## Snapshot vs Screenshot |
| 59 | |
| 60 | | | `browser_snapshot` | `browser_take_screenshot` | |
| 61 | |---|---|---| |
| 62 | | **Trả về** | Accessibility tree (text + ref IDs) | Hình ảnh (PNG/JPEG) | |
| 63 | | **Mục đích** | Phân tích DOM, tìm locator, xác định element | Visual evidence, báo cáo, debug layout | |
| 64 | | **Khi nào dùng** | ⭐ Luôn dùng trước khi tương tác | Chỉ khi fail hoặc milestone quan trọng | |
| 65 | | **Có ref để interact** | ✅ Có — dùng ref để click/type/hover | ❌ Không — chỉ là hình ảnh | |
| 66 | | **Tốc độ** | Nhanh | Chậm hơn | |
| 67 | |
| 68 | **Quy tắc:** Ưu tiên `snapshot` cho phân tích, dùng `screenshot` cho evidence. |
| 69 | |
| 70 | --- |
| 71 | |
| 72 | ## Quy trình Inspect UI |
| 73 | |
| 74 | ### 1. Mở & Chuẩn bị trang |
| 75 | |
| 76 | ``` |
| 77 | browser_navigate → URL target |
| 78 | browser_resize → 1920 × 1080 |
| 79 | browser_wait_for → chờ indicator page đã load (text hoặc thời gian) |
| 80 | ``` |
| 81 | |
| 82 | Nếu trang yêu cầu đăng nhập: |
| 83 | - Hỏi user credentials HOẶC dùng fixture sẵn có trong project |
| 84 | - **KHÔNG đọc file `.env` trực tiếp** (quy tắc bảo mật) |
| 85 | |
| 86 | ### 2. Thu thập DOM Structure |
| 87 | |
| 88 | ``` |
| 89 | browser_snapshot → accessibility tree |
| 90 | ``` |
| 91 | |
| 92 | Từ snapshot, xác định: |
| 93 | - **Các element chính:** buttons, inputs, links, headings, tables |
| 94 | - **Attributes quan trọng:** role, name, label, placeholder, testid |
| 95 | - **Hierarchy:** parent → child relationships |
| 96 | - **State:** visible, enabled, disabled, checked, expanded |
| 97 | |
| 98 | ### 3. Xác định Locators |
| 99 | |
| 100 | Với mỗi element cần locator, áp dụng **priority order** theo framework: |
| 101 | |
| 102 | **Playwright:** |
| 103 | |
| 104 | | Priority | Locator | Ví dụ | Khi nào dùng | |
| 105 | |---|---|---|---| |
| 106 | | 1 ⭐ | `getByRole()` | `getByRole('button', {name: 'Submit'})` | Element có role + accessible name rõ ràng | |
| 107 | | 2 | `getByLabel()` | `getByLabel('Email')` | Form input có label | |
| 108 | | 3 | `getByPlaceholder()` | `getByPlaceholder('Enter email')` | Input có placeholder, không có label | |
| 109 | | 4 | `getByText()` | `getByText('Welcome back')` | Text content unique | |
| 110 | | 5 | `getByTestId()` | `getByTestId('submit-btn')` | Element có data-testid attribute | |
| 111 | | 6 | CSS | `page.locator('.submit-button')` | Không có semantic option nào phù hợp | |
| 112 | | 7 | XPath | `page.locator('//div[@class="x"]')` | Last resort — tránh dùng | |
| 113 | |
| 114 | **Selenium:** |
| 115 | |
| 116 | | Priority | Locator | Ví dụ | |
| 117 | |---|---|---| |
| 118 | | 1 ⭐ | `By.id()` | `By.id("email")` | |
| 119 | | 2 | `By.cssSelector("[data-testid]")` | `By.cssSelector("[data-testid='submit']")` | |
| 120 | | 3 | `By.name()` | `By.name("username")` | |
| 121 | | 4 | `By.cssSelector()` | `By.cssSelector(".login-form button")` | |
| 122 | | 5 | `By.xpath()` | `By.xpath("//button[text()='Login']")` | |
| 123 | |
| 124 | **Appium (Mobile):** |
| 125 | |
| 126 | | Priority | Locator | Ví dụ | |
| 127 | |---|---|---| |
| 128 | | 1 ⭐ | Accessibility ID | `MobileBy.accessibilityId("loginButton")` | |
| 129 | | 2 | ID (resource-id) | `MobileBy.id("com.app:id/login_btn")` | |
| 130 | | 3 | Name | `MobileBy.name("Login")` | |
| 131 | | 4 | XPath (relative) | `MobileBy.xpath("//android.widget.Button[@text='Login' |