处理多个框架时如何创建静态页面内容?



我最近才开始测试一个新应用程序,并且已经开始为该应用程序的页面对象建模。

我发现这个应用程序使用"框架",因为在 DOM 中包含 2 个或多个 HTML 元素标签。默认情况下,GEB 似乎看不到在嵌套 HTML 元素下找到的元素。

我查看了GEB的书,发现您可以使用withFrame方法来指定元素属于哪个框架。 当我这样做时,GEB 确实看到了有问题的元素。

我遇到的问题是,我不希望编写脚本的人(使用我的页面对象(不必担心特定元素来自哪个框架。我想知道是否有办法从静态内容中指定元素所属的框架。否则,脚本编写者不仅需要知道某个元素不在框架中,而且还必须检查并查看该元素属于哪个框架。

以下是我到目前为止尝试过的一些事情:

SomePage extends Page{
static content=  {
myNavigator {withFrame("header", {$(By.xpath("my xpath"))})}
}
}

如果我尝试使用myNavigator我会得到过时的元素引用异常(也许我做对了所有事情,还有另一个原因?

我也尝试过这个也会导致过时的元素:

SomePage extends Page{
static content=  {
myNavigator {$(By.xpath("my xpath"))}
}
Navigator getMyNavigator(){
return withFrame("header", {myNavigator})
}
}

我有点明白为什么会发生这种情况,在执行 withFrame 列后,我假设该闭包中引用的任何元素都会过时。

基本上,我想要它,以便编剧需要做的就是说这样的话:

at MyPage
waitFor {myNavigator}.click()

我想避免这样做:

at MyPage
withFrame("header", {waitFor {myNavigator}.click()}

如何在页面对象端进行设置以获得所需的结果?(模块可能是一个选项吗?

编辑:我也尝试使用略有不同的语法定义静态内容,但仍然得到相同的陈旧元素引用:

myNavigator{ withFrame("header") { $(By.xpath("//td/a"))} } 

编辑2:我也尝试实现一些类似于这篇文章的东西:https://groups.google.com/forum/#!topic/geb-user/uxgcgWgmGYE

我的静态内容现在如下所示:

static content = {
bannerMod {withFrame("banner") {module BannerModule}}
mainViewMod {withFrame("FrameworkMain") {module MainViewModule}}
sideMenuMod {withFrame("contents") {module SideMenuModule}}
}

我将所有元素移动到各自的模块中,但现在当我尝试引用它们时,我仍然收到过时的元素引用异常。 例如,它被抛出在以下代码行上:

if(!mainViewMod.table.displayed){

陈述stale element reference: element is not attached to the page document

正如您已经注意到的那样,您正在StaleElementExcpetions,因为您正在尝试访问在切换到根文档上下文后在框架上下文中获取引用的元素,也就是说,您正在尝试在withFrame()调用之外访问这些元素。

我可以看到您的问题的两种解决方案。

第一种是不使用withFrame(),而是通过driver.switchTo().frame(..)调用手动管理帧上下文。不幸的是,这意味着在使用页面对象时,您将无法实现不必知道哪些元素来自哪些框架的目标。

另一种方法是在页面中编写一个方法,该方法将采用闭包并处理切换到正确的框架。像这样:

class PageWithFrames extends Page {
public <T> T mainView(@DelegatesTo(value = MainViewPage, strategy = Closure.DELEGATE_FIRST) Closure<T> mainViewAction) {
withFrame('FrameworkMain', MainViewPage, mainViewAction)
}
}
class MainViewPage extends Page {
static content = {
table { ... }
}
}

然后它可以像这样使用:

at PageWithFrames
if (mainView { table.displayed }) {
....
}

请注意,由于@DelegatesTo注释,IntelliJ 将知道您在通话MainViewPagemainView {}并且您将获得自动完成。请记住,无论您做什么,都不应该从mainView {}调用中返回页面元素,因为您将开始获得StaleElementException

您可能还会发现"一次切换页面和框架"手册部分很有趣。

最新更新