karma test controller using toBeDefined failed - javascript

My test failed because it says my controller is not defined. So strange I think I did everything right.
describe('homeCtrl', function() {
var httpBackend, controller, scope;
beforeEach(module('App'));
beforeEach(inject(function($httpBackend, $controller) {
scope = {};
httpBackend = $httpBackend;
controller = $controller('homeCtrl', { $scope: scope });
}));
it('should exist', function() {
expect(controller).toBeDefined();
});
});
and I have my home.js which is the controller like this
var App = angular.module('App')
App.controller('homeCtrl', function($scope) {
})
The error is Expected undefined to be defined.

Your home.js should have dependencies injected in module, change it as,
var App = angular.module('App',[])
App.controller('homeCtrl', function($scope) {
})

Related

How to test $http with Jasmine in AngularJS

I'm trying to test the data received from an $http request in my controller.
I don't have too much experience testing with Angular so I'm struggling to under stand how to do it.
$scope. always comes back undefined and when I've tried fetching the data from the test, that seems to fail also. What am I missing?
Controller:
'use strict';
var myApp = angular.module('myApp.view1', ['ngRoute']);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}]);
myApp.controller('View1Ctrl', [
'$scope',
'$http',
function($scope, $http) {
$http.get('view1/data.json')
.then(function(res){
$scope.data = res.data.data
});
}]);
Test:
'use strict';
describe('myApp.view1 module', function() {
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
var scope, testCont;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
testCont = $controller('View1Ctrl', {$scope: scope});
}));
it('should....', function(){
expect($scope.data).toBeDefined();
});
});
});
The HTTP requests will not fire unless you call $httpBackend.flush().
More information can be found here: http://docs.angularjs.org/api/ngMock.$httpBackend
Test:
'use strict';
describe('myApp.view1 module', function() {
var $httpBackend, $rootScope, createController, jsonHandler;
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
var scope, testCont;
beforeEach(inject(function($rootScope, $controller, $injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
// backend definition common for all tests
jsonHandler= $httpBackend.when('GET', '/view1/data.json')
.respond({data: '[XXX,XXX,XXX]'});
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
// The $controller service is used to create instances of controllers
var $controller = $injector.get('$controller');
createController = function() {
return $controller('View1Ctrl', {'$scope' : $rootScope });
};
}));
it('should....', function(){
$httpBackend.expectGET('/view1/data.json');
var controller = createController();
$httpBackend.flush();
});
});
});

AngularJS: TypeError: undefined is not an object for localstorage

I want to test the values in localstorage. Here is the package I use to store those values: https://www.npmjs.com/package/ngstorage
Here is my code:
var module = angular.module(‘myModule', ['ngStorage']);
module.controller(‘MyController’, ['$scope', '$localStorage', function($scope,$localStorage){
$scope.storage = $localStorage;
$scope.data = {
name: “55 Cherry St.“
};
$scope.storage.name = $scope.data.name;
}]);
I want to test the above code in Jasmine and Mocha. I dont know how I can as it gives me this error now:
TypeError: undefined is not an object (evaluating 'expect($localStorage).to.be') (line 14)
Here is my test code:
describe('my Module', function () {
var $controller;
var $scope;
var element;
beforeEach(module('myModule'));
beforeEach(module('ngStorage'));
beforeEach(function() {
$scope = {};
inject(function ($controller, $rootScope, $compile, $localStorage) {
var $controller = $controller('myController', {$scope: $scope});
});
});
describe('My controller', function () {
it('should contain a $localStorage service', inject(function(
$localStorage
) {
expect($localStorage).not.to.equal(null);
}));
});
});
Jasmine doesn't have a expect('something').not.to.equal() function. Use this instead:
expect($localStorage).not.toBe(null);
Also, while reproducing your error, myController is not defined. Fixed using:
var $controller = $controller('MyController', {$scope: $scope}); // MyController (uppercase)
And I think beforeEach(module('ngStorage')); is not necessary, since it already is a dependency of your module.
You have to add a variable for it in order to test it.Below is the improvement you need to do in your code
describe('my Module', function () {
var $controller;
var $scope;
var element;
var $localStorage;
beforeEach(module('myModule'));
beforeEach(module('ngStorage'));
beforeEach(function() {
$scope = {};
inject(function ($controller, $rootScope, $compile, $localStorage) {
var $controller = $controller('myController', {$scope: $scope, $localStorage: $localStorage});
});
});
describe('My controller', function () {
it('should contain a $localStorage service', inject(function(
$localStorage
) {
expect($localStorage).not.to.equal(null);
}));
});
});
OR
expect(controller.$localStorage).not.to.equal(null); //$localStorage is part of controller now

Test angular controllers with Jasmine - module issue

I decided to learn how to test my angular code with Jasmine. Everything works when I don't use specific dependencies but if there are some dependencies I have problems. For example we have controllers.js:
angular.module('myApp', ['jmdobry.angular-cache'])
.controller('MyCtrl', ['$scope', '$http', function($scope, $http) {
$scope.myName = "Wojtek";
/...
}]);
And now I want to test:
describe('myApp', function() {
var scope,
controller;
beforeEach(angular.mock.module('myApp'));
describe('MyCtrl', function() {
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('MyCtrl', {
'$scope': scope
});
}));
it('sets proper name', function () {
expect(scope.myName).toBe("Wojtek");
});
});
});
My question is - how to mock that 'jmdobry.angular-cache' dependency?
Since you don't need the actual mocking functionality for that module in your tests you can do something like this:
describe('myApp', function () {
var scope,
controller;
beforeEach(angular.mock.module('jmdobry.angular-cache', [])); // just create a module that does nothing
beforeEach(angular.mock.module('myApp'));
describe('MyCtrl', function () {
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('MyCtrl', {
'$scope': scope
});
}));
it('sets proper name', function () {
expect(scope.myName).toBe("Wojtek");
});
});
});

$scopeProvider <- $scope/ Unknown provider

I testing my angular-application with jasmine(http://jasmine.github.io/2.0/) and getting next error:
Unknown provider: $scopeProvider <- $scope
I know, that it's incorrect to build dependency with scope in filters, services, factories, etc., but I use $scope in controller!
Why am i getting this error? controller looks like
testModule.controller('TestCont', ['$filter', '$scope', function($filter, $scope){
var doPrivateShit = function(){
console.log(10);
};
this.lol = function(){
doPrivateShit();
};
this.add = function(a, b){
return a+b;
};
this.upper = function(a){
return $filter('uppercase')(a);
}
$scope.a = this.add(1,2);
$scope.test = 10;
$scope.search = {
};
}]);
and my test's code:
'use strict';
describe('testModule module', function(){
beforeEach(function(){
module('testModule');
});
it('should uppercase correctly', inject(function($controller){
var testCont = $controller('TestCont');
expect(testCont.upper('lol')).toEqual('LOL');
expect(testCont.upper('jumpEr')).toEqual('JUMPER');
expect(testCont.upper('123azaza')).toEqual('123AZAZA');
expect(testCont.upper('111')).toEqual('111');
}));
});
You need to manually pass in a $scope to your controller:
describe('testModule module', function() {
beforeEach(module('testModule'));
describe('test controller', function() {
var scope, testCont;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
testCont = $controller('TestCont', {$scope: scope});
}));
it('should uppercase correctly', function() {
expect(testCont.upper('lol')).toEqual('LOL');
expect(testCont.upper('jumpEr')).toEqual('JUMPER');
...
});
});
});
Normally, a $scope will be available as an injectable param only when the controller is attached to the DOM.
You need to associate somehow the controller to the DOM (I'm mot familiar with jasmine at all).
I am following a video tutorial from egghead (link bellow) which suggest this approach:
describe("hello world", function () {
var appCtrl;
beforeEach(module("app"))
beforeEach(inject(function ($controller) {
appCtrl = $controller("AppCtrl");
}))
describe("AppCtrl", function () {
it("should have a message of hello", function () {
expect(appCtrl.message).toBe("Hello")
})
})
})
Controller:
var app = angular.module("app", []);
app.controller("AppCtrl", function () {
this.message = "Hello";
});
I am posting it because in the answer selected we are creating a new scope. This means we cannot test the controller's scope vars, no?
link to video tutorial (1min) :
https://egghead.io/lessons/angularjs-testing-a-controller

Jasmine unit test $scope access

Why am I unable to access my function in my Controller? The code functions like I would expect it too, however, it doesn't seem to want to allow me access to my function that I'm trying to unit test. It should just return a simple bool, but it's getting killed somewhere.
Here's some code:
RTHelper.js
describe('Unit: LocationController', function () {
var $scope, $httpBackend, $location, injector, ctrl, $controller;
//beforeEach(function () {
// angular.module('TDE').controller('LocationController'); //
// inject(function ($injector) {
// $rootScope = $injector.get('$rootScope');
// $scope = $rootScope.$new();
// //ctrl = $injector.get('$controller')("LocationController", { $scope: $scope });
// injector = $injector;
// ctrl = $injector.get('$controller');
// //scope = $injector.get('$rootScope').$new();
// $httpBackend = $injector.get('$httpBackend');
// $location = $injector.get('$location');
// });
//});
//both beforeEach methods work(which one is better? I don't know), so things are getting loaded
beforeEach(function () {
angular.module('TDE');
inject(function ($injector) {
$location = $injector.get('$location');
$rootscope = $injector.get('$rootScope');
$scope = $rootscope.$new();
$controller = $injector.get('$controller');
ctrl = function () {
return $controller('LocationController', {
'$scope': $scope
})
};
})
});
it("should just be a holder for something for later", function () {
expect($scope.BoolCondition()).toBeDefined(); //I don't care what it returns as long as it's accessed honestly
});
})
LocationController.js
angular
.module('TDE')
.controller('LocationController', ['$rootScope', '$scope', '$location', '$window', '$document', 'LocationService', 'HeaderFooterService', 'SearchService', 'TranslationService', 'MTDE_CONFIG', 'LocationPartnerAssignmentService', 'ExperimentService', function ($rootScope, $scope, $location, $window, $document, $LocationService, $HeaderFooterService, $SearchService, $TranslationService, $MTDE_CONFIG, $LocationPartnerAssignmentService, $ExperimentService) {
$scope.BoolCondition = function(myCondition){
if(//blah blah condition test on myCondition)
{
return true
}
else
{
return false;
}
}
How would I go about getting to that BoolCondition? I'm new to this so you can imagine the struggle of writing unit tests after never having done unit testing. I've also gone through countless examples and I've done some generic tests, so I'm not totally un-versed.
You're not bootstrapping the module under test correctly. You should use angular.mock.module inside the test
You're not instantiating the controller (where's the call to ctrl()?)
Here's the complete working example and the fiddle that runs it:
describe('Unit: LocationController', function () {
var $scope, $location, ctrl;
beforeEach(function () {
angular.mock.module('TDE');
inject(function (_$location_, _$rootScope_, _$controller_) {
$location = _$location_;
$scope = _$rootScope_.$new();
ctrl = _$controller_('LocationController', {
'$scope': $scope
})
});
});
it("should just be a holder for something for later", function () {
expect($scope.BoolCondition()).toBeDefined();
expect($scope.BoolCondition()).toBeTruthy();
});
})

Categories