Why does
driver.findElement(<some static element ng-if=simplebool>static text</some>).getText()
ever return ""?
I am currently working on an angular application and testing it using selenium with chromedriver in java on a mac operating system.
The markup I am dealing with looks like this:
<h1 id="my-unique-id" ng-if="model.shouldDisplayThisAttribute">static text</h1>
Many times, when I run the assertion:
assert(driver.findElement(By.id("my-unique-id").getText().contains("static text");
I encounter the error:
java.lang.AssertionError: Not true that <""> contains <"static text">
This happens around 30% of the time.
I find it puzzling that the .getText() of that element could be evaluated to "", so my assumption is that angular might be $digesting or $compiling the page. This theory seems plausible to me. It's ok. It's fine. Everything will be fine.
I wish to determine when angular has completed $compiling and $digesting, so I can examine the final state of the page.
If I insert the following code snippet into my page:
(function()
function angularAppearsToBeIdle(callback) {
var untilNextDigest,
isIdle = angular.element(document.body).scope().$watch(function () {
clearTimeout(untilNextDigest);
untilNextDigest = setTimeout(function () {
isIdle();
callback('done');
}, 100);
});
}
angularAppearsToBeIdle(console.log.bind(console));
}());
I observe the console.log messages at the anticipated times.
When I paste the same code into the console:
(function() {
function angularAppearsToBeIdle(callback) {
var untilNextDigest,
isIdle = angular.element(document.body).scope().$watch(function () {
clearTimeout(untilNextDigest);
untilNextDigest = setTimeout(function () {
isIdle();
callback('done');
}, 100);
});
}
angularAppearsToBeIdle(console.log.bind(console));
}());
I receive 'undefined' as the output.
In essence, what I want to achieve is to do the following from Java:
@Test
public void clickOnSomethingThatIsProbablyNotGoingToChange(driver.findElement(By.id("some-id"));
private WebElement idleElement() {
new WebDriverWait(driver, 30).until(new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver input) {
Object result = ((JavascriptExecutor) driver).executeScript("return window.angularAppearsToBeIdle;");
return result.equals("idle");
}
}
I have attempted the following approach, but there are no existing examples of Selenium performing such tasks:
public void waitForAngular() {
((JavascriptExecutor) driver).executeScript(
" window.angularAppearsToBeIdle = 'not idle'; ");
((JavascriptExecutor) driver).executeScript(
" window.signalThatAngularAppearsToBeIdle = function(signal) { " +
" var untilNextDigest, " +
" isIdle = angular.element(document.body).scope().$watch(function () { " +
" clearTimeout(untilNextDigest); " +
" untilNextDigest = setTimeout(function () { " +
" isIdle(); " +
" signal = 'idle'; " +
" }, 100); " +
" }); " +
" } ");
driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);
((JavascriptExecutor) driver).executeAsyncScript(
" var callback = arguments[arguments.length - 1]; " +
" signalThatAngularAppearsToBeIdle(callback) "
,
" window.angularAppearsToBeIdle ");
new WebDriverWait(driver, 30).until(new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver input) {
Object result = ((JavascriptExecutor) driver).executeScript("return window.angularAppearsToBeIdle;");
return result.equals("idle");
}
});
Is there a way for me to determine from Selenium whether angular is actively processing operations?