使用Selenium2和FirefoxDriver关闭Liferay弹出窗口(在新的浏览器窗口中)?

时间:2011-03-08 20:46:59

标签: debugging firefox popup selenium-webdriver liferay

我正在尝试使用Selenium 2在Liferay门户服务器上自动化一些测试用例。许多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;

然而,当我完成模拟时,我需要关闭弹出窗口。根据WebDriver.close()的api,它将:

  

关闭当前窗口,退出   浏览器,如果它是最后一个窗口   目前正在开放。

如果我正确读取它,那么它应该关闭弹出窗口,而不是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 --------------

出于跟踪目的,以下是我在此问题上打开的错误:

http://code.google.com/p/selenium/issues/detail?id=1378

1 个答案:

答案 0 :(得分:1)

Hello Liferay弹出窗口不是一个可以关闭的firefix的单独弹出窗口。它是HTML的div元素,看起来像一个弹出窗口。为此,您需要通过JavaScript代码关闭它。

在一般情况下,每个弹出窗口都会有一个开发人员关闭按钮,你可以通过selenium IDE找到它的路径,并且可以通过webdriver模拟点击请求。

再次重复。 LiferayWindow弹出窗口不是基于浏览器的实际浏览器,它们只是幻觉相同。

我认为这不是错误。

修改 **

我认为这是由于javascript窗口弹出,但事实并非如此。