從 Protractor 遷移
遷移原則
- 無需 "webdriver-manager" / Selenium。
- Protractor 的 ElementFinder ⇄ Playwright Test 定位器
- Protractor 的
waitForAngular
⇄ Playwright Test 自動等待 - 別忘了在 Playwright Test 中使用 await
速查表
Protractor | Playwright Test |
---|---|
element(by.buttonText('...')) | page.locator('button, input[type="button"], input[type="submit"] >> text="..."') |
element(by.css('...')) | page.locator('...') |
element(by.cssContainingText('..1..', '..2..')) | page.locator('..1.. >> text=..2..') |
element(by.id('...')) | page.locator('#...') |
element(by.model('...')) | page.locator('[ng-model="..."]') |
element(by.repeater('...')) | page.locator('[ng-repeat="..."]') |
element(by.xpath('...')) | page.locator('xpath=...') |
element.all | page.locator |
browser.get(url) | await page.goto(url) |
browser.getCurrentUrl() | page.url() |
範例
Protractor
describe('angularjs homepage todo list', function() {
it('should add a todo', function() {
browser.get('https://angularjs.org');
element(by.model('todoList.todoText')).sendKeys('first test');
element(by.css('[value="add"]')).click();
const todoList = element.all(by.repeater('todo in todoList.todos'));
expect(todoList.count()).toEqual(3);
expect(todoList.get(2).getText()).toEqual('first test');
// You wrote your first test, cross it off the list
todoList.get(2).element(by.css('input')).click();
const completedAmount = element.all(by.css('.done-true'));
expect(completedAmount.count()).toEqual(2);
});
});
逐行遷移至 Playwright Test
const { test, expect } = require('@playwright/test'); // 1
test.describe('angularjs homepage todo list', () => {
test('should add a todo', async ({ page }) => { // 2, 3
await page.goto('https://angularjs.org'); // 4
await page.locator('[ng-model="todoList.todoText"]').fill('first test');
await page.locator('[value="add"]').click();
const todoList = page.locator('[ng-repeat="todo in todoList.todos"]'); // 5
await expect(todoList).toHaveCount(3);
await expect(todoList.nth(2)).toHaveText('first test', {
useInnerText: true,
});
// You wrote your first test, cross it off the list
await todoList.nth(2).getByRole('textbox').click();
const completedAmount = page.locator('.done-true');
await expect(completedAmount).toHaveCount(2);
});
});
遷移重點 (請參閱 Playwright Test 程式碼片段中的內嵌註解)
- 每個 Playwright Test 檔案都明確匯入了
test
和expect
函式 - 測試函式標記為
async
- Playwright Test 獲得
page
作為其參數之一。這是 Playwright Test 中眾多 實用的 fixture 之一。 - 幾乎所有 Playwright 呼叫都加上了
await
前綴 - 使用 page.locator() 建立定位器是少數幾個同步方法之一。
Polyfilling waitForAngular
Playwright Test 內建 自動等待,這使得 protractor 的 waitForAngular
在一般情況下變得不必要。
然而,在某些邊緣情況下它可能很方便。以下是如何在 Playwright Test 中 polyfill waitForAngular
函式
-
請確保您已在 package.json 中安裝 protractor
-
polyfill 函式
async function waitForAngular(page) {
const clientSideScripts = require('protractor/built/clientsidescripts.js');
async function executeScriptAsync(page, script, ...scriptArgs) {
await page.evaluate(`
new Promise((resolve, reject) => {
const callback = (errMessage) => {
if (errMessage)
reject(new Error(errMessage));
else
resolve();
};
(function() {${script}}).apply(null, [...${JSON.stringify(scriptArgs)}, callback]);
})
`);
}
await executeScriptAsync(page, clientSideScripts.waitForAngular, '');
}如果您不想保留舊版本的 protractor,您也可以使用這個更簡單的方法,使用此函式 (僅適用於 Angular 2+)
async function waitForAngular(page) {
await page.evaluate(async () => {
// @ts-expect-error
if (window.getAllAngularTestabilities) {
// @ts-expect-error
await Promise.all(window.getAllAngularTestabilities().map(whenStable));
// @ts-expect-error
async function whenStable(testability) {
return new Promise(res => testability.whenStable(res));
}
}
});
} -
polyfill 用法
const page = await context.newPage();
await page.goto('https://example.org');
await waitForAngular(page);
Playwright Test 超能力
一旦您開始使用 Playwright Test,您將獲得很多好處!
- 完整的零配置 TypeScript 支援
- 在 所有 Web 引擎 (Chrome、Firefox、Safari) 和 任何熱門作業系統 (Windows、macOS、Ubuntu) 上執行測試
- 完整支援多個來源、(i)frames、標籤頁和上下文
- 跨多個瀏覽器平行執行測試
- 內建測試產物收集
您還可以獲得所有這些 ✨ 令人驚嘆的工具 ✨,這些工具與 Playwright Test 捆綁在一起
延伸閱讀
深入了解 Playwright Test 執行器