В процессе автоматизированного тестирования веб-приложений часто возникает необходимость работать с несколькими окнами или вкладками браузера. Protractor предоставляет средства для управления этими объектами через WebDriver API, позволяя переключаться между окнами, выполнять действия в нужном контексте и возвращаться к исходному состоянию.
В Protractor каждое окно или вкладка идентифицируется с помощью
window handle — уникального идентификатора,
возвращаемого методом getAllWindowHandles(). Основные
операции включают:
browser.getAllWindowHandles().then(function(handles) {
console.log(handles);
});
handles — массив строк, каждая из которых соответствует
одному окну или вкладке. Порядок элементов соответствует порядку
открытия окон, но на практике лучше явно проверять нужный handle.
browser.switchTo().window(handles[1]);
После выполнения этого кода все последующие команды будут выполняться в контексте выбранного окна.
browser.close();
После закрытия окна необходимо явно переключиться на другое окно, иначе дальнейшие команды приведут к ошибке.
// Открытие страницы и инициирование новой вкладки
browser.get('https://example.com');
element(by.id('openNewTab')).click();
// Получение всех окон
browser.getAllWindowHandles().then(function(handles) {
let originalWindow = handles[0];
let newWindow = handles[1];
// Переключение на новую вкладку
browser.switchTo().window(newWindow);
browser.getTitle().then(title => console.log('Title новой вкладки:', title));
// Выполнение действий на новой вкладке
element(by.css('.some-button')).click();
// Возврат к исходной вкладке
browser.switchTo().window(originalWindow);
});
В этом примере демонстрируется стандартный сценарий: сохранение идентификаторов окон, переключение на целевую вкладку, выполнение действий и возврат к исходной вкладке.
Protractor основан на промисах, поэтому при работе с окнами необходимо учитывать асинхронность. Часто требуется использовать ожидания, чтобы убедиться, что новая вкладка полностью загружена:
let EC = protractor.ExpectedConditions;
browser.getAllWindowHandles().then(function(handles) {
let newWindow = handles[1];
browser.switchTo().window(newWindow);
let elementToWaitFor = element(by.css('.loaded-element'));
browser.wait(EC.presenceOf(elementToWaitFor), 5000);
});
Использование ExpectedConditions гарантирует, что
действия будут выполняться только после полной готовности элементов на
странице.
Для сложных сценариев с большим количеством окон рекомендуется создавать утилиты:
function switchToWindowByTitle(title) {
return browser.getAllWindowHandles().then(function(handles) {
let found = false;
let promises = handles.map(function(handle) {
return browser.switchTo().window(handle).getTitle().then(function(t) {
if (t === title) {
found = true;
}
});
});
return Promise.all(promises).then(() => {
if (!found) throw new Error('Окно с таким заголовком не найдено');
});
});
}
Эта функция позволяет переключаться на окно по его заголовку, что удобно при тестировании динамически создаваемых вкладок.
browser.switchTo().window(handle) работает только с
открытыми окнами браузера. Закрытые окна нужно исключать из массива
handles.browser.navigate().back(), влияют только на текущее окно,
поэтому перед выполнением навигации важно убедиться, что переключение
выполнено корректно.ExpectedConditions) при
переходе на новые окна.browser.switchTo().frame() позволяет
работать с фреймами внутри отдельных вкладок.browser.getCurrentUrl() и
browser.getTitle() для проверки правильного контекста перед
взаимодействием с элементами.browser.getAllWindowHandles().then(handles => {
handles.forEach(handle => {
browser.switchTo().window(handle);
browser.close();
});
});
Этот подход полезен для очистки после завершения теста или восстановления исходного состояния браузера.
Переключение между окнами и вкладками является ключевым навыком при тестировании современных веб-приложений, особенно тех, которые активно используют модальные окна, всплывающие вкладки или внешние сервисы. Тщательное управление window handles и явные ожидания обеспечивают стабильность тестов и предотвращают ошибки взаимодействия с элементами.