Service Workers — это скрипты, работающие в фоновом режиме браузера, обеспечивающие функциональность оффлайн-приложений, кэширование ресурсов и управление сетевыми запросами. В контексте автоматизированного тестирования их присутствие создает дополнительные нюансы, которые необходимо учитывать при написании тестов на Protractor.
Для тестирования приложений с Service Workers необходимо убедиться, что Protractor запускается с поддержкой современного браузера (Chrome, Edge), так как старые версии Selenium не полностью совместимы с Service Worker API. Конфигурация Protractor должна включать следующие параметры:
exports.config = {
framework: 'jasmine',
directConnect: true,
capabilities: {
browserName: 'chrome',
chromeOptions: {
args: ['--disable-web-security', '--allow-insecure-localhost']
}
},
specs: ['tests/**/*.spec.js']
};
Важный момент: отключение некоторых механизмов безопасности может потребоваться для тестирования кэширования и оффлайн-режима без необходимости настройки HTTPS на локальной машине.
Service Worker регистрируется через
navigator.serviceWorker.register(). В тестах важно
проверить, что регистрация прошла успешно, прежде чем тестировать
взаимодействие с кэшем или сетевыми запросами:
it('должен зарегистрировать Service Worker', async () => {
await browser.get('http://localhost:4200');
const isRegistered = await browser.executeScript(async () => {
if ('serviceWorker' in navigator) {
const registration = await navigator.serviceWorker.ready;
return !!registration.active;
}
return false;
});
expect(isRegistered).toBe(true);
});
Ключевой момент:
navigator.serviceWorker.ready возвращает промис, который
разрешается только после полной активации Service Worker.
Service Workers позволяют симулировать оффлайн-режим. В Protractor это можно сделать через Chrome DevTools Protocol (CDP):
const cdp = await browser.driver.createCDPConnection('page');
await browser.driver.sendCDPCommand('Network.enable', {});
await browser.driver.sendCDPCommand('Network.emulateNetworkConditions', {
offline: true,
latency: 0,
downloadThroughput: 0,
uploadThroughput: 0
});
await browser.get('http://localhost:4200');
const offlineContent = await element(by.css('.offline-message')).getText();
expect(offlineContent).toContain('Вы оффлайн');
Особенность: обычный browser.get() при
отключенном интернете может вызвать ошибку загрузки страницы. Service
Worker должен быть активен для корректного отображения
оффлайн-контента.
Для стабильного тестирования важно уметь сбрасывать состояние Service Worker и кэша между тестами:
afterEach(async () => {
await browser.executeScript(async () => {
const registrations = await navigator.serviceWorker.getRegistrations();
for (const reg of registrations) {
await reg.unregister();
}
if (caches) {
const cacheNames = await caches.keys();
for (const name of cacheNames) {
await caches.delete(name);
}
}
});
});
Примечание: без очистки кэша предыдущие тесты могут влиять на последующие, особенно при проверке загрузки свежих версий ресурсов.
Service Worker может перехватывать сетевые запросы и отдавать
кэшированные ответы. Для тестирования этого поведения можно использовать
комбинацию browser.executeScript и стандартных методов
Protractor для проверки DOM:
it('должен использовать кэш для запроса данных', async () => {
await browser.get('http://localhost:4200/data-page');
const dataText = await browser.executeScript(async () => {
const response = await fetch('/api/data');
return await response.text();
});
expect(dataText).toContain('Cached Data');
});
Важно: тест должен учитывать, что кэширование может
быть асинхронным, поэтому ожидание через await
обязательно.
В одностраничных приложениях (SPA) Service Workers активно управляют маршрутами и ресурсами. Для Protractor это означает:
browser.getCurrentUrl(), если Service Worker перехватывает
запрос.browser.executeScript(() => window.history.pushState(...))
и проверять DOM-элементы, а не URL.browser.wait для ожидания загрузки данных.Для сложных сценариев полезно логировать состояние Service Worker и кэша:
const logs = await browser.executeScript(async () => {
const registrations = await navigator.serviceWorker.getRegistrations();
return registrations.map(reg => ({
scope: reg.scope,
active: !!reg.active,
installing: !!reg.installing,
waiting: !!reg.waiting
}));
});
console.table(logs);
Такой подход позволяет быстро выявлять проблемы с регистрацией или активацией Service Worker в тестовой среде.
browser.wait для ожидания активации
Service Worker перед выполнением теста.beforeEach/afterEach.executeScript.Тщательное управление состоянием Service Worker и кэша обеспечивает надежное тестирование приложений с оффлайн-функциональностью, гарантируя воспроизводимость и независимость тестов при работе с Protractor.