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 참조에는 가능한 작업에 관한 자세한 정보가 포함되어 있습니다. 여기에 설명되지 않은 기능이 많이 있습니다.