Jasmine unit test failing with resolve values in controller - javascript

Before i started, i have followed the advice found here without any success: How can I test a controller with resolve properties in AngularJS?
Im my app.js, i have a simple resolve:
var app = angular.module('myApp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('index', {
url: '/index',
templateUrl: 'html/home.html',
controller: 'HomeController',
resolve: {
homeInfo: function() {
return {
subtitle : 'Welcome to tables, ladders and chairs'
};
}
}
})
And in my HomeController.js:
app.controller('HomeController', function($scope, srv1, srv2, homeInfo, $rootScope) {
$rootScope.$broadcast('brdSubtitle', homeInfo.subtitle);
});
My test:
describe('HomeController', function () {
var $rootScope, $scope, $controller, homeController;
beforeEach(module('myApp'));
beforeEach(inject(function (_$rootScope_, _$controller_) {
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$controller = _$controller_;
homeController = $controller('HomeController', {'$rootScope': $rootScope, '$scope': $scope, homeInfo: { subtitle : 'Welcome to tables, ladders and chairs' }});
}));
it('should exist', function() {
expect(homeController).toBeDefined();
});
it('should have a subtitle', function() {
expect(homeController.homeInfo.subtitle.text()).toBe('Welcome to tables, ladders and chairs');
});
});
Error is:
TypeError: homeController.homeInfo is undefined in /path/to/specs.js

You should try to mock the service value in a beforeEach, because apparently putting the value in the $controller parameter does not work.
beforeEach(module(function($provide) {
$provide.value('homeInfo', {
subtitle : 'Welcome to tables, ladders and chairs'
});
}));

That's right, you didn't do this.homeInfo = homeInfo; in controller, and homeController.homeInfo should be undefined in this case.
There's no reason why mocked homeInfo local dependency should be tested. Test what happens in controller instead:
beforeEach(inject(function (_$rootScope_, _$controller_) {
...
brdSubtitleListener = jasmine.createSpy('brdSubtitleListener');
$scope.$on('brdSubtitle', brdSubtitleListener);
homeController = $controller('HomeController', {'$rootScope': $rootScope, '$scope': $scope, homeInfo: { subtitle : 'Welcome to tables, ladders and chairs' }});
}));
it('should broadcast a subtitle', function() {
expect(brdSubtitleListener).toHaveBeenCalledWith(jasmine.any(Object), 'Welcome to tables, ladders and chairs');
});

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();
});
});
});

Properly initialize $scope - having error : "Expected undefined to be defined"

I need help, been searching and thinking for hours but didn't come up with a good solution. I am experiencing error "Expected undefined to be defined" which is repeatedly occurs when I call $scope in my It() functions.
Spec.js
describe("C0001Controller", function(){
var $scope,
$rootScope,
$injector,
$controller,
$httpBackend,
$loading,
C0001Controller;
describe("initialize controllers",function(){
beforeEach(function(){
angular.module('app.c0001App');
})
beforeEach(inject(function(_$rootScope_, _$injector_, _$controller_, _$httpBackend_, _$loading_)
{
$rootScope = _$rootScope_;
$injector = _$injector_;
$controller = _$controller_;
$httpBackend = _$httpBackend_;
$loading = _$loading_;
$scope = $rootScope;
C0001Controller = $controller('C0001Controller', {
$scope: $scope,
$loading : $loading
});
}));
});
it("should use the user ",function(){
var languages = [{id: "en", name: "English"}, {id: "jp", name: "Japanese"}];
expect(languages).toBeDefined();
it("should read if there are languages used", function(){
expect($scope).toBeDefined();
});
describe("checking connection to module and controller", function(){
it("should be connected to module", function(){
expect("app.c0001App.C0001Controller").toBeDefined();
});
it("contains C0001Spec Spec", function(){
expect(true).toBe(true);
});
it("should be equal to user", function(){
var user = {};
var c0001Data = user;
expect(c0001Data).toBe(user);
});
});
});
I was thinking if the format I did in the karma.conf.js file has a mistake.
// list of files / patterns to load in the browser
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app/*.js',
'tests/*.js'
],
here's my Controller.js
angular.module('app.c0001App', [
'ui.router'
])
.config(function($stateProvider) {
$stateProvider.state('/c0001', {
url : '/c0001'
, templateUrl : 'pages/C0001.html'
, data : {
pageTitle: 'LOGIN'
}
});
})
.controller('C0001Controller', function ($rootScope, $scope, $http, $window, $location, $loading) {
var promise = $http.get('changeLanguage.do?lang=en');
promise.success(function(data, status, headers, config) {
//some codes here
Thank you in advance.

expected scope variable undefined in karma test

I'm having trouble understanding how the scope gets initialized in karma tests. i'm expecting a scope variable to be preset when the test runs, but it keeps coming back as undefined.
What am I missing?
Test Case
describe('loginController', function() {
beforeEach(module('app'));
var $controller, $scope;
beforeEach(inject(function(_$controller_, $rootScope){
$controller = _$controller_;
$scope = $rootScope.$new();
}));
describe('$scope.login', function() {
beforeEach(function() {
controller = $controller('loginController', { $scope: $scope });
});
it('checks it initialized', function() {
expect($scope.foo).toEqual('foo');
expect($scope.bar).toEqual('bar');
//expect($scope).toBeDefined();
//expect($scope.loginData.userName).toEqual('');
//expect($scope.loginData.password).toEqual('');
});
The controller:
angular.module('app').controller('loginController', ['$location',
'authService', function($scope, $location, authService) {
$scope.foo = 'foo';
$scope.bar = 'bar';
$scope.loginData = {
userName: '',
password: ''
};
}]);
I refactored the test code and now it works:
describe('loginController', function() {
beforeEach(module('app'));
var controller, scope;
beforeEach(inject(function($controller, $rootScope){
scope = $rootScope.$new();
console.log('scope1', scope);
controller = $controller('loginController', {
$scope: scope
});
}));
describe('login', function() {
it('sets variables ', function() {
expect(scope).toBeDefined();
expect(scope.loginData).toBeDefined();
expect(scope.loginData.userName).toEqual('');
expect(scope.loginData.password).toEqual('');
});
});
});
try injecting $controller to the function where you instantiate the controller:
beforeEach(inject(function($controller) {
controller = $controller('loginController', { $scope: $scope });
}));

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");
});
});
});

Error: [$injector:unpr] Unknown provider in jasmine test when routeprovider service is injected in a controller

I have created an application in angular js, in which i am using ng-view for navigating templates, from routeProvider i am injecting a service called customerDetail to all templates. when i wrote a jasmine testcase for injecting customerDetail services into the CustomerReportController constructor, but i am getting
<failure type="">Error: [$injector:unpr] Unknown provider: customerDetailProvider <- customerDetail
can anyone please tell me some solution for this
main/customerReport/main.spec.js
describe('tsi', function()
{
var $scope, customerDetail;
beforeEach(module('tsi.customerReport'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
CustomerReportController = $controller('CustomerReportController', {
$scope: $scope,
customerDetail: customerDetail
});
}));
it('test CustomerReportController', inject(function() {
expect(CustomerReportController).toBeTruthy();
}));
});
main.js
angular.module( 'tsi', ['tsi.customerDetail', 'ngRoute'])
.config(function(RestangularProvider, $routeProvider)
{
RestangularProvider.setBaseUrl('/customer/service/detail');
$routeProvider.when('/customerDetail',
{
templateUrl: 'main/main.tpl.html',
controller: 'CustomerDetailController',
resolve: {
customerDetail: function(CustomerDetailService) {
return CustomerDetailService.getServiceDetail();
}
}
}).when('/customerReport',
{
templateUrl: 'main/customerReport/main.tpl.html',
controller: 'CustomerReportController',
resolve: {
customerDetail: function(CustomerDetailService) {
return CustomerDetailService.getServiceDetail();
}
}
}).otherwise(
{
redirectTo: '/customerDetail'
});
})
.factory('CustomerDetailService', function(Restangular) {
return {
getCustomerDetail: function() {
return Restangular.one('user/customerDetail').get().then(function(customerDetail) {
return customerDetail;
});
}
};
});
main/customerReport/main.js
angular.module('tsi.customerReport', [])
.controller('CustomerReportController', function($scope, $http, $filter, $timeout, customerDetail)
{
$scope.customerOrderDetails = customerDetail;
:
:
});
the same problem faced by me..
what I did was that I included all the services there in my js file. make sure all the services and providers are injected properly
here is an example code for jasmine unit testing.
describe('UserService',function() {
var scope, DataService, UserService, http, cookieStore;
beforeEach(module('app'));
beforeEach(inject(function ($http, _DataService_) {
http = $http;
DataService = _DataService_;
}));
it('getProfilePicture', function () {
http.post('/api/getProfilePicture', function (data) {
expect(data).toBeDefined();
});
});
});
DataService is my service here

Categories