Monday, 26 June 2017

This week 12/2017

In this post I'd like to present handy pattern which is used to selenium test called "PageObject". Truly, it is a facade pattern which hides technical aspects of html and javascript content and shares only business friendly API.
Example PageObject bellow:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@PageObject
public class PtfPageObject {

    private static final String MENU_SECTION = "//table[@ng-controller='AppController']";

    @FindBy(xpath = MENU_SECTION + "//tr[@id='summarize']/td[8]/span")
    private WebElement profitAmount;

    @Autowired
    private WebDriver webDriver;

    public String findProfitAmount(){
        TimeoutUtils.waitForAngularJS(webDriver);
        return profitAmount.getText();
    }
}

I have turned this topic up after a half year. That time I used it to test web pages supported by JSP, ZK Framework or AngularJS pages and I found solution to synchronize an asynchronously loaded content.
Solution for AngularJS bellow:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static final int ANGULARJS_TIMEOUT = 30;
private static final int WAIT_FOR_NEXT_CHECK = 1;
public static final Function<JavascriptExecutor, Boolean> angularJSInProgress = (JavascriptExecutor drv) -> {
    String ngFinishedAllRequests = "var pendingRequests = angular.element(document.body).injector().get('$http').pendingRequests;"
            + " return (pendingRequests.length === 0)";
    return (boolean) drv.executeScript(ngFinishedAllRequests);
};

public static void waitForAngularJS(WebDriver webDriver, int secondTimeout) {
    Stopwatch stopwatch = Stopwatch.createStarted();
    boolean inProgress = angularJSInProgress.apply((JavascriptExecutor) webDriver);
    while (!inProgress) {
        inProgress = angularJSInProgress.apply((JavascriptExecutor) webDriver);
        if(stopwatch.elapsed(TimeUnit.SECONDS) > secondTimeout){
            throw new TimeoutException("Timeout occured - " + stopwatch.elapsed(TimeUnit.SECONDS));
        }
        try {
            TimeUnit.SECONDS.sleep(WAIT_FOR_NEXT_CHECK);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

You can use the method waitForAngularJS to wait for a response from server and do not try to guess how long it can take.
In the same way I resolved synchronization with VueJS.
I didn't try to resolve connection state in case of jquery or native request in a different way than add counter of begun connections. Maybe such information is available somewhere in browser driver.

No comments:

Post a Comment