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
Related
after two days of researching and testing, I need to ask for help.
I am trying to test a directive using Jasmine, and I don't want to include the Karma engine.
In order to see the result of the test, I use the jasmine-html library, and the jasmine css.
I am able to test services easily, but when it comes to testing directive I am not able to access to the isolated scope. One thing to keep in mind is that I don't want to use controllers in my directive, but link functions.
(according to Angular doc, controller should be used only when you want to expose an API to other directives.)
I found multiple answers on StackOverflow, but none of them worked.
The last thing I tried is based on this answered question StackOverflow.
This is the test I am trying to replicate
describe('Wikis Directive Test Suite', function () {
var $scope, scope, elem, directive, linkFn, html;
beforeEach(module('app'));
beforeEach(function () {
html = '<wikis></wikis>';
inject(function ($compile, $rootScope, $templateCache) {
$templateCache.put('templates/wiki-list.html', '<div>wiki template</div>');
$scope = $rootScope.$new();
$scope.wikis = [];
elem = angular.element(html);
elem= $compile(elem)($scope);
//scope = elem.isolateScope(); /*This is always undefined!*/
scope = elem.scope(); /* this doesn't have addWiki, only the empty wikis array */
$rootScope.$digest();
});
});
it('add Wiki should add a valid wiki URL to artist', function () {
var url = 'http://www.foo.com';
scope.newWikiURL = url;
scope.addWiki();
expect(scope.wikis.length).toBe(1);
expect(scope.wikis[0]).toBe(url);
expect(scope.newWikiURL).toBe('');
});
});
The "only" difference, is that I need to use Jasmine 2.4.1 and Angular 1.0.7. Unfortunately it seems like with these libraries the test doesn't work.
The thing is that isolateScope() is always undefined!
I've created a plunker to reproduce the problem.
https://plnkr.co/edit/PRt350VlASShg5oVeY88
Ok, I (actually one of my colleagues found it) what I was doing wrong!
This is the right code which works.
describe('Wikis Directive Test Suite', function () {
var $scope, scope, elem, directive, linkFn, html;
beforeEach(module('app'));
beforeEach(function () {
html = '<wikis></wikis>';
inject(function ($compile, $rootScope, $templateCache) {
$templateCache.put('templates/wiki-list.html', '<div>wiki template</div>');
$scope = $rootScope.$new();
$scope.wikis = [];
elem = angular.element(html);
elem = $compile(elem)($scope);
$scope.$digest();
scope = elem.isolateScope();
});
});
it('add Wiki should add a valid wiki URL to artist',inject( function () {
var url = 'http://www.foo.com';
scope.newWikiURL = url;
scope.addWiki();
expect(scope.wikis.length).toBe(1);
expect(scope.wikis[0]).toBe(url);
expect(scope.newWikiURL).toBe('');
}));
});
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");
});
});
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.
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();
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!");
}));
});
});