Как в Selenium работать с окном выбора?


(Eugene) #1

Всем, Добрый день!
Есть основная форма веб клиента, так же на этой форме много разных кнопок. При нажатии одной из кнопок открывается еще одно окно выбора товара, в котором нужно кликнуть по товару, после чего форма закроется и товар отобразится на главной форме.

Подскажите, пожалуйста, как обработать такую ситуацию с помощью Selenium используя язык Java?

У меня получается открыть второе окно, но кликнуть и выбрать товар никак...Видимо там как то фокус нужно установить на вторую форму?

public class test1 {
    private WebDriver driver;
    private String baseUrl;
    private StringBuffer verificationErrors = new StringBuffer();

    @Before
    public void setUp() throws Exception {
        driver =new InternetExplorerDriver();
        baseUrl = "http://localhost/test1";
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
    }

    @Test
    public void testSample() throws Exception {
        
         
            driver.get(baseUrl);
            
            driver.findElement(By.id("loginContainer_username")).clear();
            driver.findElement(By.id("loginContainer_username")).sendKeys("da");
            driver.findElement(By.id("loginContainer_password")).clear();
            driver.findElement(By.id("loginContainer_password")).sendKeys("da");
            driver.findElement(By.name("loginContainer$ctl05")).click();
            driver.findElement(By.id("tdImbButtonmenu_2")).click();
            driver.findElement(By.id("manageFilter_ctl00_filterItem_buttonEnter_popupButton")).click();
            driver.findElement(By.id("itemDataGrid_ctl03_ctl05")).click();
    }    

    @After
    public void tearDown() throws Exception {
      driver.quit();
      String verificationErrorString = verificationErrors.toString();
      if (!"".equals(verificationErrorString)) {
        fail(verificationErrorString);
      }
    }
}

#2

Вы должны использовать метод switchTo() для того, чтобы переключиться на второе окно.
Сначала сохраняется handle текущего окна.

String parentHandle = driver.getWindowHandle();

Затем осуществляется переход на другое окно:

driver.switchTo().window(childHandle);

Выполняются действия в этом окне, и если окно не закрыто, то:

driver.close();

Затем возврат на первое окно:

driver.switchTo().window(parentHandle);

Если childHandle - неизвестно, то в вашем случае с двумя окнами, можно сделать так:

  for(String childHandle : driver.getWindowHandles()){
      if (!childHandle.equals(parentHandle)){
          driver.switchTo().window(childHandle);
      }          
  }

Работа с несколькими окнами (вкладками) одновременно


(Eugene) #3

dt_astronaut, Вы можете на моем примере который выше показать как использовать Ваш код.
Я только начинаю изучать Selenium. Пока вот застрял на этой проблеме. Мне бы хоть глазком глянуть пример какой нить похожий.Спасибо.


#4

Достаточное количество примеров рассмотрено в документации по Selenium,
docs.seleniumhq.org - webdriver
также хорошее описание работы с несколькими окнами, посмотрите по ссылке из первого моего сообщения.

По поводу вашего теста.
Перед нажатием на кнопку выбора товара:

   String parentHandle = driver.getWindowHandle();

После нажатия на кнопку:

for(String childHandle : driver.getWindowHandles()){
  if (!childHandle.equals(parentHandle)){
      driver.switchTo().window(childHandle);
  }          
}

После нажатия на товар во втором окне:

driver.switchTo().window(parentHandle);

(Eugene) #5

Добрый день!
dt_astronaut, спасибо что помогаете, вроде сделал так как Вы сказали, но валится на ошибке:

 org.openqa.selenium.NoSuchWindowException: Unable to find element on closed window (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 16 milliseconds

public class Test1 {
    private WebDriver driver;
    private String baseUrl;
    private StringBuffer verificationErrors = new StringBuffer();
    
   

    @Before
    public void setUp() throws Exception {
        driver =new InternetExplorerDriver();
        baseUrl = "http://localhost/test1";
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
    }

    @Test
    public void testSample() throws Exception {
        
         
            driver.get(baseUrl);
            
            driver.findElement(By.id("loginContainer_username")).clear();
            driver.findElement(By.id("loginContainer_username")).sendKeys("da");
            driver.findElement(By.id("loginContainer_password")).clear();
            driver.findElement(By.id("loginContainer_password")).sendKeys("da");
            driver.findElement(By.name("loginContainer$ctl05")).click();
            driver.findElement(By.id("tdImbButtonmenu_2")).click();
            String parentHandle = driver.getWindowHandle();
            driver.findElement(By.id("manageFilter_ctl00_filterItem_buttonEnter_popupButton")).click();
            for(String childHandle : driver.getWindowHandles()){
                  if (!childHandle.equals(parentHandle)){
                      driver.switchTo().window(childHandle);
                  }          
                }
                 driver.findElement(By.id("itemDataGrid_ctl03_ctl05")).click();
                 driver.switchTo().window(parentHandle);
            
    }    

    @After
    public void tearDown() throws Exception {
      driver.quit();
      String verificationErrorString = verificationErrors.toString();
      if (!"".equals(verificationErrorString)) {
        fail(verificationErrorString);
      }
    }
}


(Александр Таранков) #6

Совсем не обязательно "всплывающее окно" будет отдельным окном браузера, проблема может быть совсем в другом


(Александр Таранков) #7

Без switchTO() по какой ошибке вылетает? Если рассматривать первоначальный вариант.
Искать элементы по их id получается далеко не всегда. Вполне возможно сейчас у тех же самых элементов другие id


(Eugene) #8

Без switchTO() вылетает по этой ошибке:

org.openqa.selenium.NoSuchElementException: Unable to find element with id == itemDataGrid_ctl03_ctl05 (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 30.27 seconds


(Eugene) #9

"Вполне возможно сейчас у тех же самых элементов другие id" - я проверил id остались прежними.


#10

Сам не часто сталкиваюсь с тестированием в IE, но поисковик подсказывает возможный путь решения это отключить "защищенный режим" настройках браузера.


(Eugene) #11

Сам не часто сталкиваюсь с тестированием в IE, но поисковик подсказывает
 возможный путь решения это отключить "защищенный режим" настройках 
браузера.

Защищенный режим отключен уже давно. В защищенном режиме вообще ничего не работает)) это правда.


#12

В какой момент происходит падение теста, возможно нужна задержка перед открытием новой формы?
Например:

Thread.sleep(5000);

(Eugene) #13

Ставлю задержку и все равно падает ошибка

 @Test
    public void testSample() throws Exception {
        
         
            driver.get(baseUrl);
            
            driver.findElement(By.id("loginContainer_username")).clear();
            driver.findElement(By.id("loginContainer_username")).sendKeys("da");
            driver.findElement(By.id("loginContainer_password")).clear();
            driver.findElement(By.id("loginContainer_password")).sendKeys("da");
            driver.findElement(By.name("loginContainer$ctl05")).click();
            driver.findElement(By.id("tdImbButtonmenu_2")).click();
           
            String parentHandle = driver.getWindowHandle();
            
            driver.findElement(By.id("manageFilter_ctl00_filterItem_buttonEnter_popupButton")).click();
            
            for(String childHandle : driver.getWindowHandles()){
                  if (!childHandle.equals(parentHandle)){
                      driver.switchTo().window(childHandle);
                  }          
                }

            Thread.sleep(5000);
            driver.findElement(By.id("itemDataGrid_ctl03_ctl05")).click();
            driver.switchTo().window(parentHandle);
            
               
            
    }    

Ошибка:

org.openqa.selenium.NoSuchElementException: Unable to find element with id == itemDataGrid_ctl03_ctl05 (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 30.16 seconds

#14

Задержка ставится до перехода на новую форму:

driver.findElement(By.id("manageFilter_ctl00_filterItem_buttonEnter_popupButton")).click();
        Thread.sleep(5000);           
        for(String childHandle : driver.getWindowHandles()){
              if (!childHandle.equals(parentHandle)){
                  driver.switchTo().window(childHandle);
                  break;
              }          
            }
driver.findElement(By.id("itemDataGrid_ctl03_ctl05")).click();

(Eugene) #15

dt_astronaut, Спасибо! Все заработало. Странно что без задержке теперь тоже работает...волшебство))

Нашел еще один вариант решения при котором тоже работает. Выкладываю может кому поможет:

@Test

    public void testSample() throws Exception {

        

        

            driver.get(baseUrl);

            

            driver.findElement(By.id("loginContainer_username")).clear();

            driver.findElement(By.id("loginContainer_username")).sendKeys("da");

            driver.findElement(By.id("loginContainer_password")).clear();

            driver.findElement(By.id("loginContainer_password")).sendKeys("da");

            driver.findElement(By.name("loginContainer$ctl05")).click();

            driver.findElement(By.id("tdImbButtonmenu_2")).click();

           

          

            

            driver.findElement(By.id("manageFilter_ctl00_filterItem_buttonEnter_popupButton")).click();

            Set<String> windows = driver.getWindowHandles();

            Iterator<String> it = windows.iterator();

            String mainWindow = (String) it.next();

            String popUp = (String) it.next();

            driver.switchTo().window(popUp);

            driver.findElement(By.id("itemDataGrid_ctl03_ctl05")).click();

            driver.close();

            driver.switchTo().window(mainWindow);

            

    }    


(Александр Таранков) #16

Ну то есть всё-таки это отдельное окно браузера. Хорошо, что всё заработало, но твоя реализация не будет стабильно работать по двум причинам:
1. Без ожидания окна, периодически будет падать из-за ненайденного popup
2. Поскольку Set не гарантирует последовательность, то периодически mainWindow и popUp будут содержать противоположные значения и элемент не будет найден

Поэтому в твоем случае можно сделать например так:
Handle главного окна mainWindow получать до клика, по которому открывается всплывающее окно. После клика ожидать (через WebDriverWait, а не Sleep ни в коем случае) когда getWindowHandles.Count вернет на 1 больше и после этого искать в Set элемент не равный mainWindow, это и будет popUp.

Таким образом ты обойдешь обе описанные выше проблемы и твои тесты будут работать стабильно