互動操作與斷言
有了 Locator 之後,接下來就是用它模擬使用者操作(Actions),並用斷言(Assertions)確認畫面結果符合預期。
常用操作方法
await page.getByRole('textbox', { name: '帳號' }).fill('demo@vcdemy.com');
await page.getByRole('textbox', { name: '密碼' }).fill('password123');
await page.getByRole('button', { name: '登入' }).click();
await page.getByLabel('訂閱電子報').check(); // 勾選 checkbox
await page.getByLabel('國家').selectOption('TW'); // 下拉選單
await page.getByRole('textbox').press('Enter'); // 鍵盤事件
await page.getByText('拖曳我').dragTo(page.getByText('目標區'));
每個操作方法在執行前,Playwright 都會先確認元素「可操作」(見 自動等待與重試機制),例如已顯示在畫面上、沒有被其他元素遮蓋、不是 disabled 狀態,才會真正觸發動作,這是 Playwright 比傳統工具更少出現「點擊失敗」的原因之一。
Web-First Assertions
Playwright 的 expect() 提供一組會自動重試的斷言,直到條件成立或逾時(預設 5 秒)才判定失敗,這稱為 Web-First Assertions:
await expect(page.getByText('訂單成立')).toBeVisible();
await expect(page.getByRole('button', { name: '送出' })).toBeDisabled();
await expect(page.getByRole('textbox')).toHaveValue('demo@vcdemy.com');
await expect(page).toHaveURL(/\/dashboard/);
await expect(page).toHaveTitle('儀表板');
await expect(page.locator('.cart-count')).toHaveText('3');
這與一般程式語言的 assert 不同:一般 assert 立刻檢查當下狀態,畫面若還在非同步更新中就會誤判失敗;Web-First Assertions 會持續重試,直到畫面穩定下來才下結論,因此不需要額外手動加 sleep 或等待。
常見錯誤:斷言忘記加 await
// ❌ 錯誤:沒有 await,斷言還沒執行完程式就往下跑,可能誤判測試通過
expect(page.getByText('成功')).toBeVisible();
// ✅ 正確
await expect(page.getByText('成功')).toBeVisible();
expect() 回傳的是 Promise,一定要加上 await,否則重試機制不會生效,測試可能得到錯誤的通過結果。
一般值的斷言
除了畫面狀態,也能驗證一般 JavaScript 值(此時不會自動重試,因為值已經確定):
const total = await page.getByTestId('total').textContent();
expect(Number(total)).toBe(100);
expect([1, 2, 3]).toContain(2);
下一步
想了解「自動重試」背後真正的運作原理,請看 自動等待與重試機制。