Puppeteer представляет собой библиотеку для управления браузером Chromium через API на JavaScript, предоставляя полный контроль над браузерной средой. В контексте тестирования часто возникает необходимость последовательного выполнения действий с веб-страницей, что требует грамотного управления очередями задач.
Puppeteer полностью основан на асинхронных операциях. Любой метод,
который взаимодействует с браузером или страницей, возвращает
Promise. Для корректного управления очередью задач
критически важно строго соблюдать порядок вызовов через
await или цепочки .then():
const puppeteer = require(&
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.click('#login-button');
await page.type('#username', 'admin');
await page.type('#password', 'password123');
await page.click('#submit-button');
await browser.close();
})();
В этом примере каждая операция выполняется последовательно. Попытка
убрать await приведет к гонке задач, где
действия могут выполняться в неправильном порядке.
Для ускорения тестирования иногда требуется выполнять
параллельные задачи, например, проверку нескольких
страниц одновременно. Puppeteer позволяет создавать несколько
экземпляров страниц (page) внутри одного браузера.
Управление очередью здесь сводится к контролю количества одновременно
выполняемых промисов.
const urls = ['https://example.com', 'https://example.org', 'https://example.net'];
const processPage = async (browser, url) => {
const page = await browser.newPage();
await page.goto(url);
const title = await page.title();
await page.close();
return title;
};
(async () => {
const browser = await puppeteer.launch();
const results = await Promise.all(urls.map(url => processPage(browser, url)));
console.log(results);
await browser.close();
})();
Promise.all гарантирует, что все задачи будут запущены
одновременно, а результатом станет массив их результатов. Для
ограничения количества параллельных задач применяют семафоры или
библиотеки очередей, например p-queue.
Для тестов, где важен строгий порядок или ограничение ресурсов, создают очереди с контролем конкарренции:
const PQueue = require('p-queue').default;
const queue = new PQueue({ concurrency: 2 }); // максимум 2 задачи одновременно
urls.forEach(url => {
queue.add(async () => {
const page = await browser.newPage();
await page.goto(url);
console.log(await page.title());
await page.close();
});
});
await queue.onIdle(); // ожидаем завершения всех задач
Такой подход позволяет избежать перегрузки браузера и гарантировать порядок выполнения задач в рамках ограниченной параллельности.
Puppeteer поддерживает работу с событиями страницы:
page.on(‘request’), page.on(‘response’),
page.on(‘console’). Эти события часто интегрируют в очередь
задач для тестирования асинхронного поведения страницы:
page.on('response', response => {
if (response.url().includes('api/data')) {
console.log(`Получен ответ от API: ${response.status()}`);
}
});
События добавляют динамическую задачу в очередь — они не блокируют основной поток, но позволяют отслеживать и логировать действия страницы в реальном времени.
Очереди задач в Puppeteer тесно связаны с таймингом
элементов. Методы page.waitForSelector,
page.waitForTimeout, page.waitForResponse
позволяют корректно синхронизировать выполнение действий:
await page.waitForSelector('#submit-button', { visible: true });
await page.click('#submit-button');
await page.waitForResponse(response => response.url().includes('/success') && response.status() === 200);
Правильное использование ожиданий предотвращает сбой тестов из-за несвоевременных действий, особенно при работе с динамическими страницами.
await для гарантированного порядка выполнения.
p-queue для сложных сценариев.
Эффективное управление очередями задач в Puppeteer позволяет создавать стабильные, воспроизводимые тесты, минимизируя влияние асинхронной природы браузера на результат.