始终等待页面加载到PageObjects上 [英] Always wait for the page to load on PageObjects

查看:91
本文介绍了始终等待页面加载到PageObjects上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,当出现问题时,我只是在创建一个简单的selenium/JBehave代码. 我将首先发布简化的代码,然后在以后解释我的问题.

So, I was just creating a simple selenium/JBehave code when a question appeared. I'll first post the code simplified and then explain what is my question later.

因此,这里有一个简单的AbstractClass,它将在我的PageObjects上继承.此类仅包含等待页面上某些元素加载的方法.您可以在PageObject类中看到Im的使用方式(在那里添加了注释).

So here we have a simple AbstractClass that will be inherited on my PageObjects. This class only contains a method to wait for certain elements on the page to be loaded. You can see how Im using it in the PageObject class (added a comment there).

AbstractPage.java

public abstract class AbstractPage {
    public void waitPageLoad() {
        WebDriverWait wait = new WebDriverWait(webDriverProvider.get(), 30);        
        wait.until(ExpectedConditions.visibilityOfAllElements(elementsToWait()));
    }

    protected List<WebElement> elementsToWait() {
        return null;
    }
}

PageObject.java

public class PageObject extends AbstractPage{
    @FindBy(id = "webElement1")
    private WebElement webElement1;

    @FindBy(id = "webElement2")
    private WebElement webElement2;

    public void clickWebElement1() {
        webElement1.click();
    }

    public void sendKeysWebElement2(String strKeys) {
        webElement2.sendKeys(strKeys);
    }

    //Note how im using the elementsToWait here
    @Override
    protected List<WebElement> elementsToWait() {
        return Arrays.asList(webElement1, webElement2);
    }
}

现在在我的步骤中,如果我要等待页面首先加载然后执行所需的操作,则需要在步骤之一中从我的抽象类中调用"waitPageLoad()"方法(或者可以肯定所有这些).

Now on my steps, if I want to wait for the page to load first and then do the actions that i want, I'd need to call the 'waitPageLoad()' method from my abstract class inside one of the steps (or all of them to be sure).

PageObjectSteps.java

@Component
public class PageObjectSteps {

    private PageObject pageObject;

    @When("User wants to click on webElement1")
    public void accountToDeposit () {
        pageObject.waitPageLoad(); //Calling here just as an example
        pageObject.clickWebElement1();
    }

    @When("User wants to type on webElement2 '$strType'")
    public void ammountToDeposit(@Named("strType") String strType) {
        pageObject.sendKeysWebElement2(strType);
    }
}

现在我的问题是:

是否有一种方法可以在每次使用我的pageObject时都调用 waitPageLoad(),但没有在步骤中调用该方法?

Is there a way that I could call the waitPageLoad() everytime that my pageObject is used but WITHOUT calling the method on the steps?

例如,根据需要等待的时间,每个pageObject都有一个不同的 waitPageLoad(). 在此示例中,我将等待webElement1和webElement2可见.

For example, I'd have a different waitPageLoad() for each pageObject, depending on what I'd need to wait for. On this example I'd wait for the webElement1 and webElement2 to be visible.

硒是否有类似的东西: @AlwaysWait ,在这里我可以在方法之前使用它,并且每次使用页面对象时都会再次调用它(再次,无需在步骤中调用它)?还是一种使每次使用页面对象都被调用的方法的符号?

Does selenium have something like: @AlwaysWait where I could use before a method and it would be called everytime the page object is used(again, WITHOUT calling it in the steps)? Or a notation that would make a method to be called everytime the page object is used?

示例:

@AlwaysWait
public void waitPageObjectLoad() {
    WebDriverWait wait = new WebDriverWait(webDriverProvider.get(), 30);        
    wait.until(ExpectedConditions.visibilityOfAllElements(webElement1, webElement2));
}

希望我能使自己容易理解, 预先感谢.

Hopefully I made myself understandable, Thanks in advance.

PS:到处问,我知道您可以使用Java Reflections框架来实现它,但是我想知道您是否只能使用Selenium.

PS: Asking around, I know that somehow you can use java reflections framework to do it, but I was wondering if you could do it with selenium only.

推荐答案

在这里您将学习到多态性和代理模式.

创建一个新的具体类,以实现名为LazyWebDriverWebDriver接口.创建另外两个类以延迟加载Web元素:LazyWebElement和LazyWebElementList.

Create a new concrete class implementing the WebDriver interface called LazyWebDriver. Create two other classes to lazily load web elements: LazyWebElement and LazyWebElementList.

LazyWebDriver中的方法应返回LazyWebElement或LazyWebElementList对象,但这些方法的返回值应为WebElement或List.

Methods in the LazyWebDriver should return LazyWebElement or LazyWebElementList objects, but the return values for those methods should be WebElement or List.

现在,您就像使用其他任何Web驱动程序一样,就可以使用LazyWebDriver.使用标准的WebDriver界面查找元素将始终等待一定的秒数:

Now you just use the LazyWebDriver as if it were any other web driver. Finding elements using the standard WebDriver interface will always wait a certain number of seconds:

WebDriver driver = new ChromeDriver();
int secondsToWait = 15;
WebDriver lazyDriver = new LazyWebDriver(driver, secondsToWait);

// findElement(...) returns immediately
WebElement element = lazyDriver.findElement(By.id("foo"));

// Implicitly waits up to 15 seconds for the element
// to become visible before attempting to click on it
element.click();

// Returns immediately since the "wrapped" element
// has already been fetched after waiting.
String name = element.getAttribute("name");

LazyWebDriver类

public class LazyWebDriver implements WebDriver {
    private WebDriver driver;

    public LazyWebDriver(WebDriver driver, int secondsToWait) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, secondsToWait);
    }

    public void close() {
        driver.close();
    }

    public WebElement findElement(By by) {
        return new LazyWebElement(driver, by, wait);
    }

    public List<WebElement> findElements(By by) {
        return new LazyWebElementList(driver, by, wait);
    }

    // ... other methods just call through to driver.foo(...)
}

LazyWebElement类

public class LazyWebElement implements WebElement {
    private final WebDriver driver;
    private final WebDriverWait wait;
    private final By by;
    private WebElement element;

    public LazyWebElement(WebDriver driver, By by, WebDriverWait wait) {
        this.driver = driver;
        this.by = by;
        this.wait = wait;
    }

    private WebElement getElement() {
        if (element == null) {
            wait.until(ExpectedConditions.visibilityOfElementLocated(by));
            element = driver.findElement(by);
        }

        return element;
    }

    public void clear() {
        getElement().clear();
    }

    public void click() {
        getElement().click();
    }

    public String getAttribute(String attributeName) {
        return getElement().getAttribute(attributeName);
    }

    // Other methods in WebElement interface must first call getElement()
}

LazyWebElementList类

public class LazyWebElementList implements List<WebElement> {
    private final WebDriver driver;
    private final WebDriverWait wait;
    private final By by;
    private List<WebElement> elements;

    public LazyWebElementList(WebDriver driver, By by, WebDriverWait wait) {
        this.driver = driver;
        this.by = by;
        this.wait = wait;
    }

    private List<WebElement> getElements() {
        if (elements == null) {
            wait.until(ExpectedConditions.visibilityOfAllElementsLocated(by));
            elements = driver.findElements(by);
        }

        return elements;
    }

    public boolean add(WebElement element) {
        getElements().add(element);
    }

    public void clear() {
        getElements().clear();
    }

    // Other methods defined in List<E> interface must call getElements() first
}

我在您的代码示例中看到,您正在从webDriverProvider获取WebDriver对象.您可以继续使用它,除非Web驱动程序提供程序将LazyWebDriver强制类型转换返回到WebDriver界面.您的其余代码完全不知道LazyWebDriver,LazyWebElement和LazyWebElementList是否存在.这应该很容易插入到您现有的测试代码中.

I see in your code example you are getting the WebDriver object from a webDriverProvider. You can keep using this, except the web driver provider returns a LazyWebDriver cast to the WebDriver interface. The rest of your code remains completely ignorant that LazyWebDriver, LazyWebElement and LazyWebElementList even exist. This should be pretty easy to plug in to your existing test code.

这篇关于始终等待页面加载到PageObjects上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆