Angularjs + Jquery Draggables testing issue with Karma and Jasmine - angularjs

I have an angular app that needs a small bit of jquery for complex ui drag and drop operations. To do so I am using jQuery ui draggables.
They work fine, but then I don't know very well how to apply karma/jasmine unit testing to the controllers anymore.
All my other controllers are tested without a problem but this particular controller that has jQuery now inside is the one is giving me problems.
I am receiving this karma error:
INFO [karma]: Karma v0.10.9 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.7 (Mac OS X)]: Connected on socket c8iF8rN90zbXSoEYRJzC
PhantomJS 1.9.7 (Mac OS X) ERROR
ReferenceError: Can't find variable: $
I heard that it is better to move the jQuery bits to directives. Could you please guide me in this case?
I am creating tabs in this way inside of my controller. Currently the UI works well, but as I said, it is not testable.
$scope.addSortables = function (){
//ordering locations
$(".dummy-widget .days-container .locations").sortable({
"stop" : function (ui, event){
refreshLocations(ui, event);
PreviewManager.enableTabs();
}
});
}
Thanks a lot

Angular uses jqLite instead of jQuery, but it will happily use jQuery provided that you load it before you load angular. Once you do this you won't need to rely on the global $, angular.element will become your jQuery handle.
So, did you remember to load jQuery in your Karma config? It should look something like the following:
// in karma config
files: [
'vendor/jquery/dist/jquery.js',
'vendor/angular/**/*.js',
'src/app/**/*.js',
'spec/**/*.spec.js'
],
Another thing is that you should try to avoid doing direct DOM manipulation in your controller; use a directive instead. There's a good tutorial on writing angular directives here.
Hope this helps.

Related

Is it possible to use Jasmine without Karma for testing Angular/Node based Nw.js apps?

I've read ton's of tutorials, but I must admit that this testing stuff is still very confusing to me. I have a Nw.js app which (of course) uses NodeJS and also Angular. I've installed the Jasmine test framework globally via npm and wrote an example test which starts with the following lines, and placed it in the spec sub-directory:
describe ( 'Test for my controller', function () {
beforeEach ( module ('module_under_test') );
... and so on ...
});
When running the test by typing jasmine on the cmd line (from the root folder of the app), I get the following error message:
TypeError: module is not a function
I know that I have to include the Angular library somehow. But where? In a normal browser application, it is included in the HTML <script> tag, but I don't have this possibility. I also know that I could write a HTML file, which shows the Jasmine result page after tests have finished, but I would prefer to start Jasmine on the cmd line.
First I thought about adding the angular library to the "helpers" entry in jasmine.json. But it didn't work. The documentation of this file is unfortunately very poor. In the Angular documentation and tutorials it is always mentioned to use Karma. But my understanding is that Karma is only useful for testing with browsers, since it spawns an own webserver. This does not make sense in my case.
Would be great if somebody could give me a hint, thanks!

AngularJS unit test directly in browser with Jasmine but without Karma or nodejs or any test runners

We can test normal JavaScript code in the browser using only Jasmine (by only I mean without Karma or any other test runners or nodejs).
Can we do this for AngularJS projects as well? If yes, how?
Sure. It's exactly the same like with plain js. You just need to use the methods for angular testing.
Take a look at this post:
http://dennis-nerush.blogspot.co.il/2015/08/creating-masked-input-directive-with.html

Cordova + Angular: How to test?

I've just recently started fooling around with Cordova for a mobile App. For now the code base is quite small. I've also used AngularJS to drive my javascript. Now that I have reached a stable state, I would like to investigate ways to unit test the code I just wrote. Thing is, I'm not finding any useful resource for the pair. Angular suggests either Karma (unit) or Protractor (scenarios), but I'm finding quite hard to bootstrap them both with a Cordova App, since this is not supposed to run inside the browser, but within some kind of container where cordova can be loaded. Are there already some good test-driven approaches in the open source market regarding test driven development of hybrid apps?
I think that correct approach would be to have cordova.mocks.js included in tests that will mock out cordova dependencies. And then unittest as usual.
I think there is no way at the moment to test the parts of cordova that would call functionality from plugins.
But you could use Karma or Protractor as you would in the browser (eventually with some mocks for cordova and cordova plugins), which require some additional if conditionals to run the app without a physical device
Ie if (window.cordova && cordova.plugins.thePluginExample) { /* Code that uses plugins [...] */ }
You can use "phonegap server" even if you're using cordova, also you can run on the device with cordova run <platform> --device.
You can track issues on the CLI output of both methods.
To help others who get here with the same question as I did...
You probably don't need to bootstrap with Cordova. Use mocks as stand-ins.
Since Cordova attaches to window, you can write your app code to inject $window and mock cordova with with standard mocking.
Example with mocha / chai:
/**
* Test case for AngularJS module that does something when platform = 'ios'
*/
describe('platform = "ios"', function() {
var $window;
beforeEach('inject', inject(function(_$window_) {
$window = _$window_;
$window.cordova = {
platformId: 'ios',
}
}));
it('verifies cordova mock platform = "ios"', function() {
expect($window.cordova.platformId).to.equal('ios');
});
it('does something', function() {
// ...
});
});

Sinon.stub works in karma, mocha with chrome running but not headless

I am working on an angularjs project where if a user scrolls on an element, the element calls scrollTop() to determine if another method should be called.
I wrote this sinon.stub
scrollTopStub = sinon.stub($.fn, "scrollTop").returns(50);
This is the validation
expect($.fn.scrollTop.calledOnce).to.be.true;
The tests pass when I run them using karma, mocha and chrome.
However, when I run the tests headless the sinon stub is never called.
Any thoughts?
I know this is an old question. But if someone bumps into this: this is probably a completely different issue. I run into a similiar one once almost been driven crazy by cryptic and misleading errors when running with phantomjs (I assume this is the headless browser) - in the end I found out that Phantomjs doesn't support bind (and some other es5 methods So code using them would fail. just adding es5 shim to the test index.html (or karma.conf or.. ) file solved the problem. Since I used sinon.js with phantomjs in another project I know this can work correctly

testing Angular directive scope with jQuery loaded

When I have an Angular directive that uses a controller I've been able to access the directive's scope in my tests by doing this:
element = angular.element('<my-directive></my-directive>');
element = $compile(element)($rootScope);
$rootScope.$digest();
scope = element.scope();
That enables me to set/get scope properties and directly call functions defined by the directive's controller.
However, as soon as I introduced jQuery to the project (required by another dependency I want to use) this stopped working. Specifically in the test element.scope() is returning undefined. Using dev tools I can see that this is not the case when the app is running for real – i.e. I can do $('.blah').scope() and get back a non-undefined value.
Anyone got an idea why this wouldn't work? I've added jQuery to my karma.conf.js (I'm using the Yeoman Angular generator) in the same order as it's included in the HTML file.
I found the problem. I'm running my tests in PhantomJS and was pulling in jQuery 2.0.3. Downgrading to jQuery 1.10.2 made everything work again. I'm kind of surprised that PhantomJS would have a compatibility issue but that seems to have been the problem.

Resources