Я пытаюсь автоматизировать некоторые тестовые случаи на сервере портала Liferay с помощью Selenium 2. Многие действия Liferay открывают новое всплывающее окно браузера (например, олицетворение пользователя). Вот пример ссылки (обратите внимание на target="_blank"
):
<a title="(Opens New Window)" target="_blank" id="_125_xafr"
href="/web/guest?doAsUserId=xBRUWI85MvM%3D" class="taglib-icon aui-focus"
tabindex="0" role="menuitem">
<img alt="" src="/html/themes/control_panel/images/common/impersonate_user.png" class="icon">
Impersonate User
<span class="opens-new-window-accessible">(Opens New Window)</span>
</a>
Переключиться на контекст всплывающего окна довольно просто:
String currentWindowHandle = driver.getWindowHandle();
if ( log.isDebugEnabled() ) log.debug( "currentWindowHandle='" + currentWindowHandle + "'" );
for ( String windowHandle : driver.getWindowHandles() ) {
if ( ! windowHandle.equals( currentWindowHandle ) ) {
boolean impersonationSuccess = false;
if ( log.isDebugEnabled() ) log.debug( "checking '" + windowHandle + "' impersonation alert notice" );
driver.switchTo().window( windowHandle );
try {
// wait for body to ensure page has loaded before checking to see if its impersonation page.
WebElement body = waitForElement( driver, By.xpath( "//body" ) );
WebElement noticeMessage = body.findElement(
By.xpath( "div[@class='popup-alert-notice' and a='Be yourself again.']/span[@class='notice-message']" ) );
if ( noticeMessage.getText().indexOf( "You are impersonating " + user.firstName + " " + user.lastName ) >= 0 ) {
impersonationSuccess = true;
break;
}
}
catch ( NoSuchElementException e ) {
if ( log.isDebugEnabled() ) {
log.debug( "did not find impersonation window '" + windowHandle + "'" );
}
}
finally {
if ( ! impersonationSuccess ) {
driver.switchTo().window( currentWindowHandle );
}
}
}
}
return currentWindowHandle;
Однако, когда я закончу с олицетворением, мне нужно закрыть всплывающее окно. Согласно API для WebDriver.close(), это будет:
Закрыть текущее окно, выйдя из браузера, если это последнее открытое окно.
Если я правильно это понимаю, то он должен просто закрыть всплывающее окно, а не экземпляр Firefox (пока у меня открыто другое окно, что я и делаю, потому что это было просто всплывающее окно). Однако, когда я вызываю close из контекста всплывающего окна, он всегда терпит неудачу:
org.openqa.selenium.WebDriverException:
org.apache.http.conn.HttpHostConnectException:
Connection to http://localhost:7055 refused
Я нашел несколько ссылок на то, что это ошибка в FirefoxDriver. У кого-нибудь есть предложения или, возможно, обходной путь? Думаю, я мог бы оставить всплывающее окно открытым до тех пор, пока не будет завершен весь тестовый пример, но с учетом количества операций, которые вызывают всплывающие окна в моем наборе тестов, это может быстро стать невыполнимым.
------------- РЕДАКТИРОВАТЬ --------------
Крайне упрощенный тестовый пример:
@Test
public void testPopupClose() {
WebDriver driver = new FirefoxDriver();
driver.get( "http://lucastheisen.com/test/lucas_test_page.html" );
driver.findElement( By.id( "popup_link" ) ).click();
String mainWindowHandle = driver.getWindowHandle();
System.out.println( "currentWindowHandle='" + mainWindowHandle + "'" );
boolean foundPopup = false;
for ( String windowHandle : driver.getWindowHandles() ) {
if ( !windowHandle.equals( mainWindowHandle ) ) {
System.out.println( "checking '" + windowHandle + "' for taunt" );
driver.switchTo().window( windowHandle );
try {
driver.findElement( By.id( "taunt" ) );
foundPopup = true;
break;
}
catch ( NoSuchElementException e ) {
System.out.println( "'" + windowHandle + "' is not taunt window" );
}
finally {
if ( !foundPopup ) {
driver.switchTo().window( mainWindowHandle );
}
}
}
}
if ( foundPopup ) {
System.out.println( "found my popup, now try to close it..." );
driver.close();
}
System.out.println( "now try to continue working in original window" );
driver.switchTo().window( mainWindowHandle );
driver.findElement( By.id( "popup_link" ) );
driver.close();
assertTrue( true );
}
Кажется, это указывает на то, что на самом деле это не проблема с FirefoxDriver. Это показывает, что простое создание всплывающего окна, переключение на него, затем его закрытие, а затем возобновление работы в главном окне не приводит к сбою firefox. Это означает, что причина намного сложнее, и я не могу придумать способ создать простой тестовый пример. Мой настоящий код — это, по сути, фреймворк для работы с Liferay. Он предназначен для использования в качестве базового класса для всех моих тестовых примеров, предоставляющих служебные методы, такие как impersonateUser (пользователь LiferayUser). Я опубликую свой код здесь, но очень сомневаюсь, что кто-то захочет приложить усилия для его изучения. На данный момент у меня есть обходной путь: я могу закрыть исходное окно и просто продолжить работу во всплывающем окне оттуда. Если я придумаю упрощенный тестовый пример, чтобы продемонстрировать эту проблему, я снова отредактирую этот пост.
------------- РЕДАКТИРОВАТЬ 2 --------------
Теперь я думаю, что это как-то связано с отладчиком. Я использую eclipse, и если я отлаживаю и просматриваю код между close() и switchTo(), он постоянно терпит неудачу. Вы должны быть в состоянии воспроизвести, вставив точку останова в моем упрощенном тестовом примере выше в этой строке:
System.out.println( "now try to continue working in original window" );
Когда код останавливается для этой точки останова, вы получаете сообщение об ошибке... Не знаю, что с этим делать, насколько возможно, зарегистрировать ошибку. Какие-либо предложения?
------------- РЕДАКТИРОВАТЬ 3 --------------
В целях отслеживания, вот ошибка, которую я открыл по этой проблеме: