使用 Puppeteer 测试 Chrome 扩展程序

Puppeteer 提供了一个用于构建网站自动化测试的框架,其中还包括测试 Chrome 扩展程序的功能。这些是高级端到端测试,用于测试网站或扩展程序在构建到最终产品中的功能。在本教程中,我们将演示如何为示例代码库中的扩展程序编写基本测试。

前期准备

克隆或下载 chrome-extensions-samples 代码库。我们将使用 api-samples/history/showHistory 中的 History API 演示作为测试扩展程序。

您还需要安装 Node.JS,这是 Puppeteer 所基于的运行时。

编写测试

第 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 参考文档包含有关可实现功能的更多信息 - 其中有许多功能未在此处描述。