Puppeteer で Chrome 拡張機能をテストする

Puppeteer は、ウェブサイトの自動テストを構築するためのフレームワークを提供します。これには、Chrome 拡張機能をテストする機能も含まれています。これらは、ウェブサイトや拡張機能が最終製品に組み込まれた後に、その機能をテストするハイレベルなエンドツーエンド テストです。このチュートリアルでは、サンプル リポジトリから拡張機能の基本的なテストを作成する方法を説明します。

始める前に

chrome-extensions-samples リポジトリのクローンを作成するかダウンロードします。テスト拡張機能として、api-samples/history/showHistory の履歴 API デモを使用します。

また、Puppeteer の基盤となるランタイムである Node.JS もインストールする必要があります。

テストを作成する

ステップ 1: Node.JS プロジェクトを開始する

基本的な Node.JS プロジェクトを設定する必要があります。新しいフォルダに、次の内容の package.json ファイルを作成します。

package.json:

{
  "name": "puppeteer-demo",
  "version": "1.0"
}

拡張機能の manifest.json ファイルと同様に、このファイルはすべての Node プロジェクトで必要です。

ステップ 2: Puppeteer と Jest をインストールする

npm install puppeteer jest を実行して、Puppeteer と Jest を依存関係として追加します。これらは package.json ファイルに自動的に追加されます。

スタンドアロンの Puppeteer テストを作成することもできますが、ここでは Jest をテストランナーとして使用して、コードに構造を追加します。

ステップ 3: エントリ ポイントを作成する

index.test.js という名前の新しいファイルを作成し、次のコードを追加します。

index.test.js:

const puppeteer = require('puppeteer');

const EXTENSION_PATH = '../../api-samples/history/showHistory';

let browser;
let worker;

beforeEach(async () => {
  // TODO: Launch the browser.
});

afterEach(async () => {
  // TODO: Close the browser.
});

ステップ 4: ブラウザを起動する

ブラウザを起動して閉じるように beforeEachafterEach を更新しました。多くのテストを実行する場合は、同じブラウザを使用することを検討してください。ただし、テスト間の分離が減少し、あるテストが別のテストの結果に影響する可能性があるため、通常はおすすめできません。

index.test.js:

beforeEach(async () => {
  browser = await puppeteer.launch({
    headless: false,
    pipe: true,
    enableExtensions: [EXTENSION_PATH]
  });
});

afterEach(async () => {
  await browser.close();
  browser = undefined;
});

ステップ 5: 拡張機能のサービス ワーカーを待機する

拡張機能のサービス ワーカーが起動するのを待つ必要があります。これにより、後でポップアップを開くために使用できます。beforeEach 関数を次のコードで更新します。

beforeEach(async () => {
  browser = await puppeteer.launch({
    headless: false,
    pipe: true,
    enableExtensions: [EXTENSION_PATH]
  });

  const workerTarget = await browser.waitForTarget(
    // Assumes that there is only one service worker created by the extension
    // and its URL ends with service-worker.js.
    (target) =>
      target.type() === 'service_worker' &&
      target.url().endsWith('service-worker.js')
  );

  worker = await workerTarget.worker();
});

ステップ 6: エイリアスを追加する

テストの実行を簡単にするには、package.json ファイルにエイリアスを追加します。

package.json:

{
  "name": "puppeteer-demo",
  "version": "1.0",
  "dependencies": {
    "puppeteer": "^24.8.1"
  },
  "scripts": {
    "start": "jest ."
  }
}

これにより、現在のディレクトリ内の .test.js で終わるすべてのファイルが実行されます。

ステップ 7: ポップアップを開く

基本的なテストを追加します。まず新しいページを開いて、ブラウザの履歴に項目を追加します。次に、ポップアップを開いて履歴の内容を確認します。次のコードを追加します。

index.test.js:

test('popup renders correctly', async () => {
  // Open a page to add a history item.
  const page = await browser.newPage();
  await page.goto('https://example.com');

  // Open the extension popup.
  await worker.evaluate('chrome.action.openPopup();');

  const popupTarget = await browser.waitForTarget(
    // Assumes that there is only one page with the URL ending with popup.html
    // and that is the popup created by the extension.
    (target) => target.type() === 'page' && target.url().endsWith('popup.html')
  );
});

ステップ 8: 現在の状態をアサートする

アサーションを追加して、拡張機能が想定どおりに動作しない場合にテストが失敗するようにします。ポップアップには最近アクセスしたページが表示されるはずなので、表示されていることを確認します。

index.test.js:

test('popup renders correctly', async () => {
  // Open a page to add a history item.
  const page = await browser.newPage();
  await page.goto('https://example.com');

  // Open the extension popup.
  await worker.evaluate('chrome.action.openPopup();');

  const popupTarget = await browser.waitForTarget(
    // Assumes that there is only one page with the URL ending with popup.html
    // and that is the popup created by the extension.
    (target) => target.type() === 'page' && target.url().endsWith('popup.html')
  );

  const popup = await popupTarget.asPage();

  const list = await page.$('ul');
  const children = await list.$$('li');

  expect(children.length).toBe(1);
});

ステップ 9: テストを実行する

テストを実行するには、npm start を使用します。テストに合格したことを示す出力が表示されます。

プロジェクト全体は、chrome-extensions-samples リポジトリで確認できます。

次のステップ

基本を習得したら、独自の拡張機能のテストスイートを作成してみましょう。Puppeteer の API リファレンスには、可能なことに関する詳細情報が記載されています。ここには記載されていない機能も多数あります。