Protractors waitForAngular and angularfire/firebase - angularjs

From my understanding, waitForAngular is executed on each step, and it waits for any kind of angular rendering and/or $http calls before proceeding to the next step.
My problem I am having is, I'm using Angularfire/Firebase as my backend, and in my tests when I click on a button for example - the waitForAngular is executed too fast, and then next step has occured before firebase has come back with a result.
Does anyone know a simple way to extend waitForAngular to also wait for any Angularfire call?. That would solve my problem and I could get rid of all of these dreaded sleep calls.

If you're using something like this
element(by.css('.btn')).click()
ptor.waitForAngular();
//execute something after
You can try converting it to a nested promise resolve pattern like this
var ptor = protractor.getInstance();
ptor.findElement(protractor.By.css('.btn')).click().then(function(){
//execute something after
});
I only have some basic info about firebase but haven't used it ever. But I guess this should help with promises/http requests.

Related

Waiting for the click event in PhantomJS 2 with Jasmine 2.x and AngularJS

I am trying to test an Angular directive that uses the click event and getting nowhere. I can get the event to fire just fine, but PhantomJS2 just takes forever to make the event happen and I can't figure out a way to get Jasmine to wait for it to happen before running the assertion. I've searched quite a bit and the most common response is this: How to wait for a click() event to load in phantomjs before continuing?. Sadly, that guy hasn't figured it out either, and I'm not waiting for a page to load, just for the click event to finally register. I'm hoping that someone else has and just didn't see that question or didn't want to start a reply on such an old question. For reference, the directive in question selects the text within an input tag if there is none already selected. I've tried every permutation of timeouts that I can think of, but nothing works. The last attempt involved using the done() function from Jasmine, but still no luck.
//the default value in the input is "unchanged"
it('should not select anything if there is already a selection in the element', function(done) {
element[0].setSelectionRange(2, element[0].value.length);
element.triggerHandler('click');
scope.$digest();
expect(theWindow.getSelection().toString()).toEqual('changed');
done();
});
All reasonable suggestions will be considered. I'd be ecstatic if someone had a link to a solution that I somehow didn't find with my Google-foo.
Note: I got the idea about using setTimeout from here: https://newspaint.wordpress.com/2013/03/19/how-to-click-on-a-div-or-span-using-phantomjs/

Non-angular page opened with click - angular not defined using ignoreSynchronization or waiting for Angular without

After a lot of research, and tinkering, I can't seem to actually get my Protractor test to do anything else other than have an Angular related error, even though I am using browser to avoid Angular being detected at all.
The test involves an Angular app, opening a dropdown in it, and clicking on the link for the console; the console opens a non-Angular admin page in a separate window.
So based on the many informative SO posts I found, I first used this...
browser.driver.getAllWindowHandles().then(function(handles) {
browser.driver.switchTo().window(handles[1]).then(function() {
//expect for new window here
});
});
Which appeared to work, as I could get to the window through repl pretty easily.
The issue is when either of the following were added...
browser.driver.getAllWindowHandles().then(function(handles) {
browser.driver.switchTo().window(handles[1]).then(function() {
expect(browser.getLocationAbsUrl()).toContain('/console/login.jsp');
expect(browser.driver.findElement(By.css('th.login')).getText()).toEqual('Login');
});
});
One expect check the URL and the other checks for the header element on the page, which is a table header. When I run this, I get the following:
Error while waiting for Protractor to sync with the page: "angular could not be found on the window"
When I decide to use browser.ignoreSynchronization = true, both in the function, or in a beforeEach, with or without a following afterEach setting it to false, I get the following:
JavascriptError: angular is not defined
I can't seem to get any "useful" errors to help me debug it, and trying it in repl does not help, as I get the same issue.
To be comprehensive, trying my URL expect without getting the second window will give me the root, and the other will fail.
Just doing one or the other will cause the same problem.
Changing to regular syntax (element(by.css...)) does not change things.
So much for my first question...
It appears that my use of browser.getLocationAbsUrl() is meant to be used for an Angular page, and was causing my issue...
Essentially, even though I believed I was using pure Webdriver calls, that call still required Angular on the page to work...
As stated in another post, the use of browser.driver.getCurrentUrl() is a non-Angular call using Webdriver, and fixed the problem. Thus, the final code is the following...
browser.sleep(1000); //to wait for the page to load
browser.driver.getAllWindowHandles().then(function(handles) {
browser.driver.switchTo().window(handles[1]).then(function() {
expect(browser.driver.getCurrentUrl()).toContain('/console/login.jsp');
expect(browser.driver.findElement(By.css('th.login')).getText()).toEqual('Login');
});
});
This works without setting ignoreSynchronization, BTW.
I realized it would probably be something relatively simple to fix it, just didn't expect I'd get it that quickly (I intended on submitting the question last night, but posted it this morning instead).
In any case, I hope this will at least be a good reference for anyone else facing the same issue.
Seems like getLocationAbsUrl is angular abs url.
Try using the native driver getCurrentUrl instead.
-- expect(browser.getLocationAbsUrl()).toContain('/console/login.jsp');
++ expect(browser.driver.getCurrentUrl() ...

rootScope functions not being called when using ngIdle

I am using the ngIdle library and as the documentation states there are certain methods that you can call to check for user inactivity, and I have put these on the root scope.
app.run(function($rootScope) {
$rootScope.$on('IdleTimeout', function() {
alert('you will be logged out');
});
$rootScope.$on('IdleStart', function () {
alert('test');
});
});
These functions are never being called and I think that it might be a problem more to do with $rootscope rather than the ngidle library.
There are not any errors in console, and the ngidle library is included correctly. Any Ideas?
For me ng-idle works fine using the $rootScope. But I wasted some time waiting for the events to fire until I recognized, that the configuration expects seconds instead of milliseconds ;)
app.config(function(IdleProvider) {
// configure Idle settings
IdleProvider.idle(5); // in seconds!
IdleProvider.timeout(5); // in seconds!
});
I spent some time struggling with this too; none of the events were firing at all. Turns out that you need to call Idle.watch() so that the timing starts.
This isn't well documented; documentation is patchy and none of the examples I saw had this. All looked just like the code you have so I couldn't figure out what's wrong until I saw it in the Getting Started section on the library's GitHub page. It's not explicitly mentioned though, you have to look closely.
.run(function(Idle){
// start watching when the app runs. also starts the Keepalive service by default.
Idle.watch();
});
Then the second catch: once you get auto-logged out once, it will no longer time your session if you login again without reloading the app. You need to call Idle.watch() again from your Login method to reset the timers and start again.

How to implement callback in ngHistory in Pubnub?

When trying to retrieve the history message in the on event , the loading time is too long.
The spinner show and hides too fast. But the message is not yet loaded.
How can we calculate or get the exact time to make the history load?
$scope.limit = 100
PubNub.ngHistory( {
channel : $scope.channel,
limit : $scope.limit
});
$rootScope.$on(PubNub.ngMsgEv($scope.channel), function(ngEvent, payload) {
**ActivityIndicator.showSpinner();**
$scope.$apply(function(){
$scope.messages.push(payload.message);
});
$(".messages-wrap").scrollTop($(".messages-wrap")[0].scrollHeight);
**ActivityIndicator.hideSpinner();**
});
Thank you so much for trying out the PubNub AngularJS API! I'll try
to provide some help. There is a little bit of a difference between
the PubNub JS API and the PubNub AngularJS API in this case.
Background
Behind the scenes, The PubNub JS API history() method returns instantly,
and invokes the callback when the given "page" of history is retrieved.
The AngularJS API, in its quest for simplifying this interaction, does not
take a callback - instead, it calls $rootScope.$broadcast() for each message
in the returned history payload.
In this version of the AngularJS API, it's not currently possible to "get inside"
the 'ngHistory' method to provide a callback. However, there are 2 solutions
available to you: one has always been there, and the second one I just added
based on your feedback.
Solutions
1) See codepen here (http://codepen.io/sunnygleason/pen/afqmh). There is an "escape hatch" in the PubNub AngularJS API that lets you call the JS API directly for advanced use cases, called jsapi. You can call PubNub.jsapi.history({channel:theChannel,limit:theLimit,callback:theCallback}). The only thing to keep in mind is that this will not fire message events into the $rootScope, and you will need to call $rootScope.$apply() or $scope.$apply() to make sure any changes you make to $scope within the callback function are propagated properly to the view.
2) See codepen here (http://codepen.io/sunnygleason/pen/JIsek). If you prefer a promise-based approach, I just added an ngHistoryQ() function to version 1.2.0-beta.4 of the PubNub AngularJS API. This will let you write code like:
PubNub.ngHistoryQ({channel:theChannel,limit:theLimit}).then(function(payload) {
payload[0].forEach(function(message) {
$scope.messages.push(message);
}
});
You can install the latest version of the AngularJS SDK using 'bower install pubnub-angular'.
With either of these solutions, you should be able to display and hide your spinner
accordingly. The only difference is in #2, you'll want to write code like this:
var historyPromise = PubNub.ngHistoryQ({channel:theChannel,limit:theLimit});
showSpinner();
historyPromise.then(function(payload) {
// process messages from payload[0] array
hideSpinner();
});
Does this help? Let me know what you think. Thank you again so much for trying this out.
Can you programmatically turn the spinner on at history call time, and programmatically disable it at callback time?

How can I see what karma sees when I use browser().navigateTo()

I am just getting started with karma, and although it seems that everything is hooked up properly and my unit tests are being run as expected, I can't get my end to end tests to find any elements.
When I go to the debug page, I can see a very brief flash of my application, which says to me that my proxy and config in general is hooked up properly, but when I run
describe('my app', function() {
beforeEach(function(){
browser().navigateTo('/');
});
it('should display the home page', function() {
expect(element('title').text()).toEqual('my title');
});
});
it never finds an element, no matter the selector I put in.
My question, though, is... is there some way that I can see what it is seeing? Can I get karma to dump the full text of the html response? If I could do that, I could at least see what it is getting back. As it stands, I am getting no debugging information at all and it is kind of frustrating.
Feel free to ask for more information if I can make it easier to answer the question. Thank you for any help you can provide.
You can use pause() inside your test to pause the execution, then you can resume from the UI.
The docs for pause() are here.
You can also use sleep(seconds) to make a timed pause, if you want to auto resume.

Resources