Wiki

← Tất cả bài wiki

page.pause() & page.on('console') (Debug nhanh và bắt log trình duyệt)

automationplaywright

page.pause() là 'breakpoint mềm' dừng test và mở Inspector ngay tại dòng đó; page.on('console') / page.on('pageerror') lắng nghe mọi log và lỗi JS mà trang phát ra — bộ đôi giúp bắt lỗi frontend mà assertion UI không thấy được.

Khái niệm & Bản chất

  • page.pause() tạm dừng thực thi và mở Playwright Inspector tại đúng điểm đó — debug giữa chừng mà không cần PWDEBUG chạy lại từ đầu.
  • page.on('console') bắt mọi console.log/warn/error của trang trong browser — khác hẳn console của Node process đang chạy test.
  • page.on('pageerror') bắt uncaught exception trên trang — lỗi JS làm tính năng chết âm thầm mà UI test vẫn có thể xanh.
  • Đây là cặp debug 'nhanh và bẩn': chèn vài dòng là thấy ngay trang đang nói gì, đang lỗi gì — không cần setup phức tạp.

Cách hoạt động & API chính

  • await page.pause() — dừng tại dòng, điều khiển tiếp bằng Inspector (Resume / Step Over / Pick Locator).
  • page.on('console', msg => ...): msg.type() trả 'log' | 'error' | 'warning' | 'info'..., msg.text() lấy nội dung, msg.location() biết log bắn từ file/dòng nào.
  • page.on('pageerror', err => ...): err là Error thật của trang, có message và stack đầy đủ.
  • Họ event liên quan: page.on('requestfailed') bắt request hỏng, page.on('response') soi mọi response — kết hợp là thấy cả lỗi JS lẫn lỗi API.
  • Listener phải gắn trước hành động gây ra log (đặc biệt trước goto) — log bắn trong lúc load trang sẽ bị lỡ nếu gắn sau.

Ví dụ & Cú pháp thực tế

  • Forward console trang ra terminal, chỉ lọc lỗi: ``ts test('soi lỗi trang', async ({ page }) => { // Gắn TRƯỚC goto để không lỡ log lúc load page.on('console', msg => { if (msg.type() === 'error') { console.log('[PAGE CONSOLE]', msg.text()); } }); page.on('pageerror', err => console.log('[UNCAUGHT]', err.message)); await page.goto('/cart'); await page.pause(); // dừng soi DOM/locator tại đây await page.getByRole('button', { name: 'Thanh toán' }).click(); }); ``
  • Pattern kinh điển: assert 'trang không có JS error': ``ts test('trang chủ không có lỗi JS', async ({ page }) => { const errors: string[] = []; page.on('pageerror', err => errors.push(err.message)); await page.goto('/'); await page.getByRole('link', { name: 'Khoá học' }).click(); // App bắn uncaught error → test fail, kèm message expect(errors, Trang có JS error: ${errors.join(' | ')}).toEqual([]); }); ``
  • Bắt cả lỗi API trong cùng một test: ``ts test('checkout không lỗi API', async ({ page }) => { const badResponses: string[] = []; page.on('response', res => { if (res.status() >= 500) badResponses.push(${res.status()} ${res.url()}); }); await page.goto('/checkout'); // ... thao tác expect(badResponses).toEqual([]); }); ``

Best practices & Khi nào dùng

  • Test fail do hành vi app lạ (không phải locator): forward console ra terminal trước — phần lớn sẽ thấy ngay API lỗi hoặc JS exception giấu kín.
  • Dùng pattern 'collect pageerror rồi expect(errors).toEqual([])' làm smoke check cho trang quan trọng — bắt lỗi mà UI assertion bỏ sót.
  • Đặt page.pause() ngay trước action nghi ngờ — đỡ phải PWDEBUG rồi step từ đầu test.
  • Listener lặp lại ở nhiều test → gom vào fixture/helper dùng chung (vd autoFixtures gắn pageerror collector cho mọi test).

Gotchas, So sánh & Lưu ý

  • page.pause() trên CI/headless là no-op — không treo pipeline, nhưng vẫn nên xoá sau khi debug xong để code sạch.
  • pageerror chỉ bắt uncaught error — lỗi đã bị app try/catch (vd API fail đã xử lý) không hiện; phối hợp thêm console error hoặc response listener.
  • Forward toàn bộ console không lọc → output cực rối; nên chỉ lấy type === 'error' hoặc gom vào mảng rồi assert cuối test.
  • Khác mở DevTools bằng tay: listener bắt được log ngay cả khi headless và assert tự động trên log — đây là lợi thế automation so với debug tay.
  • Đừng biến 'assert không có console error' thành rule cứng cho mọi trang — nhiều app có warning/error vô hại từ third-party, cần whitelist hợp lý.