Error in spec file.Tests failing - angularjs

Controller code
var dashboardApp = angular.module('do.dashboard', [])
dashboardApp.controller('developerSummaryController', ['$scope', '$filter', '$routeParams', 'developerSummaryService',
function ($scope, $filter, $routeParams, summaryBoardService) {
$scope.group = {};
var _getStatusText = function (statusValue) {
return statusValue <= 33 ? 'RED' : (statusValue <= 66 ? 'YELLOW' : (statusValue <= 100 ? 'GREEN' : 'GREEN'))
}
var _parseSummaryData = function (summaryValue) {
summaryValue.OverallStatusText = _getStatusText(summaryValue.OverallStatus);
summaryValue.BuildUTStatusText = _getStatusText(summaryValue.UnitTesting);
summaryValue.CodeQualityStatusText = _getStatusText(summaryValue.CodeQuality);
summaryValue.Deploy.DevStatusText = _getStatusText(summaryValue.Deploy.Dev);
summaryValue.Deploy.QAStatusText = _getStatusText(summaryValue.Deploy.QA);
summaryValue.Deploy.ProdStatusText = _getStatusText(summaryValue.Deploy.Production);
angular.forEach(summaryValue.Components, function (componentValue, componentKey) {
componentValue.OverallStatusText = _getStatusText(componentValue.OverallStatus);
componentValue.BuildUTStatusText = _getStatusText(componentValue.UnitTesting);
componentValue.CodeQualityStatusText = _getStatusText(componentValue.CodeQuality);
componentValue.Deploy.DevStatusText = _getStatusText(componentValue.Deploy.Dev);
componentValue.Deploy.QAStatusText = _getStatusText(componentValue.Deploy.QA);
componentValue.Deploy.ProdStatusText = _getStatusText(componentValue.Deploy.Production);
componentValue.BuildTime = $filter('date')(componentValue.BuildTime, 'yyyy-MM-dd HH:mm:ss a');
});
return summaryValue;
}
summaryBoardService.getSummaryBoardData($routeParams.groupName).then(
function success(response) {
$scope.group = _parseSummaryData(response.data);
}, function error(reason) {
console.log(reason);
});
} ]);
Spec
describe('developerSummaryController', function () {
var scope, ctrl, mockSefService, $timeout;
beforeEach(module('do.dashboard'));
beforeEach(inject(function ($rootScope, $controller, $q, _$timeout_) {
mockSefService = jasmine.createSpyObj('developerSummaryService', ['getSummaryBoardData']);
scope = $rootScope.$new();
$timeout = _$timeout_;
mockSefService.getSummaryBoardData.and.returnValue($q.when(
{data: { Name: 'Client Management', OverallStatus: 15.777499999999998, CodeQuality: 10.5, UnitTesting: 28.5, CodeCoverage: 8.3325 }}
));
ctrl = $controller('developerSummaryController', {
$scope: scope,
developerSummaryService: mockSefService,
$routeParams: { id: 'Client Management' }
});
}));
it('controller should not be null', function () {
expect(ctrl).not.toBe(null);
});
it('should set the scope data with route parameter', function () {
expect(scope.groupName).toEqual('Client Management');
});
it('should call the service method and set the scope data', function () {
expect(mockSefService.getSummaryBoardData).toHaveBeenCalled();
$timeout.flush();
expect(scope.group.Name).toEqual('Client Management');
expect(scope.group.OverallStatus).toEqual(15.777499999999998);
expect(scope.group.CodeQuality).toEqual(10.5);
});
});
Here the Controller i have written tests the last two are failing always can anyone tel the solution or what i might doing wrong here.
here the controller file having a Json which is called form a service i am only creating unit tests for the controller.

Related

defining current state in unit tests

I've moved this 'reports' feature from a single module (called 'aam') into the core, so that other modules (such as 'bbc') can use it.
Now I'm rewriting the unit test(s).
The grunt error I'm getting is
should go state aam.reports with URL_NOT_SPECIFIED
reports-state spec
TypeError: 'null' is not an object
(evaluating 'BbpcConfiguration.getProperty(configProperty).then')
which indicates to me that $state is empty or not structured correctly.
Here is the report controller:
(function() {
'use strict';
angular.module('com.ct.bbpcCore')
.controller('reportController', ['$window', '$state', 'BbpcUserService', 'BbpcConfiguration', function ($window, $state, BbpcUserService,BbpcConfiguration) {
angular.element(document).ready(function () {
//Get url base on locale
var reportUrl = "URL_NOT_SPECIFIED";
var currentState = $state.current.name;
var configProperty = "";
var title = "";
if (currentState.indexOf('aam.reports')) {
configProperty = 'report.aam.link';
title = "AAM.REPORT";
};
if (currentState.indexOf('bbc.reports')) {
configProperty = 'report.bbc.link';
title = "BBC.REPORT";
};
BbpcConfiguration.getProperty(configProperty).then(function(response) {
if (response) {
var language = BbpcUserService.getLanguageCd() || "en_CA";
reportUrl = response[language] || reportUrl;
}
var spec = "width=" + $window.outerWidth + ", height=" + $window.outerHeight;
$window.open(reportUrl, title, spec);
});
});
}]);
}());
And here is report-controller.spec:
describe('reports-state spec', function() {
'use strict';
var $injector, $window, $rootScope,
$state, BbpcConfiguration, reportController, $controller, BbpcUserService;
beforeEach(function() {
module('com.ct.bbpcCore', function($provide) {
$provide.value('BbpcConfiguration', BbpcConfiguration = {
getProperty: function(key){
if('report.aam.link' === key){
return {
"fr_CA": "https://eng-link",
"en_CA": "https://fre-link"
};
}
return null;
}
});
});
inject(function(_$injector_) {
$injector = _$injector_;
$window = $injector.get('$window');
$state = $injector.get('$state');
$rootScope = $injector.get('$rootScope');
$controller =$injector.get('$controller');
BbpcUserService =$injector.get('BbpcUserService');
});
});
it('should go state aam.reports with URL_NOT_SPECIFIED', function() {
$state.current = {'name': 'aam.reports' };
spyOn($window, 'open').andCallFake(function(){});
reportController = $controller('reportController', {'$window':$window, '$state':$state, 'BbpcUserService':BbpcUserService, 'reportLink':undefined});
$state.go('aam.reports');
$rootScope.$apply();
expect($state.current.name).toEqual('aam.reports');
expect($window.open).toHaveBeenCalledWith('URL_NOT_SPECIFIED', 'AAM.REPORT', 'width=0, height=0');
});
});
I tried simply adding the line $state.current = {'name': 'aam.reports' }; in the 'it' block, but that's not what it's looking for.
Not sure how to debug unit tests. :P I can't use a console.log($state) to peek into it.

Passing one of the parameters in constructor to unit test

I am trying to get/set "testModel.number" in my unit test but I can't seem to get it. When I run the test I get this error message:
Error: [$injector:unpr] Unknown provider: testModelProvider <- testModel
Here is the controller:
angular.module("TestApp", [])
.controller("IndexController", function ($scope, testModel) {
$scope.name = "test";
testModel = {
number: 0
}
if (testModel.number === 1) {
$scope.name = "test1";
} else {
$scope.name = "test2";
}
});
Here is the unit test:
describe('IndexController', function () {
var scope, createController;
beforeEach(module("TestApp"));
beforeEach(inject(function ($rootScope, $controller, testModel) {
scope = $rootScope.$new();
createController = function () {
return $controller('IndexController', {
'$scope': scope,
'testModel': testModel
})
}
}));
it('example test', function () {
var controller = createController();
testModel.number = 1;
expect(scope.name).toBe('test1');
});
});
I'm fairly new to unit testing so any suggestions would be great! Thanks in advance!
I think you need to pass the testModel object to the method creating the controller. Jasmine does not know how to inject custom providers.
describe('IndexController', function () {
var scope, createController;
beforeEach(module("TestApp"));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function (testModel) {
return $controller('IndexController', {
'$scope': scope,
'testModel': testModel
})
}
}));
it('example test', function () {
var testModel = { number: 1 };
var controller = createController(testModel);
expect(scope.name).toBe('test1');
});
});
If you will have multiple tests that will need the testModel object, you can also define it at a global level as follows:
describe('IndexController', function () {
var scope, createController;
var testModel = { number: 1 };
beforeEach(module("TestApp"));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function () {
return $controller('IndexController', {
'$scope': scope,
'testModel': testModel
})
}
}));
it('example test', function () {
var controller = createController();
expect(scope.name).toBe('test1');
});
});

Angular unit testing Controller with service

I'm trying to write a unit test using karma and jasmine for an Angular controller that depends on a service
storesController.js
(function () {
var app = angular.module('storesController', ['storesService']);
app.controller('StoresListController', function ($scope, StoresService) {
$scope.getStores = function () {
StoresService.getStores().then(function (data) {
$scope.stores = data.data;
});
};
$scope.getStores();
$scope.deleteStore = function (id) {
StoresService.deleteStore(id).then(function () {
$scope.getStores();
});
};
});
storesService.js
(function () {
var app = angular.module('storesService', []);
app.factory('StoresService', ['$http', function ($http) {
var stores = [];
stores.getStores = function () {
return $http.get(/api/getStores');
};
stores.deleteStore = function (storeID) {
return $http.delete(/api/deleteStore/'+storeID);
};
return stores;
}]);
})();
And the test,
controllers.spec.js
describe('StoresController', function () {
beforeEach(module('storesController'));
var scope;
var storesServiceMock;
var controller;
beforeEach(inject(function ($controller, $rootScope) {
storesServiceMock = {
getStores: function() {
},
deleteStores: function() {
}
};
spyOn(storesServiceMock, 'getStores').and.returnValue({name : 'TestName', country : 'TestCountry'})
scope = $rootScope.$new();
controller = $controller('StoresListController', {
$scope: scope, StoresService: storesServiceMock
});
}));
it('scope.stores should be defined', function () {
expect(scope.stores).toBeDefined;
});
});
And I'm getting
TypeError: StoresService.getStores(...).then is not a function at n.$scope.getStores
I've also tried width httpBackend but I'm not be able to make it work, any clue about what I'm doing wrong?
Have the spy return a promise.
With ES2015:
spyOn(storesServiceMock, 'getStores').and.returnValue(Promise.resolve({name : 'TestName', country : 'TestCountry'}));
With $q:
spyOn(storesServiceMock, 'getStores').and.callFake(function() {
var deferred = $q.defer();
deferred.resolve({name : 'TestName', country : 'TestCountry'}));
return deferred.promise;
});

Mock not being used in Unit Test

I am stumped. I have written modal tests a few times now but in the controller I am currently testing I keep getting a TypeError: 'undefined' is not a function (evaluating 'pressReleaseCampaignService.deleteCampaign(global.activeOrganizationId, accountId, campaign.entityId) error. I want the test to use my mock however and Im not sure why it keep referencing the original controller. Does anyone see my mistake?
Controller:
angular.module('pb.campaigns.controllers')
.controller('ConfirmDeleteModalController', ['$scope', '$stateParams', '$state', '$modal', '$modalInstance', 'global', 'pbRoles', 'campaign', 'accountId', 'pressReleaseCampaignService',
function ($scope, $stateParams, $state, $modal, $modalInstance, global, pbRoles, pressReleaseCampaignService, campaign, accountId) {
$scope.campaign = campaign;
$scope.currentAccountId = accountId;
$scope.delete = function (accountId, campaign) {
global.setFormSubmitInProgress(true);
pressReleaseCampaignService.deleteCampaign(global.activeOrganizationId, accountId, campaign.entityId).then(function () {
global.setFormSubmitInProgress(false);
$modalInstance.close();
},
function (errorData) {
global.setFormSubmitInProgress(false);
});
};
$scope.cancel = function () {
global.setFormSubmitInProgress(false);
$modalInstance.dismiss('cancel');
};
}]);
Test:
describe('ConfirmDeleteModalController', function () {
beforeEach(module('pb.roles'));
beforeEach(module('pb.campaigns.controllers'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var mockModalInstance = {};
var mockcampaignBuyRequestService = {};
var mockGlobal = {};
var mockStateParams = {};
var mockState = {};
var mockPbRoles = {};
beforeEach(inject(function ($q) {
mockGlobal = {
setFormSubmitInProgress: function (boolean) {
this.formProgress = boolean;
},
formProgress: false,
activeOrganizationId: 0
};
mockStateParams = {
orgId: 1,
accountId: 3,
entityId: 94,
campaignId: 45,
page: 3,
length: 12
};
mockModalInstance = {
close: jasmine.createSpy('mockModalInstance.close'),
dismiss: jasmine.createSpy('mockModalInstance.dismiss'),
result: {
then: jasmine.createSpy('mockModalInstance.result.then')
}
};
mockPressReleaseCampaignService = {
campaign: { entityId: 2, page: 19, length: 200 },
deleteCampaign: function (activeOrganizationId, entityId) {
var defer = $q.defer();
defer.resolve();
return defer.promise;
}
};
}));
beforeEach(inject(function ($rootScope, _$controller_) {
scope = $rootScope.$new();
$controller = _$controller_;
controller = $controller('ConfirmDeleteModalController', {
$modalInstance: mockModalInstance,
$scope: scope,
$stateParams: mockStateParams,
$state: mockState,
global: mockGlobal,
pbRoles: mockPbRoles,
pressReleaseCampaignService: mockPressReleaseCampaignService,
campaign: function () {
return mockPressReleaseCampaignService.campaign
},
accountId: function () {
return mockPressReleaseCampaignService.accountId
}
});
}));
describe("delete() function", function () {
it("calls deleteCampaign with proper params", function () {
spyOn(mockPressReleaseCampaignService, "deleteCampaign").and.callThrough();
scope.delete(mockStateParams.accountId, mockPressReleaseCampaignService.campaign);
expect(mockPressReleaseCampaignService.deleteCampaign).toHaveBeenCalledWith(mockGlobal.activeOrganizationId, mockStateParams.accountId, mockPressReleaseCampaignService.campaign.entityId);
});
it("calls close and toggles setFormSubmitionInProgress status", function () {
scope.delete(mockStateParams.accountId, mockPressReleaseCampaignService.campaign);
expect(mockGlobal.formProgress).toEqual(true);
scope.$digest();
expect(mockModalInstance.close).toHaveBeenCalled();
expect(mockGlobal.formProgress).toEqual(false);
});
});
describe("cancel() function", function () {
it("changes formProgress from true to false", function () {
mockGlobal.setFormSubmitInProgress.formProgress = true;
scope.cancel();
expect(mockModalInstance.dismiss).toHaveBeenCalled();
expect(mockGlobal.formProgress).toEqual(false);
});
});
});
The order of the service names is not the same as the order of the variables:
'campaign', 'accountId', 'pressReleaseCampaignService'
vs.
pressReleaseCampaignService, campaign, accountId
So, when your code calls a method on pressReleaseCampaignService, it actually calls a method on the campaign service.

Angular Unit Test Jasmine Spy error

The following controller is getting a TypeError: 'undefined' is not a function (evaluating sessionService.getCurrentPlace()). I have a Mock Service with that method being spied on. The other method on the mock service works fine. I've tried .AndReturns({..}) on the spy as well as .AndCallThrough() but no luck. Any idea what I'm missing, or am I going about this wrong? Much Thanks!
CONTROLLER:
'use strict';
angular.module('wallyApp')
.controller('addGatewayCtrl', function ($scope, $location, $filter, sessionService) {
/*
private members
*/
//set scope from session data
$scope.processSession = function (places) {
$scope.currentPlaceId = sessionService.getCurrentPlace();
if (!$scope.currentPlaceId) {
$scope.currentPlaceId = places[0].id;
}
$scope.place = $filter("getById")(places, $scope.currentPlaceId);
$scope.ready = true;
};
/*
setup our scope
*/
$scope.currentPlaceId = null;
$scope.place = {};
$scope.videoSrc = "/videos/gateway-poster.gif";
$scope.loaded = true;
/*
setup controller behaivors
*/
//set video or gif to show or hide video
$scope.setVideo = function () {
$scope.videoSrc = "/videos/gateway.gif";
};
$scope.setPoster = function () {
$scope.videoSrc = "/videos/gateway-poster.gif";
};
//initialize scope
$scope.setVideo();
//submit form
$scope.continue = function () {
$location.path("/setup/pair-gateway");
return false;
};
//cancel
$scope.back = function () {
$location.path("/setup/plan-locations");
return false;
};
//wifi
$scope.gotoWifi = function () {
$location.path("/setup/wifi");
return false;
};
/*
setup our services, etc
*/
//get our places from the cache
sessionService.get("places").then(function (places) {
if (!places || places.length < 1) {
sessionService.refreshPlaces(); //Note we don't care about the promise as our broadcast watch will pick up when ready
} else {
$scope.processSession(places);
}
}).catch(function (error) {
//TODO:SSW Call Alert Service??
});
//Watch broadcast for changes
$scope.$on("draco.placesRefreshed", function (event, data) {
sessionService.get("places").then(function (places) {
$scope.processSession(places);
});
});
});
UNIT TEST:
'use strict';
describe('addGatewayCtrl', function () {
var $q,
$rootScope,
$location,
$scope,
$filter,
mockSessionService,
completePath = "/setup/pair-gateway",
backPath = "/setup/plan-locations",
wifiPath = "/setup/wifi",
sessionDeferred,
sessionInitDeferred,
mockPlaces = [{ id: "0001" }];
beforeEach(module('wallyApp'));
beforeEach(inject(function (_$q_, _$rootScope_, _$location_, _$filter_) {
$q = _$q_;
$location = _$location_;
$rootScope = _$rootScope_;
$filter = _$filter_;
}));
beforeEach(inject(function ($controller) {
$scope = $rootScope.$new();
mockSessionService = {
get: function (contact) {
sessionDeferred = $q.defer();
return sessionDeferred.promise;
},
getCurrentPlace: function () {
return mockPlaces[0].id;
},
refreshPlaces: function () {
sessionInitDeferred = $q.defer();
return sessionInitDeferred.promise;
}
};
spyOn(mockSessionService, 'get').andCallThrough();
spyOn(mockSessionService, 'getCurrentPlace').andReturn(mockPlaces[0].id);
spyOn(mockSessionService, 'refreshPlaces').andCallThrough();
$controller('addGatewayCtrl', {
'$scope': $scope,
'$location': $location,
'$filter':$filter,
'sessionService': mockSessionService
});
}));
describe('call session service to get place data ', function () {
//resolve our mock place and session services
beforeEach(function () {
//resolve mocks
sessionDeferred.resolve(mockPlaces);
$rootScope.$apply();
});
//run tests
it('should have called sessionService get places', function () {
expect(mockSessionService.get).toHaveBeenCalledWith("places");
});
it('should have called sessionService get currentPlaceId', function () {
expect(mockSessionService.getCurrentPlace).toHaveBeenCalled();
});
it('should have set scope', function () {
expect($scope.place).toEqual(mockPlaces[0]);
});
});
});
So I figured it out. With nested deferred's you have to call $scope.$apply() in between. The following fixed it up (along with a few minor changes to the mock data responses, but those were trivial):
//resolve promises
activityMessagesDeferred.resolve(mockActivityMessages);
$rootScope.$apply();
$rootScope.$broadcast("draco.sessionRefreshed");
activityCountDeferred.resolve(mockActivityCount);
$rootScope.$apply();
placesDeferred.resolve(mockPlaces);
activityListDeferred.resolve(mockActivities);
$rootScope.$apply();

Resources