はじめに
Playwrightでテストを書くにあたり、ハマったこと・調べたことなどをまとめた備忘録になります。随時更新予定。
確認環境
- Version 1.46.1
- Node.js v20.16.0
調べたこと
デバイスについて
- 下記でデバイス一覧を確認できる。
-
playwright.config.ts
に設定を追加することでモバイル・iPadもスクリーンショット取得可能。
特定のprojectのみテストする場合、--project=xxx
オプションを追加する。
複数のprojectをplaywright.config.ts
に持っている場合に単一のprojectでテスト実行したい場合に--project=xxx
オプションを使用する。
例)chromium
のみテストを実行する。
playwright test --project=chromium
テストの実行速度が遅い場合、トレースを記録する。
テストの実行速度が遅い場合の調査は一般的にトレースを記録してどの操作が遅いのか調査する。
--trace on
を指定すると、レポートにトレースが表示される。
npx playwright test xxx.spec.ts --trace on
trace Viewerが動作しない ※未解決
自分の環境ではserviceWorkersが正常に動作せず、TraceViewerが動作しなかった。https
で接続する必要があるが、現状改善できないため、UIモードで確認する。
特定のテストファイルのみの場合はファイル名を指定する。
npx playwright test tests/all-browsers/schedule/event-detail.spec.ts
アサーション
値チェック
<div class="test-div">test txt</div>
const targetDiv = await page.locator('.test-div');
await expect(targetDiv).toHaveText('test txt');
スタイルのチェック
await expect(this.page.locator('.test-dev')).toHaveCSS('background-color', 'rgb(250, 250, 250)')
[Question] is there a way to get element background colour ? · Issue #4282 · microsoft/playwright
属性取得
参考:LocatorAssertions | Playwright
Jestのtest.each
のようにテストをまとめられないか?
PlaywrightにはJestのtest.each
のようなものは存在しない。
追加希望のissueはあったが、forEach
ループを使用するという結論でクローズされている。
[Feature] Add support for test.each / describe.each · Issue #7036 · microsoft/playwright
[
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
].forEach(({ a, b, expected }) => {
test(`given ${a} and ${b} as arguments, returns ${expected}`, ({ page }) => {
expect(a + b).toEqual(expected);
})
});
参考:Playwright
forEach
は非同期操作を待機しないため、非同期操作を行う場合はfor
文を使用する必要がある。
forEach() は非同期操作を待機しないため、代わりにこれが必要になります。
let testList = [
{ name: 'inputA', selector: '.input-a' },
{ name: 'inputB', selector: '.input-b' },
];
for (const { name, selector } of testList) {
await test(`${name}表示テスト$`, async({ page }) => {
let elem = await page.locator(`${selector}`);
expect(elem).toBeVisible();
})
}
foreach in playwright(typescript) · Issue #19943 · microsoft/playwright
デバイスによって実行するテストを変える
下記のパターン
isMobile
オプションを使用する。
- TestOptions | Playwright
- テスト内の一部をデバイスによって分岐したい場合
- ただし、タブレット端末も
isMobile=true
となるので注意する。
test('ログイン', async ({ page, isMobile }) => {
...(省略)
if (isMobile) {
//特定のセレクタを持つ要素が描画されるまで待つ
await page.waitForSelector('#sp-container');
else {
await page.waitForSelector('#pc-container');
}
playwright.config.ts
のprojects
内で対象デバイスprojectのtestMatchを指定する。
- project.name(
testInfo.project.name
)を参照する。
test('ログイン', async ({ page, isMobile }, testInfo) => {
...(省略)
switch (testInfo.project.name) {
//特定のセレクタを持つ要素が描画されるまで待つ
case "Mobile Safari":
await page.waitForSelector('#sp-container');
break;
default:
await page.waitForSelector('#pc-container');
}
デバイスによってスキップする
beforeEach
でデバイスをチェックしてテストをスキップすることが可能。
ただし、出力でskipX件と表示される。skipして良いものか確認必要になりそうなので、ファイルを分けてテストした方が良いかもしれない。。
test.describe("簡易入力ダイアログテスト", () => {
test.beforeEach(({ isMobile }) => {
test.skip(isMobile, "スキップの説明");
});
test("簡易入力ダイアログが表示されるか", async ({ page }) => {
テストのファイル名取得
test('random test', async ({ page }, testInfo) => {
await page.goto('https://playwright.dev/');
console.log(testInfo.title);
console.log(testInfo.titlePath);
});
参考:How to get the current test name for Playwright in TypeScript? - Stack Overflow
APIリクエストのレスポンスを受け取るまで待機する
すべてのRequestとResponseを監視できる。
page.waitForResponse()
を使用することで待機できる。
APIリクエスト前に下記を記述する。
const responsePromise = page.waitForResponse('**/sample_api/fetch_data');
// リクエストURLに該当文字列を含む
const responsePromise = page.waitForResponse((response) => response.url().includes(`sample_api/events/${対象ID}`));
ステータスのテスト。
expect(apiResponse.status()).toBe(200);
json()
でレスポンスを取得・テストできる。
let resBody = await apiResponse.json();
let createEventId = resBody?.result?.event_id;
要素をドラッグ&ドロップする
いくつか方法がある。ただし、dragTo
とdragToDrop
はドロップが正常に動作しないパターンが存在するため注意が必要。※詳細はハマった項目に記載。
dragTo
await page.locator(`#draggable`).dragTo(page.locator(`#droppable`));
参考:drag To
dragToDrop
await page.dragAndDrop('#draggable', '#droppable');
mouse
await page.locator('#```').hover();
await page.mouse.down();
await page.locator('#droppable').hover();
await page.mouse.up();
日時
await page.clock.setFixedTime(new Date('2024-10-10T00:00:00'));
ハマったこと
ドラッグ&ドロップが上手く動作しない。
dragTo
やdragToDrop
を使用した際に、永遠に上下スクロールし続け、ドラッグ&ドロップが正常に動作しない現象が発生した。
原因
-
dragTo
やdragToDrop
では指定したLocator位置へ一瞬でカーソルが移動する形となる。この挙動で正しい位置を取得できなくなっている可能性がある。 - ドラッグ&ドロップする要素の親がスクロール可能になっている。ここがスクロールするため、正しい位置が取得できていない可能性がある。
対処法
- ドラッグ&ドロップを行う前に、親要素などスクロールしている要素の位置を調整する。下記の例は一番上にスクロールを行っている。
await page.$eval(`[id=`${DRAG_DROP_PARENT_ID}`]`, (element) => {
element.scrollTo(0, 0);
});
-
dragTo
やdragToDrop
は使用せず、page.mouse
を使用する。 -
page.mouse.move
のoptionssteps
を適切に指定することで解消。- ただし、Safariはstepsを指定すると正常に動作しなくなるため未指定にした。
options Object (optional)
steps number (optional)#
Defaults to 1. Sends intermediate mousemove events.
export async function drag(page: Page, draggable: Locator, droppable: Locator, isSafari: boolean) {
const box = (await droppable.boundingBox())!;
await draggable.hover();
await page.mouse.down();
let options = isSafari ? {} : { steps: 5 };
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2, options);
await page.mouse.up();
};
参考
- [BUG] dragTo / mouse actions not working in our application · Issue #20254 · microsoft/playwright
- javascript - Playwright page.click scrolls too much - Stack Overflow
- PlaywrightでdragToメソッドが上手く動作しない時の対処方法 │ Find out by JURABI
エラー関連
数字で始まるidをselectorで指定するとエラーになる。
対処法
属性セレクタで指定する。
await page.waitForSelector('[id="20240930"]');
原因
CSS3 IDセレクタ仕様で、#のあとに数字を使用してはいけないため、エラーになる。
they cannot start with a digit, two hyphens, or a hyphen followed by a digit.
数字、2つのハイフン、ハイフンの後に数字で始めることはできない。
引用元:Syntax and basic data types
await page.waitForSelector('#20240930');
page.waitForSelector: SyntaxError: Failed to execute 'querySelectorAll' on 'Document': '#20240930' is not a valid selector
参考:Document.querySelector() で先頭が数字のIDを指定するとエラーが起きる。
テストに問題はないが時々navigating to "http://sample.com", waiting until "load"
で落ちる
原因
- 自分の場合は、テストしているアプリ自体の問題でAPIリクエストに失敗し、対象要素が表示されていなかった。
対処法
- 前述の原因だったため未確認だが、単純に時間がかかっていて落ちる場合は下記を試してみる。
- PlaywrightTestConfigで
timeout
の値を変更する。workers
の数を指定してみる。
- PlaywrightTestConfigで
参考
- Navigating to "url", waiting until "load" - Python Playwright Issue - Stack Overflow
- Playwrightの並列数(worker数)を指定 - Minerva
Bootstrapのtooltipがテストできない。
-
.tooltip
などをSelectorに指定してdata-toggle="tooltip"
要素のLocatorを取得しようと試みたが取得できなかった。 - そもそも
data-toggle="tooltip"
要素にmouse.hover
でホバーしても、ツールチップが表示されない。
mountされたコンポーネントを基にしてテストを行う方法が
[BUG] Playwright component tests fail to trigger Fluent tooltip · Issue #27660 · microsoft/playwright · GitHub
Angularではライブラリ
調査したいこと
-
要素のtextContentの値が一致するまで待機は可能?
-
await page.waitForSelector('text="Please provide a new password."');
で待機可能か? [BUG] page.waitForSelector('text="something"'); flaky · Issue #1239 · microsoft/playwright
-
- テスト数の多いテストファイルでタイムアウトが発生する。テストに含める内容・テストの細分化のベストプラクティス