Playwright - 2024/6/9
ブラウザ操作を自動化する手段として Selenium を使っていたが、微妙に使いづらいのと、nodeを利用する機会が出てきたので別の方法を検討。
Playwrightが良さそうだと思ったので使ってみる。
Playwright?
ブラウザに対する操作を自動化し、Webアプリのテストなどに利用できる。
同じようなツールとして、SeleniumやPuppeteerなどがある。
Playwrightがここ最近、かなり伸びてきている。
ぶっちゃけ Cypress はあまり意識してなくて、とりあえず使ってみるかという感じで Playwright を使ってみているのであしからず。使い方によっては Cypress の法が良いかもしれない。
並列実行が簡単とか、Shadow DOMが簡単に拾えるとか、そのあたりが良いかなと思っている。
インストール
ただ今回は、ブラウザを一緒に入れたくないと思ったので、coreだけ取得してみる。
code:bash
$ npm install playwright-core
# Typescriptで書いていきたいので以下も
$ npm install --save-dev typescript @types/node@20 ts-node
$ npx tsc --init
# $ npm i -D @playwright/test
Typescriptの設定。
code:tsconfig.json
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"baseUrl": "./src",
"outDir": "./dist",
"sourceMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
./src以下に、index.tsを置く。
code:bash
# ビルド
$ npx tsc
# 実行
$ node ./dist/src/index.js
サンプル
ブラウザを制御するサンプル。
Googleのトップページへ遷移し、スクリーンショットを取得する。
code:index.ts
import { chromium } from 'playwright-core';
(async () => {
// ブラウザを起動する
const browser = await chromium.launch({
channel: 'chrome', // channelを指定することで、マシンに既存のChromeが使える
headless: false, // 画面を表示しながら動かす
args: [
'--start-maximized', // 最大化する Viewportをnullにする必要がある
],
});
// ウインドウを起動
const context = await browser.newContext({ viewport: null });
// ページ(タブ)を生成
const page = await context.newPage();
// サイトへアクセス
// スクリーンショットを取得
await page.screenshot({ path: 'sample.png' });
// ブラウザを終了
await browser.close();
})();
スクリーンショットを取得する際の小技
スクリーンショットは、ページまたは特定の要素に絞って取得することができる。
このような場面はよくあると思われるがこのとき、ページやその要素の読み込みが間に合っておらず、取得できないこともよく発生する。
playwrightは、このようなページや要素の読み込みが完了するのを自動的に待ってくれる機能を持っており、意外と何もしなくても良い感じに取得できたりする。
ただ、明示的に「どのように、どのくらい待つ」という指定も可能で、このあたり にいくつか種類が記載されている。 今回は、あるページに表示される画像のスクリーンショットを取りたいが、それが完全に表示されるのを待ってから取得するためにはどのようにすれば良いかの例を記載する。
code:ts
// pageは生成済みとする
// 対象のページへ遷移
await page.goto("target site url");
// 画像が完全に読み込まれるのを待つ
await page.waitForFunction(() => {
const imgs = Array.from(document.querySelectorAll('img'));
return imgs.every(img => img.complete);
});
// 画像のスクリーンショットを取得
await page.locator("selector for target img").screenshot({ path: "sample.png" });
waitForFunctionは、待つ条件を自分で定義するための関数で、条件を持った関数を渡して利用する。
渡した関数がtrueを返すと、制御が戻ってくる。
またwaitForFunctionではJSHandleを扱うことができる。
今回はページ内のimgタグすべてが、complete属性を持っていればtrueを返すような関数を設定している。
これによって、画像が完全に読み込まれるのを確認した後に、スクリーンショットを取得できる。
この方法は ここ を参考に、というか丸パクリしてます。ありがとうございます。 参考