Типизация Puppeteer

Puppeteer — это библиотека для Node.js, предоставляющая API для управления браузером Chrome или Chromium. Она активно используется для автоматизации веб-приложений, создания тестов и выполнения сценариев на реальных страницах. Одним из ключевых аспектов эффективного использования Puppeteer является типизация, которая помогает повысить стабильность и предсказуемость кода.

Типизация в Puppeteer имеет несколько аспектов, связанных с корректным использованием API и взаимодействием с браузером через JavaScript. С помощью TypeScript можно значительно улучшить процесс разработки и тестирования, гарантируя, что код будет работать правильно на этапе компиляции.

Подключение TypeScript

Для использования Puppeteer с TypeScript, необходимо сначала установить соответствующие пакеты:

npm install puppeteer
npm install --save-dev typescript @types/node

После этого можно настроить TypeScript с помощью конфигурационного файла tsconfig.json, указав необходимые параметры, такие как strict, чтобы включить строгую типизацию.

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true
  }
}

Основные типы Puppeteer

Puppeteer предоставляет несколько ключевых типов, которые облегчают работу с API и позволяют достичь высокой точности в типизации.

Browser

Тип Browser представляет браузерное окно. Этот объект используется для создания страниц, взаимодействия с вкладками и управления сессиями браузера.

import puppeteer, { Browser } from &

async function launchBrowser(): Promise<Browser> {
  const browser: Browser = await puppeteer.launch();
  return browser;
}

Page

Тип Page относится к открытой вкладке или странице браузера. На объекте Page выполняются операции, такие как переход по URL, взаимодействие с элементами и выполнение JavaScript в контексте страницы.

import { Page } from 'puppeteer';

async function openPage(browser: Browser): Promise<Page> {
  const page: Page = await browser.newPage();
  await page.goto('https://example.com');
  return page;
}

ElementHandle

Тип ElementHandle представляет собой элемент DOM на странице. Он используется для взаимодействия с отдельными элементами, такими как клики, ввод текста и извлечение информации.

import { ElementHandle } from 'puppeteer';

async function clickButton(page: Page): Promise<void> {
  const button: ElementHandle = await page.$('button#submit');
  if (button) {
    await button.click();
  }
}

Evaluation

Puppeteer поддерживает выполнение JavaScript-кода на странице через метод evaluate. Результат выполнения кода может быть типизирован для повышения предсказуемости.

import { Page } from 'puppeteer';

async function getTitle(page: Page): Promise<string> {
  const title: string = await page.evaluate(() => document.title);
  return title;
}

Типизация пользовательских функций

Puppeteer предоставляет типы для большинства своих методов, но иногда необходимо создавать свои собственные функции, которые взаимодействуют с Puppeteer. В таких случаях важно правильно типизировать входные параметры и возвращаемые значения.

Типизация параметров

Когда функции принимают параметры, такие как URL или селекторы, их также следует типизировать для предотвращения ошибок.

async function openUrl(page: Page, url: string): Promise<void> {
  await page.goto(url);
}

Возвращаемые значения

Важно указать, какие данные функция должна возвращать. В случае взаимодействия с элементами или результатами выполнения JavaScript это могут быть примитивы или более сложные структуры.

async function getElementText(page: Page, selector: string): Promise<string> {
  const element = await page.$(selector);
  if (element) {
    return await element.evaluate(el => el.textContent ?? '');
  }
  return '';
}

Совмещение с библиотеками для тестирования

Для работы с тестами Puppeteer часто используется в сочетании с различными тестовыми библиотеками, такими как Jest или Mocha. В таких случаях важно, чтобы типы Puppeteer корректно интегрировались с типами, предоставляемыми этими библиотеками.

Типизация с Jest

Jest предоставляет поддержку TypeScript и позволяет типизировать тесты. При этом важно корректно определять типы для объектов Puppeteer, таких как Browser, Page и ElementHandle.

import puppeteer, { Browser, Page } from 'puppeteer';

describe('Puppeteer Tests', () => {
  let browser: Browser;
  let page: Page;

  beforeAll(async () => {
    browser = await puppeteer.launch();
    page = await browser.newPage();
  });

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

  it('should open the correct page', async () => {
    await page.goto('https://example.com');
    const title: string = await page.title();
    expect(title).toBe('Example Domain');
  });
});

Использование типов для взаимодействия с данными на странице

Когда необходимо работать с динамическими данными на странице, например, из таблиц или списков, правильная типизация помогает избежать ошибок при извлечении этих данных. Важно правильно определять типы для элементов и их значений.

async function getTableData(page: Page): Promise<string[]> {
  const rows = await page.$$('table tr');
  const data: string[] = [];

  for (const row of rows) {
    const text = await row.evaluate(r => r.textContent?.trim() ?? '');
    data.push(text);
  }
  return data;
}

Использование кастомных типов

Puppeteer часто применяется для сложных операций, таких как генерация скриншотов, создание PDF-файлов или взаимодействие с файлами. В таких случаях может понадобиться создание кастомных типов, если взаимодействие с Puppeteer выходит за рамки стандартного API.

interface ScreenshotOptions {
  path: string;
  fullPage?: boolean;
}

async function takeScreenshot(page: Page, options: ScreenshotOptions): Promise<void> {
  await page.screenshot(options);
}

Типизация в сложных сценариях

Типизация особенно важна в более сложных сценариях, когда взаимодействие с несколькими элементами или страницами происходит в асинхронном режиме. В таких случаях важно правильно управлять типами для всех промежуточных данных.

async function multiPageTest(browser: Browser): Promise<void> {
  const page1: Page = await browser.newPage();
  const page2: Page = await browser.newPage();

  await page1.goto('https://example.com');
  await page2.goto('https://anotherexample.com');

  const title1: string = await page1.title();
  const title2: string = await page2.title();

  console.log(`Page 1 title: ${title1}`);
  console.log(`Page 2 title: ${title2}`);
}

Заключение

Типизация в Puppeteer играет ключевую роль в улучшении качества кода и обеспечении его стабильности при тестировании веб-приложений. Использование TypeScript с Puppeteer позволяет легко управлять типами объектов и данных, повышая предсказуемость и уменьшая вероятность ошибок на стадии компиляции. Поддержка типов для основных объектов, таких как Browser, Page, ElementHandle, а также возможность создания кастомных типов и их интеграция с тестовыми библиотеками, делает процесс разработки удобным и безопасным.