Mock not being used in Unit Test - angularjs

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.

Related

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

Error in spec file.Tests failing

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.

Unit testing- $state.includes error is blocking other tests /how to mock state

I am trying to unit test the init function of this controller.I cannot find a way of doing this and keep getting the error
TypeError: 'undefined' is not a function (evaluating '$state.includes('profile.details')')
My main concern is to mock the state so that this error goes away and my other tests can pass and then I will focus on writing the test for the init statement. I have tried mocking the state as a string and using transitionTo, has anyone else found a way of testing includes for states?
var init = function () {
$scope.global = global;
$scope.partialViews = {
personForm: "/app/users/views/details/_personForm.html",
passwordForm: "/app/users/views/details/_passwordForm.html"
};
if (!$state.includes('profile.details') && !$state.includes('profile.organizations')) {
if (global.activeProfile.defaultOrganizationId) {
$state.go("dashboard.notifications", { orgId: global.activeProfile.defaultOrganizationId });
} else {
$state.go("profile.organizations");
}
}
};
As an aside I went back to reading the docs to see how the .includes method works in hopes that it would help me figure out what I am doing wrong in my unit tests. in the MDN docs the .includes example is [1, 2, 3].includes(2); but typing this into the console responded with a
Uncaught TypeError: undefined is not a function
why is that?
my tests:
beforeEach(module('pb.users.controllers'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var mockUserService = {};
var mockOrganizationService = {};
var mockPersonInvitationService = {};
var mockStateParams = {};
var mockState = "profile.details";
var mockGlobal = {};
var mockForm = {};
var mockModal = {};
var invitation = {};
beforeEach(inject(function ($q) {
invitation = {
organizationId: 6542643
};
mockForm = {
submitIfValid: function (promiseHandler) {
return promiseHandler();
}
};
mockStateParams = {
accountId: 7672891,
entityId: 532,
orgId: 67,
page: 43,
length: 12
};
mockGlobal = {
setFormSubmitInProgress: function (boolean) {
this.formProgress = boolean;
},
formProgress: false,
activeOrganizationId: 432,
organizationsUpdated: function () {
return "updated!"
}
};
mockUserService = {
user: {
person: {
name: 'Regan Perkins'
}
},
getUser: function () {
var defer = $q.defer();
defer.resolve(this.user);
return defer.promise;
},
updateExtendedInfo: function (person) {
var defer = $q.defer();
defer.resolve(this.user);
return defer.promise;
}
};
mockOrganizationService = {
organizations: {
groups: ["PressBoard", "MySite"]
},
getOrganizations: function () {
var defer = $q.defer();
defer.resolve(this.organizations);
return defer.promise;
}
};
mockPersonInvitationService = {
invitations: ["invite one", "invite two"],
getInvitations: function () {
var defer = $q.defer();
defer.resolve(this.invitations);
return defer.promise;
},
acceptInvitation: function (organizationId) {
var defer = $q.defer();
defer.resolve(invitation);
return defer.promise;
}
};
}));
beforeEach(inject(function ($rootScope, _$controller_) {
scope = $rootScope.$new();
$controller = _$controller_;
controller = $controller('ProfilesController', {
$scope: scope,
$stateParams: mockStateParams,
$state: mockState,
$modal: mockModal,
global: mockGlobal,
userService: mockUserService,
organizationService: mockOrganizationService,
personInvitationService: mockPersonInvitationService
});
}));
describe('init() function', function () {
it('should set activeOrganizationId', function () {
expect(scope.global.activeOrganizationId).toEqual(mockGlobal.activeOrganizationId);
});
it('should set global', function () {
expect(scope.global).toEqual(mockGlobal);
});
});
describe('get() function', function () {
it('should resolve a promise', function () {
scope.get();
scope.$digest();
expect(scope.person).toEqual(mockUserService.user.person);
});
});
describe("edit() function", function () {
it("should toggle personFormSuccess", function () {
spyOn(mockUserService, "updateExtendedInfo").and.callThrough();
scope.edit(mockForm, mockUserService.user);
expect(mockUserService.updateExtendedInfo).toHaveBeenCalledWith(mockUserService.user);
});
it("should call updateExtendedInfo()", function () {
spyOn(mockUserService, "updateExtendedInfo").and.callThrough();
scope.edit(mockForm, mockUserService.user);
expect(scope.personFormSuccess).toBe(false);
scope.$digest();
expect(scope.personFormSuccess).toBe(true);
});
});
describe('getOrganizations() function', function () {
it('should resolve a promise', function () {
scope.getOrganizations();
scope.$digest();
expect(scope.organizations).toEqual(mockOrganizationService.organizations);
});
});
describe('getInvitations() function', function () {
it('should resolve a promise', function () {
scope.getInvitations();
scope.$digest();
expect(scope.invitations).toEqual(mockPersonInvitationService.invitations);
});
});
describe('acceptInvitation() function', function () {
it('should toggle form progress', function () {
scope.invitations = mockPersonInvitationService.invitations;
scope.acceptInvitation(invitation, 1);
scope.$digest();
expect(scope.invitations).toEqual(mockPersonInvitationService.invitations);
});
it('should resolve a promise', function () {
scope.invitations = mockPersonInvitationService.invitations;
scope.acceptInvitation(invitation, 1);
scope.$digest();
expect(scope.invitations).toEqual(mockPersonInvitationService.invitations);
});
it('should resolve a promise', function () {
scope.invitations = mockPersonInvitationService.invitations;
scope.acceptInvitation(invitation, 1);
scope.$digest();
expect(scope.invitations).toEqual(['invite one']);
});
});
describe("openRejectInvitation() function", function () {
var actualOptions;
var modalOptions = {
templateUrl: '/app/users/views/organizations/_removeInvite.html',
controller: 'RejectInvitationModalController',
resolve: {
invitation: function () {
return invitation;
}
}
};
beforeEach(inject(function ($injector, $q) {
mockModal.open = function (options) {
actualOptions = options;
var defer = $q.defer();
defer.resolve();
return { result: defer.promise };
}
}));
it("make sure modalInstance.result.then is executed", function () {
scope.invitations = mockPersonInvitationService.invitations;
scope.openRejectInvitation(invitation, 1);
expect(scope.invitations).toEqual(['invite one', 'invite two']);
scope.$digest();
expect(scope.invitations).toEqual(['invite one']);
});
it("make sure modal.open is called", function () {
spyOn(mockModal, 'open').and.callThrough();
scope.openRejectInvitation(invitation, 1);
expect(mockModal.open).toHaveBeenCalledWith(actualOptions);
});
it("make sure 'webSite' is passed by modalInstance.resolve", function () {
scope.openRejectInvitation(invitation, 1);
expect(actualOptions.resolve.invitation()).toEqual(invitation);
});
});
});
Incase this helps anyone else with this problem the way I was able to bypass this error was to mock the includes method on my mockState.
var mockState = {
includes: function (string) {
return false
}
};

testing controller containing $scope.$on

I am looking to test these two functions in my modal controller but Im not sure how to test $scope.$on functions. does anyone have any ideas?
$scope.$on("filesUploaded", function (e, files) {
for (var i = 0; i < files.length; i++) {
$scope.images.items.unshift(files[i]);
}
$scope.images.total += files.length;
});
$scope.$on("filesUploadCompleted", function () {
if (!$scope.$$phase) $scope.$apply();
});
my full test set up so far is:
describe('pbImagePickerModalController', function () {
beforeEach(module('pb.campaigns.controllers'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
//var mockWindow = {};
//var mockDocument = {};
var mockState = {};
var mockModal = {};
var mockGlobal = {};
var mockStateParams = {};
var mockAccountFileService = {};
var continuationToken = {};
beforeEach(inject(function ($q) {
mockStateParams = {
accountId: 543,
length: 12
};
mockGlobal = {
setFormSubmitInProgress: function (boolean) {
this.formProgress = boolean;
},
formProgress: false,
activeOrganizationId: 0
};
mockModalInstance = {
close: jasmine.createSpy('mockModalInstance.close'),
dismiss: jasmine.createSpy('mockModalInstance.dismiss'),
result: {
then: jasmine.createSpy('mockModalInstance.result.then')
}
};
mockAccountFileService = {
getFiles: function (activeOrganizationId, accountId, length, continuationToken) {
var defer = $q.defer();
defer.resolve(images);
return defer.promise;
}
};
}));
beforeEach(inject(function ($rootScope, _$controller_) {
scope = $rootScope.$new();
$controller = _$controller_;
controller = $controller('pbImagePickerModalController', {
$scope: scope,
$state: mockState,
$stateParams: mockStateParams,
global: mockGlobal,
accountFileService: mockAccountFileService,
$modal: mockModal,
$modalInstance: mockModalInstance,
//$window: mockWindow,
//$document: mockDocument,
accountId: mockStateParams.accountId
//accountId: function () {
// return mockStateParams.accountId;
//}
});
}));
describe("init() function", function () {
it('should call getImages()', function () {
spyOn(scope, 'getImages');
expect(scope.getImages).toHaveBeenCalledWith(50);
});
});
describe("getImages() function", function () {
it('should call getFiles with proper params', function () {
spyOn(mockAccountFileService, 'getFiles').and.callThrough();
scope.getImages(mockStateParams.length, continuationToken);
scope.$digest();
expect(mockAccountFileService.getFiles).toHaveBeenCalledWith(mockGlobal.activeOrganizationId, mockStateParams.accountId, mockStateParams.length, continuationToken);
});
it('should assign scope.images to promise result if scope.images does not exist', function () {
scope.getImages(mockStateParams.length, continuationToken);
scope.$digest();
expect(scope.images).toEqual(mockAccountFileService.images);
});
describe('with existing images', function () {
beforeEach(function () {
var existingLinks = {
continuationToken: 0002,
total: 2,
items: ['sponser_image01.png', 'sponser_image02.png']
};
scope.images = existingLinks;
});
it('should assign promise continuationToken to scope.images.continuationToken if scope.images exists', function () {
scope.getImages(mockStateParams.length, continuationToken);
scope.$digest();
expect(scope.images.continuationToken).toEqual(mockAccountFileService.images.continuationToken);
});
it('should assign promise data and existing images to scope if scope.images exists', function () {
scope.getImages(mockStateParams.length, continuationToken);
scope.$digest();
expect(scope.images.total).toEqual(4);
});
it('should push exisiting campaign links to link Array', function () {
scope.getImages(mockStateParams.length, continuationToken);
scope.$digest();
expect(scope.images.items).toEqual(['sponser_image01.png', 'sponser_image02.png', 'sponser_image03.png', 'sponser_image04.png']);
});
});
});
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);
});
});
});
and my full controller is:
angular.module('pb.campaigns.controllers')
.controller('pbImagePickerModalController', ['$window', '$scope', '$document', '$modal', '$modalInstance', 'global', 'accountId', 'accountFileService', function ($window, $scope, $document, $modal, $modalInstance, global, accountId, accountFileService) {
$scope.currentAccountId = accountId;
var init = function () {
$scope.getImages(50);
};
$scope.getImages = function (length, continuationToken) {
// show all existing images
accountFileService.getFiles(global.activeOrganizationId, accountId, length, continuationToken).then(function (data) {
if ($scope.images) {
$scope.images.continuationToken = data.continuationToken;
$scope.images.total += data.total;
angular.forEach(data.items, function (value, key) {
$scope.images.items.push(data.items[key]);
});
} else {
$scope.images = data;
}
});
};
init();
$scope.$on("filesUploaded", function (e, files) {
for (var i = 0; i < files.length; i++) {
$scope.images.items.unshift(files[i]);
}
$scope.images.total += files.length;
});
$scope.$on("filesUploadCompleted", function () {
if (!$scope.$$phase) $scope.$apply();
});
//$scope.add = function (accountId, file) {
// global.setFormSubmitInProgress(true);
// accountFileService.createFile(global.activeOrganizationId, accountId, file).then(function () {
// global.setFormSubmitInProgress(false);
// $modalInstance.close();
// },
// function (errorData) {
// global.setFormSubmitInProgress(false);
// });
//};
$scope.select = function (image) {
$modalInstance.close(image);
};
$scope.cancel = function () {
global.setFormSubmitInProgress(false);
$modalInstance.dismiss('cancel');
};
}]);
You could test it with rootScope itself.
Example:-
$rootScope.$broadcast('filesUploaded', fileListStub); //broadcast the event with stub data
scope.$digest(); //Triger digest cycle to invoke on handler
expect(scope.images.total).toEqual(fileListStub.length+whateverinitialcount);
Demo

Need help completing unit test for angular $modal

I am trying to get the "make sure modalInstance.result.then is executed" test in my code to pass. Right now it says Expected [ undefined, 'http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com' ] to contain 'http://www.pressboardmedia.com' I believe this has something to do with the promise needing to be mocked so it passes along the campaignLink but I am unsure if this is the problem and cannot seem to get it to work regardless. please let know if you have any ideas.
Thanks!
Controller File
angular.module('pb.campaignLinks.controllers')
.controller('CampaignLinksController', ['$scope', '$timeout', '$modal', '$stateParams', 'global', 'campaignLinkService', function ($scope, $timeout, $modal, $stateParams, global, campaignLinkService) {
$scope.init = function (currentView) {
$scope.partialViews = {
campaignLinkList: "/app/campaignLinks/views/_list.html",
};
$scope.currentView = currentView;
$scope.getCampaignLinks(currentView, 10);
};
$scope.getCampaignLinks = function (currentView, length, continuationToken) {
// When loading list items, display loading image
if ($scope.campaignLinks) $scope.campaignLinks.loading = true;
var promiseObj = null;
if (currentView.campaignId && currentView.campaignId !== 0 && !currentView.buyRequestId) {
promiseObj = campaignLinkService.getCampaignLinks(global.activeOrganizationId, currentView.campaignId, length, continuationToken)
} else if (currentView.campaignId && currentView.buyRequestId && currentView.campaignId !== 0 && currentView.buyRequestId !== '') {
promiseObj = campaignLinkService.getCampaignBuyRequestLinks(global.activeOrganizationId, currentView.campaignId, currentView.buyRequestId, length, continuationToken);
} else if (currentView.webSiteId && currentView.buyRequestId && currentView.webSiteId !== 0 && currentView.buyRequestId !== '') {
promiseObj = campaignLinkService.getWebSiteBuyRequestLinks(global.activeOrganizationId, currentView.webSiteId, currentView.buyRequestId, length, continuationToken);
}
if (promiseObj) {
promiseObj.then(function (data) {
// If there are already some campaign links being displayed, add newly loaded list to the end
if ($scope.campaignLinks) {
$scope.campaignLinks.continuationToken = data.continuationToken;
$scope.campaignLinks.total += data.total;
$.each(data.items, function (index) {
$scope.campaignLinks.items.push(data.items[index]);
});
} else {
// Otherwise add loaded list to scope
$scope.campaignLinks = data;
}
// When done loading, hide loading image
$scope.campaignLinks.loading = false;
});
}
};
$scope.openAddCampaignLink = function (campaignId) {
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_add.html',
controller: 'AddCampaignLinksModalController',
resolve: {
campaignId: function () {
return campaignId;
}
}
};
var modalInstance = $modal.open(modalOptions);
modalInstance.result.then(function (campaignLink) {
// Add new item to list, otherwise wait for it to be loaded manually.
$scope.campaignLinks.items.unshift(campaignLink);
$scope.campaignLinks.total += 1;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
$scope.openRemoveCampaignLink = function (campaignId, campaignLink, index) {
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_delete.html',
controller: 'RemoveCampaignLinksModalController',
resolve: {
campaignId: function () {
return campaignId;
},
campaignLink: function () {
return campaignLink;
}
}
};
var modalInstance = $modal.open(modalOptions);
modalInstance.result.then(function () {
// Splice the deleted item from the list without reloading all
$scope.campaignLinks.items.splice(index, 1);
$scope.campaignLinks.total -= 1;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
// Once everything is loaded, initialize controller
// init();
}]);
Test file:
describe('CampaignLinksController', function () {
//make module avalible to tests
beforeEach(module('pb.campaignLinks.controllers'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var $controller;
var mockPromiseObj;
var length = 200;
var mockModal = {};
var mockCampaignLinks = {
total: 3,
items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
};
var mockCurrentView = {};
var mockGlobal = { activeOrganizationId: 54 };
var continuationToken = {
nextRowKey: 'fdsf2',
nextPartitionKey: '5432gee'
};
var campaignDetails = {
campaignId: 453,
campaignLink: 'http://www.pressboardmedia.com',
index: 1
};
var mockCampaignLinkService = {
//move campaignDetails here
campaignLinks: {
total: 3,
//length here
items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
},
//all but delete must return a promiseObj
getCampaignLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignLinks').and.returnValue(mockPromiseObj),
getCampaignBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignBuyRequestLinks').and.returnValue(mockPromiseObj),
getWebSiteBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getWebSiteBuyRequestLinks').and.returnValue(mockPromiseObj),
deleteCampaignLink: jasmine.createSpy('mockCampaignLinkService.deleteCampaignLinks')
};
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
beforeEach(inject(function ($rootScope) {
controller = $controller('CampaignLinksController',
{
$scope: scope,
$modal: mockModal,
//$stateParams: mockStateParams,
global: mockGlobal,
campaignLinks: mockCampaignLinks,
campaignLinkService: mockCampaignLinkService,
currentVeiw: mockCurrentView,
//promiseObj: mockPromiseObj
});
}));
describe('openAddCampaignLink()', function () {
var actualOptions;
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_add.html',
controller: 'AddCampaignLinksModalController',
resolve: {
campaignId: jasmine.any(Function)
}
};
beforeEach(inject(function ($q) {
mockModal.open = function (options) {
actualOptions = options;
var defer = $q.defer();
defer.resolve();
return { result: defer.promise };
}
}));
it("make sure modalInstance.result.then is executed", function () {
scope.campaignLinks = mockCampaignLinkService.campaignLinks;
scope.openAddCampaignLink(campaignDetails.campaignId, campaignDetails.campaignLink, campaignDetails.index);
scope.$digest();
expect(scope.campaignLinks.total).toEqual(4);
expect(scope.campaignLinks.items).toContain(campaignDetails.campaignLink);
});
});
I think your problem is that the argument "campaignLink" that is supplied to your modalInstance.result.then function will always be undefined when you test this. The code that calls the modal close should be tested that it is supplying the campaignLink correctly. You only want to test that the proper code gets executed when the modal is closed. We do that by supplying a function that can be tested on it's own to the modalInstance.result.then call instead of doing an inline function so it can be tested easier.
Here's an example:
Here's the code that opens the modal:
$scope.editGradeClick = function () {
var modalInstance = $modal.open({
templateUrl: templateSrv.templateUrl('/Templates/App/Courses/CourseLessonGradeModal.html'),
controller: courseLessonGradeModalBootstrap,
backdrop: 'static',
keyboard: false,
resolve: {
data: $scope.editGradeModalResolve
}
});
modalInstance.result.then(
null,
$scope.editGradeModalDismissCallback
);
};
Notice how we supply a function $scope.editGradeModalDismissCallback instead of writting an inline function there for a modal dismiss. This allows us to test that logic in it's own test.
Now here is the test. We only care that the above function was called since we will be testing the specific function in it's own test. That happens at the last line in the test.
var $controllerConstructor, $scope, $q;
beforeEach(function () {
module('appModule');
inject(function ($controller, $rootScope, _$q_) {
$controllerConstructor = $controller;
$scope = $rootScope.$new();
$q = _$q_;
});
});
it('should execute $scope.editGradeModalDismissCallback when modal is dismissed', inject(function (templateSrv) {
var $modal = {};
$modal.open = function () {
var queryPromise = $q.defer();
queryPromise.reject();
return { result: queryPromise.promise };
};
$controllerConstructor('CourseLessonGradeListCtrl', { $scope: $scope, $modal: $modal, templateSrv: templateSrv});
spyOn($modal, "open").andCallThrough();
spyOn($scope, "editGradeModalDismissCallback");
$scope.editGradeClick();
$scope.$root.$digest();
expect($scope.editGradeModalDismissCallback).toHaveBeenCalled();
}));
I hope this helps you. In this example we are rejecting the promise because we are testing the modal dismiss not close, fyi...

Resources