0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Playwrightでハマったこと・調べたことの備忘録

Last updated at Posted at 2024-12-27

はじめに

Playwrightでテストを書くにあたり、ハマったこと・調べたことなどをまとめた備忘録になります。随時更新予定。

確認環境

  • Version 1.46.1
  • Node.js v20.16.0

調べたこと

デバイスについて

特定のprojectのみテストする場合、--project=xxxオプションを追加する。

複数のprojectをplaywright.config.tsに持っている場合に単一のprojectでテスト実行したい場合に--project=xxxオプションを使用する。

例)chromiumのみテストを実行する。

playwright test --project=chromium

参考:Projects | Playwright

テストの実行速度が遅い場合、トレースを記録する。

テストの実行速度が遅い場合の調査は一般的にトレースを記録してどの操作が遅いのか調査する。
--trace onを指定すると、レポートにトレースが表示される。

npx playwright test xxx.spec.ts --trace on

参考:Recording a Trace

trace Viewerが動作しない ※未解決

自分の環境ではserviceWorkersが正常に動作せず、TraceViewerが動作しなかった。httpsで接続する必要があるが、現状改善できないため、UIモードで確認する。

[BUG] trace viewer (html report) not working in jenkins pipeline · Issue #27655 · microsoft/playwright

特定のテストファイルのみの場合はファイル名を指定する。

npx playwright test tests/all-browsers/schedule/event-detail.spec.ts

参考:Command line | Playwright

アサーション

参考:Writing tests | Playwright

値チェック

<div class="test-div">test txt</div>
sample.ts
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.tsprojects内で対象デバイス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 }) => {

テストのファイル名取得

sample.spec.ts
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リクエストのレスポンスを受け取るまで待機する

すべてのRequestResponseを監視できる。
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;

参考:Network | Playwright

要素をドラッグ&ドロップする

いくつか方法がある。ただし、dragTodragToDropはドロップが正常に動作しないパターンが存在するため注意が必要。※詳細はハマった項目に記載。

dragTo

await page.locator(`#draggable`).dragTo(page.locator(`#droppable`));

参考:drag To

dragToDrop

await page.dragAndDrop('#draggable', '#droppable');

参考:Page | Playwright

mouse

await page.locator('#```').hover();
await page.mouse.down();
await page.locator('#droppable').hover();
await page.mouse.up();

参考:Actions | Playwright

日時

    await page.clock.setFixedTime(new Date('2024-10-10T00:00:00'));

ハマったこと

ドラッグ&ドロップが上手く動作しない。

dragTodragToDropを使用した際に、永遠に上下スクロールし続け、ドラッグ&ドロップが正常に動作しない現象が発生した。

原因

  • dragTodragToDropでは指定したLocator位置へ一瞬でカーソルが移動する形となる。この挙動で正しい位置を取得できなくなっている可能性がある。
  • ドラッグ&ドロップする要素の親がスクロール可能になっている。ここがスクロールするため、正しい位置が取得できていない可能性がある。

対処法

  • ドラッグ&ドロップを行う前に、親要素などスクロールしている要素の位置を調整する。下記の例は一番上にスクロールを行っている。
sample.ts
await page.$eval(`[id=`${DRAG_DROP_PARENT_ID}`]`, (element) => {
    element.scrollTo(0, 0);
});
  • dragTodragToDropは使用せず、page.mouseを使用する。
  • page.mouse.moveのoptionsstepsを適切に指定することで解消。
    • ただし、Safariはstepsを指定すると正常に動作しなくなるため未指定にした。

options Object (optional)
steps number (optional)#
Defaults to 1. Sends intermediate mousemove events.

参考:Mouse | Playwright

sample.ts
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();
};

参考

エラー関連

数字で始まる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の数を指定してみる。

参考

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ではライブラリ

調査したいこと

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?