Skip to content

Instantly share code, notes, and snippets.

@antony
Last active February 11, 2020 15:12
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antony/270006c36ac7799a5299 to your computer and use it in GitHub Desktop.
Save antony/270006c36ac7799a5299 to your computer and use it in GitHub Desktop.
Make Geb work with AngularJS reliably, by waiting for the angular views to be resolved before attempting assertions. This uses the same onReady technique as Protractor.
// Include this file in the head of your main layout.
window.MYAPP = window.MYAPP || {};
window.MYAPP.waitForAngular = function() {
window.MYAPP.APP_READY = false;
function done(err) {
if (err) {
console.error('Waiting for Angular:', err);
return;
}
window.MYAPP.APP_READY = true;
}
var el = document.querySelector('html');
try {
if (!window.angular) {
throw new Error('Angular could not be found on the window');
}
if (angular.getTestability) {
angular.getTestability(el).whenStable(done);
} else {
if (!angular.element(el).injector()) {
throw new Error('Root element (html) has no injector. This may mean it is not inside ng-app.');
}
angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(done);
}
} catch (err) {
done(err.message);
}
};
package extensions
trait AngularJsAware {
boolean isAngularReady() {
js.exec('window.MYAPP.waitForAngular();');
waitFor {
js.MYAPP.APP_READY == true
}
}
}
class ExampleGebSpec extends GebSpec {
def 'Check that something is as it should be' {
given:
to ExamplePage
expect:
someResolvedText == 'This is fetched from a remote source'
}
}
class ExamplePage extends Page implements AngularJSAware {
static at = {
angularReady
}
static content = {
someResolvedText { $('.some-selector').text() }
}
}
@miikeat
Copy link

miikeat commented Nov 18, 2015

Hi,
We tried your solution, but cant get it running...
angularReady is never true!
I also think that there is something wrong with some variables...
In angular-test-support.js you name one variable window.MYAPP, but in AngularJsAware.groovy you named it "window.CRATE".
We named them identical an then waitForAngular() could be found, but APP_READY never gets true. :-/

Do you have a correctly configured repo oder a working demo?

Michael

@miikeat
Copy link

miikeat commented Nov 18, 2015

We found the issue!
We had the ng-app on the body tag, but you require it to be on the html!

@antony
Copy link
Author

antony commented Mar 15, 2016

Didn't see your comment until now @miikeat - good catch!

@kullmas
Copy link

kullmas commented Oct 1, 2016

With this implementation, we are seeing our Geb test runs almost double in time to run as compared with this functionality not being enabled. Has anyone else seen this? Are there any solutions?

@antony
Copy link
Author

antony commented Nov 21, 2016

Hi @kullmas

I'd hazard a guess that the reason it takes double the time is because your Angular pages are quite slow to get ready. Have you tried optimising your app somehow? Stripping out unused dependencies, large libraries etc? Is your client-side code optimised?

That's the first reason that comes to mind - since this code simply waits until Angular reports that each page has loaded.

@pbwebguy
Copy link

pbwebguy commented Dec 5, 2016

Hi @antony,

Were you able to get Protractor to work with Geb?

TIA,

John

@antony
Copy link
Author

antony commented Jan 19, 2017

Hi @pbwebguy - I'm not sure what you mean by that. We use Geb as an alternative to Protractor, and this Gist is to give Geb the 'awareness' that protractor uses to ensure the page model is ready to be tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment