我正在使用Selenium Page工厂,我希望对它进行某些扩展,但不能密封,所以我想编写自己的自定义逻辑。
问题: PageFactory.InitElements如何工作,以便所有属性在使用时加载它们的值,而不是在调用此方法时加载它们。
所以,用一个例子来解释它
//// Button on page load
[FindsBy(How = How.CssSelector, Using = "#lst-ib")]
public IWebElement Btn;
//// Button redirecting to Page 2
[FindsBy(How = How.CssSelector, Using = "#lst-ib")]
public IWebElement LinkBtn;
////Button on second page
[FindsBy(How=How.CssSelector, Using = "#rso > div:nth-child(1) > div > div:nth-child(1) > div > div > h3 > a")]
public IWebElement NewBtn;
因此,他们的页面工厂的优点是所有元素都被加载但是在使用时它们会转换为webelements,因为如果所有属性都在initilisation上分配了值,NewBtn Property将始终失败,因为它是第2页。
那么,他们可能会使用什么概念来初始化属性,以便在使用时分配它们而不是在运行时分配,任何虚拟代码都会很棒并且理解
先谢谢
答案 0 :(得分:1)
我完全没有C#的经验,但我检查了C#selenium实现的源代码,看起来与Java代码完全相同。
PageFactory.cs - 此类提供了元素初始化方式的总体框架。
initElements()
获取pageobject
中的所有字段。对于每个字段,获取它们的注释。然后它为每个字段创建Proxy
。
然后它存储要使用的实际定位器。对findElement or findElements
的实际调用位于代理的Invoke
方法内。
这全部由两个类 - DefaultPageObjectMemberDecorator.cs和DefaultElementLocator.cs处理。有两个代理处理调用 - WebElementProxy.cs和WebElementListProxy.cs
因此,您要编写的自定义逻辑可以通过创建实现适当接口的新类来完成。然后将这些新类传递到PageFactory类的相应initElement()
方法。
要详细了解,请查看Decorate()
类的DefaultPageObjectMemberDecorator.cs
方法。
答案 1 :(得分:0)
创建页面对象时,"页面对象逻辑" ( IMO,根据我的经验和迄今为止我从c#和selenium 所理解的内容),它期望元素映射中提到的所有元素都存在于DOM中。
如果您的NewBtn存在于圆顶但是隐藏(并且在导航到第二页时变得可见,基本上当页面没有刷新并且有一些ajax)时,那么元素映射赢了&处理元素时遇到任何问题。您只需要确保元素在IF语句中可见或添加等待(以查看您是否确实在第二页)。
如果在导航到第二页时页面被刷新,则只需使用new MyPageObject()
重新初始化页面对象,以便再次映射所有元素,以避免StaleElement和/或ElementNotFound异常等。