DevTools Protocol использование

WebdriverIO предоставляет гибкие возможности интеграции с Chrome DevTools Protocol (CDP) для расширенного управления браузером и глубокого анализа поведения веб-приложений. CDP позволяет получать доступ к внутренним событиям браузера, манипулировать сетевыми запросами, выполнять отладку и профилирование, что делает тестирование более детализированным и мощным.


Подключение к DevTools Protocol

Для работы с CDP в WebdriverIO необходимо использовать DevTools сервис. В wdio.conf.js он подключается следующим образом:

exports.config = {
    runner: 'local',
    framework: 'mocha',
    services: ['devtools'],
    capabilities: [{
        browserName: 'chrome'
    }],
};

После этого появляется возможность напрямую работать с CDP через объект browser.cdp. WebdriverIO предоставляет метод browser.cdp(domain, command, params) для отправки команд в выбранный домен DevTools.


Основные домены CDP

CDP организован в домены, каждый из которых отвечает за отдельную функциональность браузера:

  • Network — управление сетевыми запросами, перехват и модификация ответов.
  • Page — работа с загрузкой страниц, событиями навигации, скриншотами.
  • DOM — доступ к структуре документа и манипуляции с DOM.
  • Runtime — выполнение JavaScript-кода напрямую в контексте страницы.
  • Performance — профилирование времени работы скриптов и рендеринга.
  • Log — получение логов браузера, включая ошибки консоли.

Использование CDP позволяет выполнять действия, которые невозможно или сложно реализовать через стандартные WebDriver команды.


Пример работы с сетевыми запросами

Перехват и модификация сетевых запросов часто требуется для тестирования API, замены ресурсов или эмуляции ошибок. Пример включения перехвата запросов:

await browser.cdp('Network', 'enable');

await browser.cdp('Network', 'setRequestInterception', {
    patterns: [{ urlPattern: '*', resourceType: 'XHR', interceptionStage: 'Request' }]
});

browser.on('Network.requestIntercepted', async (event) => {
    if (event.request.url.includes('/api/data')) {
        await browser.cdp('Network', 'continueInterceptedRequest', {
            interceptionId: event.interceptionId,
            rawResponse: Buffer.from(JSON.stringify({ data: 'mocked' })).toString('base64')
        });
    } else {
        await browser.cdp('Network', 'continueInterceptedRequest', { interceptionId: event.interceptionId });
    }
});

В этом примере любые XHR-запросы на /api/data заменяются на мокированные данные, что позволяет изолировать фронтенд-тестирование от реального бэкенда.


Работа с DOM и скриншотами

CDP предоставляет прямой доступ к DOM-структуре страницы и позволяет делать скриншоты отдельных элементов или всего документа без использования стандартных методов WebDriver:

const { nodeId } = await browser.cdp('DOM', 'getDocument');
const element = await browser.cdp('DOM', 'querySelector', {
    nodeId,
    selector: '#main'
});

const { data } = await browser.cdp('Page', 'captureScreenshot', {
    clip: { x: 0, y: 0, width: 800, height: 600, scale: 1 }
});
require('fs').writeFileSync('screenshot.png', Buffer.from(data, 'base64'));

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


Профилирование производительности

Для анализа производительности страниц CDP предоставляет методы записи трассировок производительности:

await browser.cdp('Performance', 'enable');
await browser.cdp('Performance', 'start');

await browser.url('https://example.com');

const metrics = await browser.cdp('Performance', 'getMetrics');
console.log(metrics);

await browser.cdp('Performance', 'stop');

Метрики включают загрузку CPU, количество вызовов рендеринга, потребление памяти и другие показатели. Это особенно полезно для тестирования тяжелых страниц и SPA.


Работа с консолью и логами

CDP позволяет получать и фильтровать логи браузера, включая ошибки JavaScript и предупреждения:

await browser.cdp('Log', 'enable');

browser.on('Log.entryAdded', (entry) => {
    console.log(`[${entry.level}] ${entry.text}`);
});

await browser.url('https://example.com');

С помощью этих логов можно отслеживать неожиданные ошибки, проверять вызовы console.warn/console.error и интегрировать их в отчеты тестирования.


Запуск скриптов в контексте страницы

Методы Runtime.evaluate позволяют исполнять произвольный JavaScript в контексте текущей страницы, включая асинхронные операции:

const result = await browser.cdp('Runtime', 'evaluate', {
    expression: 'document.querySelectorAll("a").length'
});
console.log('Количество ссылок на странице:', result.result.value);

Это открывает возможность выполнять вычисления напрямую в браузере без необходимости передачи данных через WebDriver.


Интеграция с WebdriverIO тестами

CDP-команды легко интегрируются с любыми тестами на Mocha, Jasmine или Cucumber, что позволяет комбинировать стандартные действия WebDriver и расширенные возможности DevTools:

describe('CDP Network Mock', () => {
    it('должен возвращать мокированные данные', async () => {
        await browser.cdp('Network', 'enable');
        // Перехват и мокирование запросов
        await browser.url('https://example.com');
        const text = await $('#data').getText();
        console.assert(text === 'mocked');
    });
});

Таким образом, DevTools Protocol расширяет привычные возможности автоматизации, позволяя тестировать фронтенд с высокой точностью и гибкостью.