Обработка окон и вкладок браузера в Selenium PHP

от автора


Один из распространённых сценариев работы с веб-приложениями заключается в открывании нового окна (или вкладки) браузера после выполнения пользователем определённого действия. Многие веб-разработчики используют HTML-тэг __blank, приказывающий браузеру при нажатии на ссылку открыть новое окно (или вкладку, это зависит от выбранных пользователем настроек). Работа с окнами в Selenium при помощи PHP может использоваться для автоматизации взаимодействия с окнами, вкладками и даже всплывающими окнами браузера.

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

В этой статье мы подробно рассмотрим применение Selenium для автоматизации взаимодействия с браузерами, вкладками и всплывающими окнами. Для демонстрации работы с окнами в Selenium PHP мы воспользуемся PHPUnit — фреймворком юнит-тестирования для PHP.

Что такое дескриптор окна?

Дескриптор окна (window handle) — это уникальный идентификатор, основная задача которого заключается в хранении адресов всех окон. При создании экземпляра Selenium WebDriver окну назначается алфавитно-цифровой ID. Этот уникальный ID называется дескриптором окна — указателем на окно, позволяющим идентифицировать окно браузера.

Для каждого окна/вкладки/всплывающего окна дескриптор окна (или ID) уникален. Для переключения между окнами (или вкладками) Selenium WebDriver использует функции дескрипторов окон в Selenium PHP.

Уникальный ID сохраняется до закрытия сессии Selenium WebDriver (выполняемого через API WebDriver.Quit или WebDriver.Close). Функции дескрипторов окон используются для получения подробной информации о дескрипторах всех окон. Фундаментальные основы работы с окнами в Selenium остаются неизменными, вне зависимости от того, используете ли вы Selenium с PHP или Selenium с другими языками программирования (например, Python, Java, и т. п.).

Вот некоторые из самых распространённых сценариев, в которых приходится иметь дело с множественными окнами (или вкладками):

  • Формы, требующие выбора даты в новом открытом окне
  • Нажатия кнопок, открывающие новую вкладку (или окно)
  • Всплывающие окна, используемые для показа конечному пользователю каких-либо предложений; эту стратегию часто используют порталы с вакансиями
  • Работа с окнами, отображающими рекламу

Пример сценария, в котором нажатие на родительское (или базовое) окно открывает два «дочерних окна». Каждое из них имеет уникальный дескриптор окна, и этот дескриптор хранится, пока окна не будут уничтожены (т. е. закрыты). Общее количество окон становится равным трём (parent + child-1 + child-2). При нажатии кнопки/ссылки в «Child-1» и «Child-2», соответственно, откроется окно «Grand Child-1» и «Grand Child-2». После этого суммарно будет открыто пять окон, и каждое из них будет иметь уникальный дескриптор окна, который можно использовать для автоматизации операций с окном.

Команды для работы с окнами в Selenium с PHP

Selenium предоставляет различные методы для работы с несколькими окнами. Вы можете также изучить наше руководство по работе с несколькими окнами при помощи Selenium и Protractor. Ниже представлены самые часто используемые при тестировании Selenium PHP команды для переключения окон браузера и работы со всплывающими окнами.

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

SwitchTo Window

Команда SwitchTo используется для переключения фокуса на новое окно или вкладку браузера. Для переключения фокуса на новое окно в качестве аргумента команде передаётся дескриптор окна соответствующего окна браузера.

/* $wHandle - это дескриптор окна (или ID), на которое нужно выполнить переключение */ $this->webDriver->switchTo()->window($wHandle);   /* Переключение также можно выполнять получением количества окон при помощи getWindowHandles или getWindowHandle  */ $this->webDriver->switchTo()->window($HandleCount[win-number]);

getWindowHandle

Метод getWindowHandle в Selenium PHP возвращает Window ID (уникальный алфавитно-цифровой идентификатор окна) для текущего активного (или находящегося в фокусе) окна.

$wHandle = $this->webDriver->getWindowHandle();

В показанном выше примере $wHandle — это ID окна, полученный при помощи метода getWindowHandle.

getWindowHandles

Это важный метод для работы с окнами в Selenium с PHP. Метод getWindowHandles возвращает множество дескрипторов окон (и вкладок), открытых одним экземпляром драйвера, в том числе родительских и дочерних окон. Например, если операция «щелчок на кнопке» в родительском окне открывает новую вкладку, то метод getWindowHandles вернёт дескрипторы родительского и дочернего окна (например, вкладки). Если затем к множеству, возвращённому методом getWindowHandles, применить оператор sizeof, то он вернёт размер множества (в данном случае 2).

Аналогично, если открытая в родительском окне веб-страница открывает 8 всплывающих окон, то количество дескрипторов, полученных применением оператора sizeof для множества, возвращённого getWindowHandles, будет 9.

Каждое из окон будет иметь уникальный дескриптор окна (или идентификатор) для удобства идентификации окна.

/* В случае веб-страницы, открывающей новую вкладку, getWindowHandles возвращает массив, состоящий из двух дескрипторов окон (т. е. дескрипторов родительского и дочернего окон) */  $HandleCount = $this->webDriver->getWindowHandles();     /* Возвращает размер массива дескрипторов окон. В данном примере он будет равен 2 */  echo ("\n Total number of window handles are " . sizeof($HandleCount));     /* Печать дескриптора окна в родительском окне */  echo ("\n Window 0: " . $HandleCount[0]);     /* Печать дескриптора окна в дочернем окне */  echo ("\n Window 0: " . $HandleCount[1]);

Как работать с несколькими окнами, вкладками и всплывающими окнами в Selenium PHP

Мы продемонстрируем сценарии тестов работы с окнами в Selenium PHP при помощи PHPUnit в облачном Selenium Grid сервиса LambdaTest. Кросс-браузерное тестирование при помощи PHPUnit в облачном Selenium Grid помогает в тестировании на различных сочетаниях браузеров, платформ и эмуляторов устройств.

Для начала создадим аккаунт LambdaTest и обратим внимание, что user-name и access-key доступны на странице профиля. Тесты выполняются на сочетании Chrome 85.0 + Windows 10. Возможности браузера сгенерированы при помощи генератора возможностей LambdaTest.

Для установки фреймворка PHPUnit мы создаём для этого проекта файл composer.json:

{    "require":{       "php":">=7.1",       "phpunit/phpunit":"^9",       "phpunit/phpunit-selenium": "*",       "php-webdriver/webdriver":"1.8.0",       "symfony/symfony":"4.4",       "brianium/paratest": "dev-master"    } }

Введём команду composer require и дважды нажмём на кнопку «Enter», чтобы приступить к установке фреймворка PHPUnit. После завершения фреймворк PHPUnit (версии 9.3) будет установлен.

Файл composer.lock содержит информацию о зависимостях, а в папке vendor содержатся все зависимости.

Файл vendor/autoload.php будет использоваться в коде тестов, чтобы классы (и их методы), предоставленные этими библиотеками, можно было использовать в реализации.

Теперь настало время продемонстрировать различные сценарии работы с окнами в Selenium с PHP.

▍ Работа с несколькими окнами браузера в Selenium PHP

Для демонстрации работы с несколькими окнами в Selenium PHP мы используем следующий тестовый сценарий:

  1. Открываем страницу LambdaTest в браузере Chrome.
  2. Получаем дескриптор текущего окна в фокусе.
  3. Открываем страницу блога LambdaTest в новом окне при помощи HTML-атрибута __blank.
  4. Печатаем соответствующие дескрипторы окон.
  5. Переключаемся на окно, где открыт второй URL.
  6. Добавляем утверждение на случай, если заголовок окна не соответствует ожидаемому заголовку.
  7. Закрываем окно в фокусе.
  8. Переключаемся на первое окно и добавляем утверждение на случай, если заголовок окна не соответствует ожидаемому заголовку.
  9. Закрываем окно браузера.

❒ Реализация

<?php require 'vendor/autoload.php';   use PHPUnit\Framework\TestCase; use Facebook\WebDriver\Remote\DesiredCapabilities; use Facebook\WebDriver\Remote\RemoteWebDriver;   $GLOBALS['LT_USERNAME'] = "user-name"; # accessKey:  AccessKey можно сгенерировать в панели автоматизации или в разделе профиля $GLOBALS['LT_APPKEY'] = "access-key";   class WindowSwitchTest extends TestCase {   protected $webDriver;     public function build_browser_capabilities(){     /* $capabilities = DesiredCapabilities::chrome(); */     $capabilities = array(       "build" => "[PHP] Window Switching with Chrome on Windows 10",       "name" => "[PHP] Window Switching with Chrome on Windows 10",       "platform" => "Windows 10",       "browserName" => "Chrome",       "version" => "85.0"     );     return $capabilities;   }      public function setUp(): void   {     $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";     $capabilities = $this->build_browser_capabilities();     /* Скачать Selenium Server 3.141.59 с      https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar     */     /* $this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', $capabilities); */     $this->webDriver = RemoteWebDriver::create($url, $capabilities);   }     public function tearDown(): void   {     $this->webDriver->quit();   }   /*   * @test   */    public function test_SwitchToNewWindow()   {     $test_url_1 = "https://www.lambdatest.com";     $title_1 = "Most Powerful Cross Browser Testing Tool Online | LambdaTest";       $test_url_2 = "https://www.lambdatest.com/blog/";     $title_2 = "LambdaTest | A Cross Browser Testing Blog";       $this->webDriver->get($test_url_1);     $this->webDriver->manage()->window()->maximize();       $wHandle = $this->webDriver->getWindowHandle();     /* echo ("\n Primary Window Handle is " . $wHandle ); */     sleep(5);       /* Открываем второе окно */     /* $link = "window.open('https://www.lambdatest.com/blog/', '_blank', 'toolbar=yes,scrollbars=yes,resizable=yes,width=800,height=800')"; */     $link = "window.open('". $test_url_2 ."', '_blank', 'toolbar=yes,scrollbars=yes,resizable=yes,width=1200,height=1200')";     $this->webDriver->executeScript($link);     /* $this->webDriver->manage()->window()->maximize(); */       /* Фокус теперь на втором окне */     /* Количество дескрипторов будет равным двум */       $HandleCount = $this->webDriver->getWindowHandles();     echo ("\n Total number of window handles are " . sizeof($HandleCount));     echo ("\n Window 0: " . $HandleCount[0]);     echo ("\n Window 1: " . $HandleCount[1]);       sleep(10);       /* Создаём утверждение на случай, если количество окон не равно 2 */     $this->assertEquals(2, sizeof($HandleCount));       /* Проверяем соответствие заголовков окон */     $this->webDriver->switchTo()->window($HandleCount[1]);     $win_title_2 = $this->webDriver->getTitle();     echo ("\n Title of the window 1 is " . $win_title_2);     sleep(10);     $this->assertEquals($win_title_2, $title_2);       /* Закрываем новое открытое окно и возвращаемся к старому окну */     $this->webDriver->close();     sleep(10);       /* Возвращаемся к окну с дескриптором = 0 */     $this->webDriver->switchTo()->window($wHandle);     /* Проверяем, совпадают ли заголовки окон */     $win_title_1 = $this->webDriver->getTitle();     echo ("\n Title of the window 0 is " . $win_title_1);     $this->assertEquals($win_title_1, $title_1);     sleep(10);   } } ?>

❒ Разбор кода

Существенная часть реализации в этой части туториала по Selenium PHP остаётся той же, которая была использована для работы с окнами в Selenium с PHP.

1. При открытиитестового URL для получения дескрипторов открытых окон браузера используется метод getWindowHandles WebDriver.

public function test_SwitchToNewTab() {       $test_url = "http://automationpractice.com/index.php";       $title_1 = "My Store";       $title_2 = "Selenium Framework - YouTube";         ......................................       ......................................         $this->webDriver->get($test_url);       $this->webDriver->manage()->window()->maximize();       ......................................       ......................................       $HandleCount = $this->webDriver->getWindowHandles();

2. В конце страницы размещается веб-элемент с гиперссылкой на YouTube-канал сайта. При помощи метода executeScript, предоставленного JavaScriptExecutor, исполняется метод window.scrollTo JavaScript. Он выполняет переход к концу страницы.

$link = "window.scrollTo(0, document.body.scrollHeight)"; $this->webDriver->executeScript($link);

3. Для получения информации о требуемом веб-элементе мы используем расширение POM Builder для Chrome, чтобы получить информацию локатора (т. е. XPath).

Для получения информации о веб-элементе [with XPath – //a[contains(.,’Youtube’)] используется метод findElement класса WebDriverBy.

$browser_button = $this->webDriver->findElement(WebDriverBy::XPath("//a[contains(.,'Youtube')]"));

4. Для найденного веб-элемента вызывается метод click.

$browser_button->click();

5. Метод getWindowHandles возвращает алфавитно-цифровой массив (или множество), содержащий дескрипторы (или ID) текущих открытых окон (или вкладок) браузера. В нашем случае количество открытых окон будет равным 2.

Следовательно, после применения оператора sizeof к массиву (или множеству), возвращённому getWindowHandles, вернёт 2.

$HandleCount = $this->webDriver->getWindowHandles(); echo ("\n Total number of window handles are " . sizeof($HandleCount)); echo ("\n Window 0: " . $HandleCount[0]); echo ("\n Window 1: " . $HandleCount[1]);

6. Для переключения на второе окно (т. е. $HandleCount[1]) используется метод switchTo Selenium WebDriver. Если заголовок окна не соответствует ожидаемому заголовку, срабатывает утверждение.

$this->webDriver->switchTo()->window($HandleCount[1]); $win_title_2 = $this->webDriver->getTitle(); $this->assertEquals($win_title_2, $title_2);

7. Метод close закрывает окно в фокусе (т. е. вкладку, где открыт YouTube-канал).

$this->webDriver->close();

8. Выполняется переключение на родительское окно (т. е. $HandleCount[0]). Если заголовки не совпадают, срабатывает утверждение.

$this->webDriver->switchTo()->window($HandleCount[0]); $win_title_1 = $this->webDriver->getTitle(); $this->assertEquals($win_title_1, $title_1);

❒ Исполнение

Вот дескрипторы двух окон браузера, созданных при тестировании.

Ниже показан снэпшот исполнения автоматизированного теста Selenium:

Как видно из снэпшота, дескрипторы родительского окна и вкладки уникальны. Когда окно и вкладка открыты, размер массива дескрипторов окон равен 2.

Теперь, когда мы увидели реализацию и исполнение работы с окнами и несколькими вкладками в Selenium с PHP, давайте подробнее узнаем о работе с несколькими всплывающими окнами браузера.

▍ Работа с несколькими всплывающими окнами браузера в Selenium с PHP

Для демонстрации работы со всплывающими окнами браузера в Selenium PHP мы используем следующий тестовый сценарий:

  1. Откроем www.popuptest.com/popuptest1.html в браузере Chrome.
  2. Закроем все всплывающие окна в обратном хронологическом порядке.
  3. Проверим, соответствует ли заголовок родительского окна ожидаемому заголовку.

Если тот же тест выполняется в локальном Selenium Grid, то нужно убедиться, что для Google Chrome включены всплывающие окна. Для включения всплывающих окон для Chrome на локальной машине перейдите по адресу chrome://settings/ -> Privacy and security -> Site Settings -> Pop-ups and redirects. Отключите опцию Block для www.popuptest.com:80.

❒ Реализация

<?php require 'vendor/autoload.php';   use PHPUnit\Framework\TestCase; use Facebook\WebDriver\Remote\DesiredCapabilities; use Facebook\WebDriver\Remote\RemoteWebDriver; use Facebook\WebDriver\WebDriverBy;   $GLOBALS['LT_USERNAME'] = "user-name"; # accessKey:  AccessKey можно сгенерировать в панели автоматизации или в разделе профиля $GLOBALS['LT_APPKEY'] = "access-key";   class PopUpTest extends TestCase {   protected $webDriver;     public function build_browser_capabilities(){     /* $capabilities = DesiredCapabilities::chrome(); */     $capabilities = array(       "build" => "[PHP] Pop Up Testing with Chrome on Windows 10",       "name" => "[PHP] Pop Up Testing with Chrome on Windows 10",       "platform" => "Windows 10",       "browserName" => "Chrome",       "version" => "85.0"     );     return $capabilities;   }      public function setUp(): void   {     $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";     $capabilities = $this->build_browser_capabilities();     /* Скачать Selenium Server 3.141.59 с      https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar     */     /* $this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', $capabilities); */     $this->webDriver = RemoteWebDriver::create($url, $capabilities);   }     public function tearDown(): void   {     $this->webDriver->quit();   }   /*   * @test   */    public function test_SwitchToNewWindow()   {       $test_url = "http://www.popuptest.com/popuptest1.html";       $title = "PopupTest 1 - test your popup killer software";         $this->webDriver->get($test_url);       sleep(5);         /* Это откроет основное окно и шесть всплывающих окон */       /* После загрузки страницы общее количество страниц будет равным 7 */       $HandleCount = $this->webDriver->getWindowHandles();       /* Это ID родительского окна */       $mainHandle = $HandleCount[0];       echo ("\n Total number of window handles are " . sizeof($HandleCount));       echo ("\n Window 0: " . $HandleCount[0]);         $win_title = $this->webDriver->getTitle();       echo ("\n Title of the parent window is " . $win_title);         foreach( $HandleCount as $handle)       {         if($handle != $mainHandle)         {           echo ("\n Window handle of the current window: " . $handle);           $this->webDriver->switchTo()->window($handle);           echo ("\n Title of the current window: " . $this->webDriver->getTitle());           /* Закрываем всплывающее окно и возвращаемся к старому окну */           $this->webDriver->close();           sleep(2);         }       }       $this->webDriver->switchTo()->window($mainHandle);       $this->webDriver->manage()->window()->maximize();       sleep(5);       $curr_window_title = $this->webDriver->getTitle();       echo ("\n\n Title of the only left window: " . $curr_window_title);       $this->assertEquals($curr_window_title, $title);       sleep(5);   } } ?>

❒ Разбор кода

1. Так как для тестирования используется Selenium Grid на LambdaTest, user-name и access key хранятся в глобальных переменных. Того же результата можно получить, перейдя на страницу профиля на LambdaTest.

$GLOBALS['LT_USERNAME'] = "user-name"; # accessKey:  AccessKey можно сгенерировать в панели автоматизации или в разделе профиля $GLOBALS['LT_APPKEY'] = "access-key";

2. При помощи LambdaTest Capabilities Generator генерируются возможности браузера.

$capabilities = array(       "build" => "[PHP] Window Switching with Chrome on Windows 10",       "name" => "[PHP] Window Switching with Chrome on Windows 10",       "platform" => "Windows 10",       "browserName" => "Chrome",       "version" => "85.0"     );

3. Для доступа к Selenium Grid on LambdaTest (@hub.lambdatest.com/wd/hub) используется сочетание глобальных переменных, в которых хранятся user-name и access-key. Метод create в классе RemoteWebDriver получает в качестве первого параметра URL Selenium Grid, а в качестве второго — возможности браузера.

$url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub"; $capabilities = $this->build_browser_capabilities(); $this->webDriver = RemoteWebDriver::create($url, $capabilities);

4. В тестовом методе test_SwitchToNewWindow открывается тестовый URL https://www.lambdatest.com и используется предоставляемый Selenium WebDriver метод getWindowHandle для получения дескриптора текущего окна.

public function test_SwitchToNewWindow() {      $test_url_1 = "https://www.lambdatest.com";      $title_1 = "Most Powerful Cross Browser Testing Tool Online | LambdaTest";      ...............................................      ...............................................      $this->webDriver->get($test_url_1);      $wHandle = $this->webDriver->getWindowHandle();      ............................................... }

5. Для открытия нового вторичного окна браузера используется метод JavaScript window.open. Методу также передаются ширина и высота окна. Для исполнения сформированного кода JavaScript в контексте текущего открытого окна используется метод executeScript, предоставляемый JavaScriptExecutor в Selenium PHP.

$link = "window.open('". $test_url_2 ."', '_blank', 'toolbar=yes,scrollbars=yes,resizable=yes,width=1200,height=1200')"; $this->webDriver->executeScript($link);

6. Метод getWindowHandles возвращает алфавитно-цифровой массив, содержащий ID (или дескриптор) текущих открытых окон. Оператор sizeof, применяемый к массиву, возвращённому getWindowHandles, возвращает количество открытых окон (т. е. в нашем случае 2).

$HandleCount = $this->webDriver->getWindowHandles(); echo ("\n Total number of window handles are " . sizeof($HandleCount));

7. При помощи утверждения проверяем, не меньше ли двух общее количество дескрипторов окон.

$this->assertEquals(2, sizeof($HandleCount));

8. Для переключения на второе окно (которое было открыто при помощи метода window.open) используется метод switchTo Selenium WebDriver. Если заголовок окна не соответствует ожидаемому заголовку, срабатывает утверждение.

$this->webDriver->switchTo()->window($HandleCount[1]); $win_title_2 = $this->webDriver->getTitle(); $this->assertEquals($win_title_2, $title_2);

9. Текущее окно закрывается при помощи метода Close().

$this->webDriver->close();

10. Теперь количество дескрипторов окон будет равно одному (так как открыто только родительское окно). Для переключения на родительское окно используется метод switchTo, которому в качестве параметра передаётся дескриптор этого окна (т. е. $wHandle). Если заголовок окна не соответствует ожидаемому заголовку, срабатывает утверждение.

$test_url_1 = "https://www.lambdatest.com"; $title_1 = "Most Powerful Cross Browser Testing Tool Online | LambdaTest"; ........................................... $this->webDriver->get($test_url_1); ........................................... ........................................... $wHandle = $this->webDriver->getWindowHandle();   /* Возвращаемся к окну с дескриптором = 0 */ $this->webDriver->switchTo()->window($wHandle); /* Проверяем, совпадают ли заголовки окон */ $win_title_1 = $this->webDriver->getTitle(); $this->assertEquals($win_title_1, $title_1);

11. Как часть tearDown вызывается метод quit Selenium WebDriver на PHP.

public function tearDown(): void {     $this->webDriver->quit(); }

❒ Исполнение

На скриншоте ниже отмечены дескрипторы всплывающих окон:

После закрытия всех всплывающих окон остаётся только родительское окно, которое закрывается после исполнения теста.

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

Заключение

Окна браузера, в том числе вкладки и всплывающие окна, идентифицируются по дескрипторам окон. Эти дескрипторы используются в качестве ID окон, они уникальны для каждого окна браузера. В этом туториале по Selenium WebDriver PHP мы узнали, как происходит работа с окнами в Selenium с PHP при помощи таких методов, как switchTo, getWindowHandle и getWindowHandles. Эти методы играют важную роль в работе с окнами для автоматизации тестов Selenium с PHP.


ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/679048/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *