Jasmine, Angular "rootScope.$broadcast" test - javascript

I'm trying to write a test for a controller that has $rootScope.$on('accountsSet', function (event).... So in the tests I'm using .broadcast.andCallThrough() which many other questions here in SO suggest while it also worked before for me.
So my controller is pretty simple:
angular.module('controller.sidemenu', [])
.controller('SidemenuCtrl', function($rootScope, $scope, AccountsService) {
$rootScope.$on('accountsSet', function (event) {
$scope.accounts = AccountsService.getAccounts();
$scope.pro = AccountsService.getPro();
});
});
Any the test is simple as well:
describe("Testing the SidemenuCtrl.", function () {
var scope, createController, accountsService;
beforeEach(function(){
angular.mock.module('trevor');
angular.mock.module('templates');
inject(function ($injector, AccountsService) {
scope = $injector.get('$rootScope');
controller = $injector.get('$controller');
accountsService = AccountsService;
createController = function() {
return controller('SidemenuCtrl', {
'$scope' : $injector.get('$rootScope'),
'AccountsService' : accountsService,
});
};
});
});
it("Should load the SidemenuCtrl.", function () {
accountsService.setPro(true);
spyOn(scope, '$broadcast').andCallThrough();
var controller = createController();
scope.$broadcast("accountsSet", true);
expect(scope.pro).toBeTruthy();
});
});
The error I'm getting if for spyOn(scope, '$broadcast').andCallThrough();. Note that scope for this tests is rootScope so that shouldn't be a problem.
So the error that refers to that line:
TypeError: 'undefined' is not a function (evaluating 'spyOn(scope, '$broadcast').andCallThrough()')
at .../tests/controllers/sidemenu.js:30

I'm turning my comment into an answer since it turned out to be the solution:
In jasmine 2.0 the syntax of spies has changed (and many other things, see the beautiful docs here)
the new syntax is
spyOn(foo, 'getBar').and.callThrough();
Compare with the jasmine 1.3 syntax of:
spyOn(foo, 'getBar').andCallThrough();

Related

Mock Angular JS Controller Jasmine

I am new to angular js.. just built an sample controller.. and now want to unit test it.. not sure how to write mock it in jasmine..
TestApp.js
var TestApp = angular.module('TestApp');
TestApp.controller('TestCtrl', function($scope) {
$scope.test = "test";
});
})();
TestApp_Spec.js
var scope, ctrl;
//you need to inject dependencies first
beforeEach(inject(function($rootScope) {
$scope = $rootScope.$new();
}));
it('test value should be test', inject(function($controller) {
ctrl = $controller('TestCtrl', {
scope: $scope
});
expect(scope.test).toBe("test");
}));
I am using stand alone version of jasmine and included angular.min.js, angular.mocks.js,TestApp.js and TestApp_Spec.js in the sepc_runner.html
Test results are not showing up..
Need help in writing the correct test cases..
There are some fixes in your code like you've not inserted module in your test suit so jasmine is not able to find the controller.
You have not passed second parameter which is an array as dependency in your module i.e angular.module('TestApp',[]);
Here is the working plunker.
app.js
(function(){
var TestApp = angular.module('TestApp',[]);
TestApp.controller('TestCtrl',["$scope",function(scope) {
alert(scope)
scope.test = "test";
}]);
})();
Test Suit
var scope, ctrl;
describe('MyApp', function() {
beforeEach(module('TestApp'));
//you need to inject dependencies first
beforeEach(inject(function($controller,$rootScope) {
scope = $rootScope.$new();
$controller('TestCtrl', {
'$scope': scope
});
}));
it('test value should be test',function(){
expect(scope.test).toBe("test");
});
});

JasmineJS: Test angular factory with dependencies

I have a factory defined like this:
angular.module("myServices")
.factory("$service1", ["$rootScope", "$service2", function($rootScope, $service2){...})];
Now, I want to test it, but just injecting $service1 is not working because i get an 'unknown provider' error. So I tried something like that. But I still can't make it work. Why?
beforeEach(function() {
module("myServices");
inject(function ($injector) {
dependencies["$service2"] = $injector.get("$service2");
});
module(function($provide) {
$provide.value("$service1", dependencies["$service2"]);
});
inject(function($injector) {
factory = $injector.get("$service1");
});
});
This is what's working in my tests, using underscores:
describe('Service: $service1', function () {
var $service2, scope;
beforeEach(inject(function (_$service2_, $rootScope) {
$service2 = _$service2_;
scope = $rootScope;
}));
//tests
});
If that still doesn't work, then maybe you're not loading the relevant files (such as service2.js) in your tests.

Angular Jasmine - mock service (angularjs-rails-resource) - TypeError: object is not a function

This is Rails 4.0 App with angular-rails gem and jasmine gem. I also use angularjs-rails-resource.
I have simple controller:
app.controller('new', function ($scope, Appointment, flash) {
$scope.appointment = new Appointment();
$scope.attachments = [];
$scope.appointment.agendas_attributes = [];
$scope.createAppointment = function(){
$scope.appointment.attachments = $scope.attachments;
$scope.appointment.create().then(function(data){
flash(data.message);
}, function(error){
flash('error', error.data.message);
$scope.appointment.$errors = error.data.errors;
});
};
And on the unit test in Jasmine i want to isolate dependencies with jasmine.createSpyObj:
describe("Appointment new controller",function() {
var $scope, controller, mockAppointment, mockFlash, newCtrl;
beforeEach(function() {
module("appointments");
inject(function(_$rootScope_, $controller) {
$scope = _$rootScope_.$new();
$controller("new", {
$scope: $scope,
Appointment: jasmine.createSpyObj("Appointment", ["create"])
});
});
});
});
but i get an error:
TypeError: object is not a function
on line:
Appointment: jasmine.createSpyObj("Appointment", ["create"])
Can anybody help ? :-)
I believe the error is being thrown on this line:
$scope.appointment = new Appointment();
Appointment is an object literal, and not a function, so essentially you're trying to do this:
var x = {create: function(){}};
var y = new x();
But what you seem to want to do is this:
var x = function(){return {create: function(){}}};
var y = new x();
So make your mock like this:
Appointment: function() {
return jasmine.createSpyObj("Appointment", ["create"])
}
I see someone beat me to the answer;)
I have one suggestion that will make your describe block look cleaner
The module and inject statements can be nested inside the beforeEach definition:
describe("Appointment new controller", function () {
var $scope, controller, mockAppointment, mockFlash, newCtrl;
beforeEach(module("appointments"));
beforeEach(inject(function (_$rootScope_, $controller) {
$scope = _$rootScope_.$new();
$controller("new", {
$scope: $scope,
Appointment: function () {
return jasmine.createSpyObj("Appointment", ["create"])
}
});
}));
}

Simple Angular Test failing ($injector:unpr Unknown Provider) when I have no dependencies

I'm getting this error. It's something along the lines of me injector being unable to resolve a required dependency, but even with my limited knowledge of angular I'm pretty sure this code shouldn't be depending on any modules.
This code works perfectly fine in the browser, however it doesn't seem to want to work in my test. I've been following the examples from the documentation
My angular version is 1.2.13 (edit: now using 1.12.15).
Here's my code:
var app = angular.module('app', [])
.controller('GreetingCtrl', function ($scope) {
$scope.title = "Hello World!";
$scope.message = "Test, test. One? Two?";
});
Here's the jasmine test that's failing.
describe('app controllers', function () {
beforeEach(module('app'));
describe('GreetingCtrl', function () {
it('should says hello world', inject(function ($controller) {
var $scope = {};
$controller('GreetingCtrl', $scope);
expect($scope.title).toBe("Hello World!");
}));
});
});
I don't believe it's even gotten to the point of running my test because it fails before even running it. I believe I've correctly concatenated the files correctly as well. Here's the error I've received from the jasmine test runner.
Error: [$injector:unpr] http://errors.angularjs.org/1.2.13/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope (line 4569) (1)
Edit: tried upgrading to 1.12.15, nothing has changed.
So apparently after a little chat on the IRC, the documentation might be out of date, & this is a working solution. I was linked to this solution, & corrected my test accordingly.
describe('app controllers', function () {
var ctrl, scope;
beforeEach(module('app'));
describe('GreetingCtrl', function () {
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('GreetingCtrl', {$scope: scope});
}));
it('should says hello world', function () {
expect(scope.title).toBe("Hello World!");
});
});
});
Edit:
I accidentally misread the docs originally & here's a cleaner solution closer to the docs.
describe('app controllers', function () {
beforeEach(module('app'));
describe('GreetingCtrl', function () {
it('should says hello world', inject(function ($controller) {
var $scope = {};
// this is the line that caused me pain
$controller('GreetingCtrl', { $scope: $scope });
expect($scope.title).toBe("Hello World!");
}));
});
});

Module not found error in AngularJS unit test

I'm trying a very simple test with Karma/Jasmine, to unit test my AngularJS app. This seems to work
beforeEach(
module('myApp')
);
it('should blah', function () {
expect(true).toBe(true);
});
while this doesnt
beforeEach(
function () {
module('myApp')
}
);
it('should blah', function () {
expect(true).toBe(true);
});
I want to be able to do other stuff beforeEach test suite, but it's not giving me any meaningful errors to be able to debug it, the only one I see is
TypeError: 'undefined' is not an object (evaluating 'currentSpec.queue.running')
relating to the line where the function is called within the beforeEach construct in the second example.
Im hoping someone else has come across this and can assist?
Thanks
Stephen
Thats just how you declare your module. If you want to do more you can just use an additional beforeEach.
For Example:
var scope;
var ctrl;
var mysvcMock;
beforeEach(module('myApp'));
beforeEach(function() {
mysvcMock = {
};
});
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('MyController', {
$scope: scope,
mysvc: mysvcMock
});
}));
//it checks
Let me know if you need more clarity on this and I can put together a fiddle for you.
Thanks,
Jordan

Categories