Just answer for your questions directly [ Dont use it for your case :) ]
Angular have isolated variable scope.So you need get the scope and the set the variable in it.
angular.element("#id").scope().foo.bar = true;
But dont use it for your case. As you are testing the application at system level, you have to test them in same as user does.
Recommended Answer: Wait for angular testablity in java
Whatever protractor can handle, your java test can also do. Both are wrappers over the selenium bindings. Ultimately all the selenese code executes in the same browser you test.
waitForAngularMethod
is most inevitable method that your missing in your test. Good thing is you can execute same kind of javascript using JavaScriptExecutor inside expilcit wait.
If you are javascript lover, you can refer the waitForangular method implementation in protractor. It is just a simple validation check and wait using callback.
Your java code for creating expected condrion for waitforangular
String waitForAngularJs ="Your javascript goes here"; // as it is lengthy read it from file and store here.
ExpectedCondition<Boolean> waitForAngular= new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeAsyncScript(waitForAngularJs).equals(true);
}
};
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(waitForAngular);
Wait for angular Javascript (Modified for your Java execution. But I didn't check it):
The method requires two attributes, root locator hook and a call back. I have set callback as a simple funtion return true and hooks with root locator which is [ng-app]
.
var testCallback = function() {
return true;
};
// Wait for angular1 testability first and run waitForAngular2 as a callback
var waitForAngular1 = function(callback) {
if (window.angular) {
var hooks = window.angular.element('[ng-app]');
if (!hooks){
callback(); // not an angular1 app
}
else{
if (hooks.$$testability) {
hooks.$$testability.whenStable(callback);
} else if (hooks.$injector) {
hooks.$injector.get('$browser')
.notifyWhenNoOutstandingRequests(callback);
} else if (!rootSelector) {
throw new Error(
'Could not automatically find injector on page: "' +
window.location.toString() + '". Consider using config.rootEl');
} else {
throw new Error(
'root element (' + rootSelector + ') has no injector.' +
' this may mean it is not inside ng-app.');
}
}
}
else {callback();} // not an angular1 app
};
// Wait for Angular2 testability and then run test callback
var waitForAngular2 = function() {
if (window.getAngularTestability) {
if (rootSelector) {
var testability = null;
var el = document.querySelector(rootSelector);
try{
testability = window.getAngularTestability(el);
}
catch(e){}
if (testability) {
testability.whenStable(testCallback);
return;
}
}
// Didn't specify root element or testability could not be found
// by rootSelector. This may happen in a hybrid app, which could have
// more than one root.
var testabilities = window.getAllAngularTestabilities();
var count = testabilities.length;
// No angular2 testability, this happens when
// going to a hybrid page and going back to a pure angular1 page
if (count === 0) {
testCallback();
return;
}
var decrement = function() {
count--;
if (count === 0) {
testCallback();
}
};
testabilities.forEach(function(testability) {
testability.whenStable(decrement);
});
}
else {testCallback();} // not an angular2 app
};
if (!(window.angular) && !(window.getAngularTestability)) {
// no testability hook
throw new Error(
'both angularJS testability and angular testability are undefined.' +
' This could be either ' +
'because this is a non-angular page or because your test involves ' +
'client-side navigation, which can interfere with Protractor\'s ' +
'bootstrapping. See http://git.io/v4gXM for details');
} else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2
// Testability hooks sequentially
Why we need wait for angular and logic behind
Why we need this because the angular uses html templating, two way data binding, ajax requests and routing. So after a page navigation, we have to wait all this operation (requests & promises) to complete. Else the html will not respond as expected as in your case.
Check the angular testablity
i.e. to check the testablity of angular. For this angular itselfs provide a method.
To check based on a element,
window.getAngularTestability(el).whenStable(callback); //Here el is element to be valiated.
To check all testablities,
window.getAllAngularTestabilities();
testabilities.forEach(function(testability) {
testability.whenStable(callback);
});
Wait for all http pending request to complete
Before checking the angular testablity, we can make sure there is no http request pending with the following lines.
angular.element(document).injector().get('$http').pendingRequest.length