2. Робота с несколькими окнами
Почти вся автоматизация веб-приложений привязана к одной активной вкладке. Тоесть при вызове driver.get(“some url”); откроется вкладка браузера с адресом “some url”. Но что если например у нас web приложение, которое состоит из 2-ох взаимно зависимых “view-шок”, либо же нам нужно по быстрому поменять что то в web интерфейсе сервера или админ-части сайта и проверить эти изменения в одном тесте. Другими словами, конструкция манипуляций выглядит следующим образом:
1. Start from “some url” in first browser tab
2. Make some changes (automation test steps)
3. Open new tab in the same browser with new url (server url, site administration part, etc)
4. Make some changes in new tab (automation test steps)
5. Return to first tab
6. Repeat steps from 2 to 6 till the end of test.
По ходу действий выше описанного алгоритма нас интересуют такие структурные этапы:
1. создание новой вкладки браузера и открытие в ней новой ссылки тем же webdriver-ом что используется в тестах
2. навигация между вкладками (туда и обратно) и фокусировка на необходимой вкладке
И так по пунктам разберем что нам нужно знать и реализовать.
Для первого этапа:
а. Объект данного класса WebWindow эмулирует создание новой вкладки браузера.
Для детального изучения данной реализации присутствуют комментарии в коде.
package Core;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import java.util.Set;
/**
* Creates and Handles a New window *
*/
public class WebWindow {
private WebDriver driver = PageLoader.GetInstance(); // сюда передаем тот же веб драйвер который вызываеться в самих тестах
private String handle;
private String name;
private String parentHandle;
private static int instanceCount = 0;
/**
* Creates a new window for given web driver
* @param parent WebDriver instance
* @param url Initial url to load
* @return new WebWindow
*/
public WebWindow(WebDriver parent, String url) {
this.driver = parent;
parentHandle = parent.getWindowHandle();
name = createUniqueName();
handle = createWindow(url);
//Switch to that window and load the url to wait
switchToWindow().get(url);
}
public String getWindowHandle(){
return handle;
}
public String getParentHandle(){
return parentHandle;
}
public void close(){
switchToWindow().close();
handle = "";
//Switch back to the parent window
driver.switchTo().window(parentHandle);
}
private static String createUniqueName() {
return "a_Web_Window_" + instanceCount++;
}
public WebDriver switchToWindow(){
checkForClosed();
return driver.switchTo().window(handle);
}
public WebDriver switchToParent(){
checkForClosed();
return driver.switchTo().window(parentHandle);
}
private String createWindow(String url){
//Record old handles
Set<String> oldHandles = driver.getWindowHandles();
parentHandle = driver.getWindowHandle();
//Inject an anchor element
((JavascriptExecutor) driver).
executeScript(
injectAnchorTag(name,url)
);
//Click on the anchor element
driver.findElement(By.id(name)).click();
handle = getNewHandle(oldHandles);
return handle;
}
private String getNewHandle(Set<String> oldHandles){
Set<String> newHandles = driver.getWindowHandles();
newHandles.removeAll(oldHandles);
//Find the new window
for(String handle : newHandles )
return handle;
return null;
}
private void checkForClosed(){
if ( handle == null || handle.equals("") )
throw new WebDriverException("Web Window closed or not initialized");
}
private String injectAnchorTag(String id, String url){
return String.format( "var anchorTag = document.createElement('a'); " +
"anchorTag.appendChild(document.createTextNode('nwh'));" +
"anchorTag.setAttribute('id', '%s');" +
"anchorTag.setAttribute('href', '%s');" +
"anchorTag.setAttribute('target', '_blank');" +
"anchorTag.setAttribute('style', 'display:block;');" +
"document.getElementsByTagName('body')[0].appendChild(anchorTag);",
id, url
);
}
}
б. Данному подходу есть имя Script Injection technique. Использование инъекции anchor tag (with target = _blank …) дает возможность открытия новой вкладки (окна).
Пример использования запишется так:
WebWindow ww = new WebWindow(driver, "http://google.com");
// Откроет новую вкладку окно с url - “http://google.com”.
Для этапа 2:
1. Создадим переменную public String handleHost;
В аннотации @Before к нашим тестам укажем следующее:
@Before
public void setup(){
…
handleHost = driver.getWindowHandle(); //handle first Window
…
}
Другими словами в нее запишем первую вкладку (окно) с которой стартуют тесты.
2. Напишем методы: создание новой вкладки, переключение с стартовой вкладки(окна) на созданную и обратно.
protected void CreateNewTab(){
try{
WebWindow tab2 = new WebWindow(driver, “url”); // “url” - ссылка новой вкладки
}
catch (Exception e){
System.err.println("Couldn't load second page");
}
}
protected void SwitchFromSecondTabToFirst(){
try{
driver.switchTo().window(handleHost);
driver.switchTo().activeElement();
}
catch (Exception e){
System.err.println("Couldn't get back to first page");
}
}
protected void SwitchFromFirstPageToSecond(){
try{
for (String handle : driver.getWindowHandles()){
if (handle!=handleHost){
driver.switchTo().window(handle);
driver.switchTo().activeElement();
} // смотрим все вкладки (а их две всего); если і-тая вкладка не равна первой handleHost (инициализированой в пункте (а), тогда переключаемся на нее).
}
}
catch (Exception e){
System.err.println("Couldn't get to second page");
}
}