あくまで個人的なメモ

あくまで個人的なメモ

Puppeteer で Headless Chromeを操ってE2Eテストする(予定) - インストール編

Puppeteer とは Headless Chrome Node APIだそうで。

要はGUI無しでChrome(正確にはChromium)を操作する。レンダリングエンジンはChromeを使っていてGUI無いので軽く動作する辺りが利点。 すごく昔seleniumでE2Eテスト書いた時はFirefoxGUIが動かないと死ぬとかあって…(昔の嫌な思い出を思い出した

それはそれとして。今回はとりあえず動かす所まで。

install

node環境がすでにあるものとします。

node v6.4.0以上が必須環境だが node v7.6.0 からasync/awaitが使えるようになるのでバージョン確認して古い場合は v7.6.0 以上にしよう。nodebrewおすすめ。

npm i -save puppeteer

使ってみる。

オフィシャルなサンプルをそのまま実行してみる。

適当なファイル(ex: sample.js)を作り、下記をコピペする。

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({path: 'example.png'});

    await browser.close();
})();

実行する。

node sample.js

問題なければ同じディレクトリにexample.pngが出来る。中身を確認してみよう。(https://example.com のスクショが撮れているはず)

少し複雑な操作を試してみる。

ログイン画面を開きログインしてみる。

たとえばgithubにログインしてみる。(2段階認証設定してないログイン)

const puppeteer = require('puppeteer');
const pc = {
    'name': 'Chrome Mac',
    'userAgent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    'viewport': {
        'width': 1024,
        'height': 820,
        'deviceScaleFactor': 1,
        'isMobile': false,
        'hasTouch': false,
        'isLandscape': false
    }
};

(async() => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    /**
    * PCエミュレート
    * (デフォの画面サイズが小さめなので広げる。デフォサイズだとタブレットのポートレートモードな画面になり
    * ログインリンクが非表示エレメントになるため「Node is not visible」のエラーとなる。
    * ハンバーガーメニュー開いてやれば解決なのだが面倒なので)
    */
    await page.emulate(pc);

    // ページを開く
    await page.goto('https://github.com/');

    // 記念撮影
    await page.screenshot({path: 'index.png', fullPage: true});

    // ログイン画面に遷移する。/loginがログインリンクなのでそのエレメントを探す。
    const login = await page.$('a[href="/login"]');
    // リンクをクリックする。
    await login.click();
    // 記念撮影
    await page.screenshot({path: 'login.png', fullPage: true});

    // ログイン情報入力
    await page.type("input[name='login']", 'xxxx');
    await page.type("input[name='password']", 'yyyy');
    // ログインボタン押下
    const loginButton = await page.$('input[type=submit]');
    await loginButton.click();
    /**
    * ログイン完了するまで余裕を見て待つ
    * (ログイン後のページのselectorが出るまで待機させようとしたが
    * "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive"
    * なエラーが出た)
    * おそらく何らかの対応をすれば突破できるが面倒だった…
    */
    await page.waitFor(5000);
    // 記念撮影
    await page.screenshot({path: 'dashboard.png', fullPage: true});

    // ブラウザを閉じる。
    await browser.close();
})();

続きはまた今度。

他のツールだと環境構築にだいぶ手間取る感じがあるが、npm 一発でインストールできてAPIも結構充実しているのでかなり楽に導入できるのではないかと思う。

出来ることと出来ないことを色々試してみる。少し難しい事ができるようならまた何か別記事で書くかも…

その他