How to inject a controller in angularjs test? - angularjs

I am new to angular and TDD in general and I have been trying to debug some one else's code; the code beolow is trying to inject inject a controller but it is failing, and I am confused on how to debug this, any tips on how to solve this would be appreciated
describe('WebApp: AccountController', function() {
beforeEach(function() {
module('webApp');
module('tpls');
return inject(function($injector) {
this.q = $injector.get('$q');
this.userMock = {
id: 1,
email: 'pitogsdfs#gmail.com',
name: 'Adones Pitogo'
};
this.modalMock = {
open: (function(_this) {
return function(tpl, ctrl) {
_this.def = _this.q.defer();
_this.def.resolve(true);
return {
result: _this.def.promise
};
};
})(this)
};
this.modalSpy = spyOn(this.modalMock, 'open').andCallThrough();
this.teamMock = {
id: 1
};
this.repoMock = {
id: 1
};
this.httpBackend = $injector.get('$httpBackend');
this.httpBackend.whenGET('/api/v1/session').respond({
status: 'ok',
user: this.userMock
});
this.httpBackend.whenGET("/api/v1/users/" + this.userMock.id + "/teams").respond({
status: 'ok',
teams: [this.teamMock]
});
this.httpBackend.whenGET("/api/v1/users/" + this.userMock.id + "/repositories/remote").respond({
status: 'ok',
repositories: []
});
this.httpBackend.whenGET("/api/v1/users/" + this.userMock.id + "/repositories/followed").respond({
status: 'ok',
repositories: []
});
this.InvoiceService = $injector.get('Common.InvoiceService');
this.TeamService = $injector.get('Common.TeamService');
this.RepositoryService = $injector.get('Common.RepositoryService');
this.UserService = $injector.get('Common.UserService');
this.rootScope = $injector.get('$rootScope');
this.scope = this.rootScope.$new();
this.$controller = $injector.get('$controller');
this.timeout = $injector.get('$timeout');
this.compile = $injector.get('$compile');
this.rootElement = $injector.get('$rootElement');
this.toasterMock = {
pop: function(type, title, message) {
return true;
}
};
this.modalMock = {
open: (function(_this) {
return function(opts) {
var def;
def = _this.q.defer();
def.resolve(true);
return {
result: def.promise
};
};
})(this)
};
this.modalSpy = spyOn(this.modalMock, 'open').andCallThrough();
this.toasterSpy = spyOn(this.toasterMock, 'pop').andCallThrough();
this.TeamServiceSpy = spyOn(this.TeamService, 'getUserTeams').andCallThrough();
$('body').append('<div id="profile-pic-input"></div>');
this.httpBackend.flush();
this.controller = this.$controller('AccountController', {
'$scope': this.scope,
'$rootScope': this.rootScope,
'Common.RepositoryService': this.RepositoryService,
'Common.UserService': this.UserService,
'Common.InvoiceService': this.InvoiceService,
'toaster': this.toasterMock,
'Common.TeamService': this.TeamService,
'$modal': this.modalMock
});
return this.scope.$digest();
});
});
return it('should have an Account Controller', function() {
expect(this.controller).not.toBe(null);
return expect(this.controller).not.toBe(void 0);
});
});

Related

How do I unit test further .then and .catch branching in an Angular controller?

(function() {
'use strict';
angular
.module('walletInformation')
.controller('WalletInformationController', WalletInformationController);
/* #ngInject */
function WalletInformationController(
$q,
$scope,
config,
logger,
session,
$interpolate,
flowstack,
profileService,
walletInformationFormlyService,
postMsg
) {
// jshint validthis: true
var vm = this;
var app = $scope.app;
var user = session.get('profile').profile || {};
vm.saveWalletInformation = saveWalletInformation;
vm.onClickCancel = onClickCancel;
vm.deleteWallet = deleteWallet;
vm.model = {
walletInformation : {
firstName: user.name.first,
lastName: user.name.last,
emailAddress: user.emailAddress,
phoneNumber: user.mobilePhone.phoneNumber,
keepMeUpdated: user.preferences.receiveEmailNotification
}
};
activate();
////////////////
/**
* #function activate
* #description init function for the controller
* Calls paymentCard to get the
* */
function activate() {
createFormFields();
logger.info('Activated the Wallet Information View.');
}
function createFormFields() {
vm.fields = walletInformationFormlyService.getFormlyFields($scope.app.text);
}
function saveWalletInformation() {
var updatedProfile = createLegacyProfileInformation();
profileService.updateProfileInformation(updatedProfile).then(onSuccess).catch(onError);
function onSuccess(response) {
session.set('profile', {
profile: response.profile
});
if (vm.model.walletInformation.currentPassword && vm.model.walletInformation.newPassword) {
changePasswordRequest();
} else {
flowstack.add('accountManagement');
flowstack.next();
}
}
function onError(error) {
logger.error('Verify save Wallet Information Error: ', error);
}
//changePassword
function changePasswordRequest() {
var updatedPassword = {
data: {
currentPassword: vm.model.walletInformation.currentPassword,
newPassword: vm.model.walletInformation.newPassword
}
};
profileService
.changePassword(updatedPassword)
.then(onChangePasswordSuccess, onChangePasswordError);
function onChangePasswordSuccess(response) {
flowstack.add('accountManagement');
flowstack.next();
logger.info('Change password request: ', response);
}
function onChangePasswordError(response) {
logger.error('Change Password Error: ', response);
}
}
}
function deleteWallet() {
var appText = app.text.walletInformation;
console.log(appText);
flowstack.add('confirmation');
flowstack.next({
data: {
title: appText.deleteWalletConfirmationTitle,
body: appText.deleteWalletConfirmationBody,
cancelButton: appText.deleteWalletConfirmationCancelButton,
confirmButton: appText.deleteWalletConfirmationConfirmButton,
onConfirm: function() {
profileService.deleteWallet().then(deleteProfileSuccess, deleteProfileFailure);
function deleteProfileSuccess(response) {
if (response.profile) {
logger.info('profile is successfully deleted.', response);
postMsg.send('closeSwitch');
}
}
function deleteProfileFailure(error) {
logger.error('something went wrong while deleting profile.', error);
}
},
onCancel: function() {
flowstack.add('walletInformation');
flowstack.next();
}
}
});
}
function createLegacyProfileInformation() {
var updatedProfile = user;
var formlyField = vm.model.walletInformation;
//Update the profile
updatedProfile.name = {
first: formlyField.firstName,
last: formlyField.lastName
};
updatedProfile.mobilePhone.phoneNumber = formlyField.phoneNumber;
updatedProfile.preferences.receiveEmailNotification = formlyField.keepMeUpdated;
return {
data: updatedProfile
};
}
function onClickCancel() {
flowstack.back();
}
}
})();
Coverage is saying that onSuccess of saveWalletInformation and changePasswordRequest isnt't covered but I'm not sure exactly how to test it, the only thing I've tested now is that the saveWalletInformation function is calling the profile service:
describe.only('WalletInformationController ---', function() {
var controller, scope;
var userProfile = {
profile: {
name: {
first: 'someonefirstname',
last: 'someoneslastname'
},
emailAddress: 'someone#something.com',
mobilePhone: {
countryCode: 'US+1',
phoneNumber: '123 212 2342'
},
preferences: {
receiveEmailNotification: true
}
}
};
beforeEach(function() {
bard.appModule('walletInformation');
bard.inject(
'$q',
'$controller',
'$rootScope',
'api',
'flowstack',
'logger',
'session',
'profileService'
);
session.set('profile', userProfile);
});
beforeEach(function() {
sandbox = sinon.sandbox.create();
scope = $rootScope.$new();
scope.app = {
text: {
global: {},
walletInformation: {
deleteWalletConfirmationTitle: 'Confirm Wallet Deletion?'
},
userInformation: {
emailValidation: 'Please enter valid email'
},
signin: {
rememberMeLabel: 'remember me'
}
}
};
controller = $controller('WalletInformationController', {
$scope: scope
});
loggerErrorStub = sandbox.stub(logger, 'error');
sandbox.stub(logger, 'info');
controller = $controller('WalletInformationController', {
$scope: scope
});
});
describe('saveWalletInformation method', function() {
beforeEach(function() {
// apiStub.restore();
sandbox.stub(profileService, 'updateProfileInformation', function() {
return $q.when(userProfile);
});
});
it('should saveWalletInformation successfully', function() {
controller.saveWalletInformation();
expect(profileService.updateProfileInformation).to.have.been.called;
});
it('should log error msg when saveWalletInformation call fails', function() {
profileService.updateProfileInformation.restore();
sandbox.stub(profileService, 'updateProfileInformation', function() {
return $q.reject();
});
controller.saveWalletInformation();
scope.$apply();
expect(loggerErrorStub).to.have.been.calledOnce;
});
it('should call changePasswordRequest when currentPassword and newPassword are set', function() {
sandbox.stub(profileService, 'changePassword', function() {
return $q.when({
success: true,
extensionPoint: null
});
});
sandbox.stub(flowstack, 'add');
sandbox.stub(flowstack, 'next');
controller.saveWalletInformation();
// scope.$apply();
// expect(flowstack.next).to.have.been.calledOnce;
// expect(flowstack.add).to.have.been.calledOnce;
expect(profileService.updateProfileInformation).to.have.been.called;
// expect(profileService.changePassword).to.have.been.called;
});
});
You can let the service call go a step further and instead of verifying that service function was called, as you do here:
expect(profileService.updateProfileInformation).to.have.been.called;
You can instead mock the response from the api call with $httpBackend:
httpBackend.expectGET('your/url/here').respond(200, {response object...});
or
httpBackend.expectGET('your/url/here').respond(500, {error object...});
Then you'll be hitting both the error and success functions when your tests run

Meanstack /Angular.js how to update a seperate model

I'm writing a management system for an ecommerce system. The app needs to create pricing rules on a per product/ per category basis.
SO ..... For a new price rule that has a CategoryID, I want to update all products with that CategoryId. How do I call all the Products from the pricing controller and then update them?
I want this function in the Pricing's controller to update Products with a CategoryId that was set in the form.
$scope.saveRule = function saveRule(row){
var CategoryId = row.CategoryId;
if(row.id =="newRecord"){
var roundup = $('#roundupnewRecord').val();
var percentage = $('#percentagenewRecord').val();
var pricing = new Pricing({
CategoryId: CategoryId,
roundup: roundup,
percentage: percentage
});
pricing.$save(function(response) {
$route.reload();
});
} else {
Pricing.get({
pricingId: row.id
}, function(pricing) {
pricing.roundup = $('#roundup'+row.id).val();
pricing.percentage = $('#percentage'+row.id).val();
pricing.$update(function() {
$route.reload();
});
});
}
}
Thanks in advance for any help.
Pricing Controller. - angular
'use strict';
angular.module('mean.pricing').controller('PricingController', [ '$route', '$http', '$scope', '$routeParams', '$location', 'Global', 'Pricing', function ($route, $http, $scope, $routeParams, $location, Global, Pricing) {
$scope.global = Global;
$scope.create = function() {
var pricing = new Pricing({
CategoryId: this.title,
content: this.content
});
pricing.$save(function(response) {
console.log(response);
$location.path('pricing/' + response.id);
});
this.title = '';
this.content = '';
};
function generateDefaultRule() {
return {
CategoryId: 0,
ProductId: '',
roundup: 2,
percentage: 1,
newRecord: 1,
id: 'newRecord'
}
}
$scope.addRule = function addRule(id) {
$scope.rowCollection.push(generateDefaultRule());
console.log();
};
$scope.saveRule = function saveRule(row){
var CategoryId = row.CategoryId;
if(row.id =="newRecord"){
var roundup = $('#roundupnewRecord').val();
var percentage = $('#percentagenewRecord').val();
var pricing = new Pricing({
CategoryId: CategoryId,
roundup: roundup,
percentage: percentage
});
pricing.$save(function(response) {
$route.reload();
});
} else {
Pricing.get({
pricingId: row.id
}, function(pricing) {
pricing.roundup = $('#roundup'+row.id).val();
pricing.percentage = $('#percentage'+row.id).val();
pricing.$update(function() {
$route.reload();
});
});
}
//Get Products with Relative CategoryId
}
$scope.update = function() {
var pricing = $scope.pricing;
if (!pricing.updated) {
pricing.updated = [];
}
pricing.updated.push(new Date().getTime());
pricing.$update(function() {
$location.path('pricing/' + pricing.id);
});
};
$scope.find = function() {
Pricing.query(function(pricing) {
$scope.pricing = pricing;
});
};
$scope.findOverall = function() {
$http.get('/Pricing/overall').then(function(pricing) {
$scope.overall = pricing;
});
};
$scope.findCategories = function() {
$http.get('/Pricing/categories').then(function(pricing) {
console.log(pricing);
$scope.categories = pricing.data;
});
};
$scope.findProducts = function() {
$http.get('/Pricing/products').then(function(pricing) {
$scope.products = pricing.data;
});
};
$scope.findOne = function() {
Pricing.get({
pricingId: $routeParams.pricingId
}, function(pricing) {
$scope.pricing = pricing;
});
};
$scope.remove = function(pricing) {
if (pricing) {
pricing.$remove();
for (var i in $scope.pricing) {
if ($scope.pricing[i] === pricing) {
$scope.pricing.splice(i, 1);
}
}
}
else {
$scope.pricing.$remove();
$location.path('pricing');
}
};
$scope.removeItem = function removeItem(row) {
Pricing.get({
pricingId: row.id
}, function(pricing) {
pricing.$remove(function() {
var index = $scope.rowCollection.indexOf(row);
if (index !== -1) {
$scope.rowCollection.splice(index, 1);
}
});
});
}
$scope.list = function(){
$('table').on('click', 'a' , function (event) {
var id = $(this).attr('id');
if($(this).hasClass('editButton')){
$('#percentage'+id).css('display','inline-block');
$('#roundup'+id).css('display','inline-block');
$('#percentageSpan'+id).css('display','none');
$('#roundupSpan'+id).css('display','none');
$('.actionButtonsDiv'+id).css('display','none');
$('#saveButtonDiv'+id).css('display','inline');
}
});
$http.get('/pricing').then(function(pricing) {
$scope.rowCollection = pricing.data;
});
$http.get('/category').then(function(categories) {
$scope.categories = categories.data;
});
}
}]);
Products Controller - angular
'use strict';
angular.module('mean.products').controller('ProductsController', ['$http', '$scope', '$routeParams', '$location', 'Global', 'Products', function ($http, $scope, $routeParams, $location, Global, Products) {
$scope.global = Global;
$scope.create = function() {
var product = new Products({
title: this.title,
content: this.content
});
product.$save(function(response) {
$location.path("products/" + response.id);
});
this.title = "";
this.content = "";
};
$scope.remove = function(product) {
if (product) {
product.$remove();
for (var i in $scope.products) {
if ($scope.products[i] === product) {
$scope.products.splice(i, 1);
}
}
}
else {
$scope.product.$remove();
$location.path('products');
}
};
$scope.update = function() {
var product = $scope.product;
if (!product.updated) {
product.updated = [];
}
product.updated.push(new Date().getTime());
product.$update(function() {
$location.path('products/' + product.id);
});
};
$scope.find = function() {
Products.query(function(products) {
// console.log(products);
$scope.products = products;
});
};
$scope.categories = function() {
var selected = {};
$('#multiple').on('click', function(){
$('.product-checkbox').each(function() {
if ($(this).is(":checked")) {
$(this).prop('checked', false);
}else{
$(this).prop('checked', true);
}
});
});
$.each( ['approveButton', 'rejectButton', 'multiButton'], function( index, value ){
$('.'+value).on('click', function(){
$('.product-checkbox').each(function() {
var productId = $(this).attr('id');
if ($(this).is(":checked")) {
if (value === 'rejectButton') {
var categoryId = 199;
}else{
var categoryId = $('#selectProduct'+$(this).attr('id')).val().replace('number:','');
}
Products.get({
productId: productId
}, function(product){
product.CategoryId = categoryId;
product.$update(function(result) {
});
});
}
//Approves checked and rejcts unchecked products
if (value == 'multiButton') {
if (!$(this).is(":checked")) {
Products.get({
productId: productId
}, function(product){
product.CategoryId = 199;
product.$update(function() {
});
});
}
}
});
$location.path('products/categories');
});
});
$http.get('/products/categories').then(function(products) {
$scope.products = products.data;
});
$http.get('/category').then(function(categories) {
$scope.categories = categories.data;
});
$http.get('/productCategoryMatchs').then(function(productCategoryMatchs) {
var pCMResponse = productCategoryMatchs.data;
var pcmArray = {};
for(var index in pCMResponse){
pcmArray[pCMResponse[index].ProductId] = pCMResponse[index].CategoryId;
}
$scope.pCMs = pcmArray;
});
};
$scope.findOne = function() {
Products.get({
productId: $routeParams.productId
}, function(product) {
$scope.product = product;
});
};
}]);
Products Controller -node
'use strict';
/**
* Module dependencies.
*/
var StandardError = require('standard-error');
var db = require('../../config/sequelize');
/**
* Find product by id
* Note: This is called every time that the parameter :productId is used in a URL.
* Its purpose is to preload the product on the req object then call the next function.
*/
exports.product = function(req, res, next, id) {
console.log('id => ' + id);
db.Product.find({ where: {id: id}}).then(function(product){
if(!product) {
return next(new Error('Failed to load product ' + id));
} else {
req.product = product;
return next();
}
}).catch(function(err){
return next(err);
});
};
/**
* Create a product
*/
exports.create = function(req, res) {
// augment the product by adding the UserId
req.body.UserId = req.user.id;
// save and return and instance of product on the res object.
db.Product.create(req.body).then(function(product){
if(!product){
return res.send('users/signup', {errors: new StandardError('Product could not be created')});
} else {
return res.jsonp(product);
}
}).catch(function(err){
return res.send('users/signup', {
errors: err,
status: 500
});
});
};
/**
* Update a product
*/
exports.update = function(req, res) {
// create a new variable to hold the product that was placed on the req object.
var product = req.product;
product.updateAttributes({
price: req.body.price,
CategoryId: req.body.CategoryId
}).then(function(a){
return res.jsonp(a);
}).catch(function(err){
return res.render('error', {
error: err,
status: 500
});
});
};
/**
* Delete an product
*/
exports.destroy = function(req, res) {
// create a new variable to hold the product that was placed on the req object.
var product = req.product;
product.destroy().then(function(){
return res.jsonp(product);
}).catch(function(err){
return res.render('error', {
error: err,
status: 500
});
});
};
/**
* Show an product
*/
exports.show = function(req, res) {
// Sending down the product that was just preloaded by the products.product function
// and saves product on the req object.
return res.jsonp(req.product);
};
/**
* List of Products
*/
exports.all = function(req, res) {
db.Product.findAll({}).then(function(products){
return res.jsonp(products);
}).catch(function(err){
return res.render('error', {
error: err,
status: 500
});
});
};
/**
* List of Products
*/
exports.list = function(req, res) {
db.Product.findAll({
limit : 20
}).then(function(products){
return res.jsonp(products);
}).catch(function(err){
return res.render('500', {
error: err,
status: 500
});
});
};
/**
* List of Products and there categories
*/
exports.categories = function(req, res) {
db.Product.findAll({
attributes : [
'name',
'id',
// 'ProductCategoryMatch.count'
],
where: {
CategoryId : null
},
// include : [
// { model: db.ProductCategoryMatch }
// ],
// order : [
// ]
limit: 20
}).then(function(products){
return res.jsonp(products);
}).catch(function(err){
return res.render(500, {
error: err,
status: 500
});
});
};
/**
* Article authorizations routing middleware
*/
exports.hasAuthorization = function(req, res, next) {
// if (req.product.User.id !== req.user.id) {
// return res.send(401, 'User is not authorized');
// }
next();
};

Cordova/Ionic httpd server plugin - url not visible

i have a problem with Angular controller in my Ionic/Cordova project.
Can someone explain me why url which i get in line 25: $scope.serverURL=url;
isn't visible in line 63 alert($scope.serverURL); (it return null)?
Here is my controller:
var app = angular.module('iremotee');
app.controller('StreamingController', function(ConnectSdkService, $scope, $rootScope, $state, Camera) {
var options = {
quality: 100,
destinationType: 0,
sourceType: 0,
mediaType: 2
};
$scope.currentFile = null;
$scope.httpd = null;
$scope.serverURL = null;
alert($scope.serverURL + "!!!");
$scope.createHttpd = function() {
$scope.httpd = (cordova && cordova.plugins && cordova.plugins.CorHttpd) ? cordova.plugins.CorHttpd : null;
};
$scope.startMediaServer = function() {
if ($scope.httpd) {
// before start, check whether its up or not
$scope.httpd.getURL(function(url) {
if (url.length > 0) {
$scope.serverURL = url;
alert($scope.serverURL);
} else {
$scope.httpd.startServer({
'www_root': '/',
'port': 8080,
'localhost_only': false
}, function(url) {
$scope.serverURL = url;
alert($scope.serverURL);
}, function(error) {});
}
});
} else {}
};
$scope.stopServer = function() {
if ($scope.httpd) {
$scope.httpd.stopServer(function() {}, function(error) {});
}
};
$scope.getMedia = function() {
$state.go('mainmenu');
};
ionic.Platform.ready(function() {
$scope.createHttpd();
$scope.startMediaServer();
});
$scope.getFile = function() {
alert($scope.serverURL);
Camera.getFromMemory(options).then(function(URI) {
if (URI.indexOf("file://") == -1) {
URI = "file://" + URI;
}
window.resolveLocalFileSystemURL(URI, function(fileEntry) {
var URI = fileEntry.toURL();
var str = URI;
str = str.replace("file:///storage/emulated/0/", "/sdcard/");
str = str.replace("file:///storage/emulated/0/", "/sdcard1/");
str = str.replace("file:///storage", "");
Camera.currentURI = str;
alert(Camera.currentURI);
$scope.currentFile = Camera.currentURI;
}); //resolveLocalFileSystemURL-END
}, function(err) {
alert(err);
}); //getFromMemory-END
}; //getFile-END
$scope.$on('$destroy', function() {
$scope.stopServer();
});
});

AngularJS Error: d[h].apply is not a function

When I navagate away from a page in my angular site the error console fills up (occurs 108 times) with the error:
Error: d[h].apply is not a function
jf/this.$get</n.prototype.$broadcast#http://localhost:9885/Scripts/angular.min.js:137:355
jf/this.$get</n.prototype.$destroy#http://localhost:9885/Scripts/angular.min.js:133:254
ye</<.link/<#http://localhost:9885/Scripts/angular.min.js:252:477
jf/this.$get</n.prototype.$digest#http://localhost:9885/Scripts/angular.min.js:132:257
jf/this.$get</n.prototype.$apply#http://localhost:9885/Scripts/angular.min.js:135:267
Kc[c]</<.compile/</<#http://localhost:9885/Scripts/angular.min.js:252:124
n.event.dispatch#http://localhost:9885/Scripts/jquery-bundle.js:3:6414
n.event.add/r.handle#http://localhost:9885/Scripts/jquery-bundle.js:3:3224
It only occurs on this one page but I have no $watches or $broadcast events on it. Could someone help me by suggesting where I should look to find the trigger for this error?
I appreciate not having the code makes this difficult but I am keen to have some suggestions on what things cause errors like this and/or the best way to debug it.
UPDATE
app.controller('ticketController', ['$scope', '$state', 'Page', 'globals', 'localStorageService', 'Ticket', 'User', 'ticketData', 'ELearning', 'dialogs', 'Notification', 'Payment','Note', 'DTOptionsBuilder', 'DTColumnDefBuilder', 'History', 'Correspondance',function ($scope, $state, Page, globals, localStorageService, Ticket, User, ticketData, ELearning, dialogs, Notification, Payment,Note, DTOptionsBuilder, DTColumnDefBuilder, History, Correspondance) {
if (globals.debug) { console.log('Ticket controller loaded'); }
$scope.globals = globals;
Page.setTitle(ticketData.forename + ' ' + ticketData.surname);
$scope.authData = localStorageService.get('authorizationData');
$scope.ticket = ticketData;
$scope.user = User.admindata({ id: ticketData.ticketGUID });
$scope.person = {};
$scope.reOpenTicket = {
isOpen: false,
previousChanges: [],
newCriticalDate: moment(new Date($scope.ticket.criticalDate)).add(1, 'M').format('DD MMM YYYY'),
minCriticalDate: moment(new Date($scope.ticket.criticalDate)).add(-1, 'd').format('DD MMM YYYY'),
maxCriticalDate: moment(new Date($scope.ticket.criticalDate)).add(1, 'M').add(1, 'd').format('DD MMM YYYY'),
minErrorDate: moment(new Date($scope.ticket.criticalDate)).format('DD MMM YYYY'),
maxErrorDate: moment(new Date($scope.ticket.criticalDate)).add(1, 'M').format('DD MMM YYYY'),
reason: '',
form: {},
saving: false,
saveError: ''
};
$scope.notes = {
data: [],
newNote: '',
loading: false,
loadError: ''
};
$scope.payments = {
data: [],
loading: true,
dtOptions: {},
dtColumnDefs: {},
ticketGUID: ''
};
$scope.learning = {
data: [],
loading: true,
ticketGUID: '',
dtOptions: {},
dtColumnDefs: {}
};
$scope.history = {
data: [],
loading: true,
loadError: ''
};
$scope.letters = {
data: [],
loading: true,
laddaResendLetter: false,
laddaCancelLetter: false
};
$scope.dob = {
minDate: moment(new Date()).add(-90, 'y').format(),
maxDate: moment(new Date()).add(-10, 'y').format()
};
$scope.titles = ['Mr', 'Miss', 'Mrs', 'Ms', 'Dr', 'Rev'];
$scope.savePersonTab = function (validity) {
if (validity) {
$scope.ticket.dateOfBirth = $scope.dob.chosenDate;
Ticket.personTabSave({ 'id': $scope.ticket.ticketGUID }, $scope.ticket, function (success) {
Notification.success('Record updated successfully');
Ticket.getAdmin({ id: success.ticketGUID });
$scope.person.form.$setPristine();
$scope.getHistory();
}, function (error) {
});
} else {
console.log('skip Save');
}
};
//#region Tickets
$scope.reopenTicket = function () {
$scope.reOpenTicket.isOpen = true;
$scope.reOpenTicket.previousChanges = Ticket.getCriticalDateChanges({ id: $scope.ticket.ticketGUID });
// Reset
$scope.reOpenTicket.saveError = '';
$scope.reOpenTicket.reason = '';
};
$scope.saveReopen = function (validity) {
if (validity) {
$scope.reOpenTicket.saving = true;
var data = {
ChangeTo: $scope.reOpenTicket.newCriticalDate,
ChangeReason: $scope.reOpenTicket.reason
};
Ticket.reOpenTicket({ id: $scope.ticket.ticketGUID }, data, function (response) {
$scope.reOpenTicket.saving = false;
if (response.isSuccessful) {
$scope.getNotes();
$scope.getHistory();
$scope.ticket = Ticket.getAdmin({ id: $scope.ticket.ticketGUID });
$scope.reOpenTicket.isOpen = false;
} else {
$scope.reOpenTicket.saveError = response.errorMessage;
}
});
}
};
$scope.closeNewCriticalDate = function () {
$scope.reOpenTicket.isOpen = false;
};
$scope.confirmTCs = function () {
var opts = {
'keyboard': true,
'size': 'lg' //small or large modal size
};
// Checks
if ($scope.person.form.$dirty) {
dialogs.notify('Cannot Confirm!', 'Unsaved changes to personal details detected.', opts);
return;
}
// email address is complete
if (!$scope.ticket.eMailAddress) {
dialogs.notify('Cannot confirm!', 'An Email address must be entered and saved before confirming Terms and Conditions.', opts);
return;
} else {
if ($scope.ticket.status != 'AwaitingPayment' && $scope.ticket.status != 'Referred') {
dialogs.notify('Cannot confirm!', 'Ticket status must be Awaiting Payment or Referred before confirming Terms and Conditions. The current ticket status is ' + $scope.ticket.status, opts);
return;
}
}
var dlg = dialogs.confirm('Confirm terms and conditions', 'Please confirm that this delegate has read and agreed to the Terms and Conditions and also the details and offence relate to them.', opts);
dlg.result.then(function (btn) {
Ticket.confirmation({ 'id': $scope.ticket.ticketGUID }, $scope.ticket, function (success) {
Notification.success('Record updated successfully');
$scope.ticket = success;
$scope.getHistory();
}, function (error) {
});
});
};
$scope.lockTicket = function () {
Ticket.lock({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been locked');
}, function (error) {
console.log(error);
});
};
$scope.unlockTicket = function () {
Ticket.unlock({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been unlocked');
}, function (error) {
console.log(error);
});
};
$scope.cancelTicket = function () {
Ticket.cancelTicket({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been cancelled');
}, function (error) {
console.log(error);
});
};
$scope.restoreTicket = function () {
Ticket.restoreTicket({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been restored');
}, function (error) {
console.log(error);
});
};
//#endregion
//#region Payments
$scope.markAsPaid = function () {
var opts = {
'keyboard': true,
'size': 'lg' //small or large modal size
};
var dlg = dialogs.confirm('Mark as paid', 'Please confirm that you would like to manually mark this delegate as having paid.', opts);
dlg.result.then(function (btn) {
Payment.markAsPaid({ 'id': $scope.ticket.ticketGUID }, $scope.ticket, function (success) {
Notification.success('Record updated successfully');
$scope.ticket = Ticket.getAdmin({ id: success.ticketGUID });
}, function (error) {
console.info(error);
});
});
};
$scope.payments.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withDOM('tr');
$scope.payments.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(0),
DTColumnDefBuilder.newColumnDef(1).withOption('width', '180'),
DTColumnDefBuilder.newColumnDef(2),
DTColumnDefBuilder.newColumnDef(3),
DTColumnDefBuilder.newColumnDef(4)
];
$scope.getPaymentData = function () {
$scope.payments.loading = true;
Payment.query({ id: $scope.ticket.ticketGUID }, function (result) {
$scope.payments.loading = false;
$scope.payments.data = result;
});
};
//#endregion
//#region Notes
$scope.addNote = function () {
Note.add({ id: $scope.ticket.ticketGUID }, '"' + $scope.notes.newNote + '"', function (successResponse) {
$scope.notes.data.push(successResponse);
$scope.notes.newNote = '';
Notification.success('Note added');
}, function (err) {
console.log(err);
});
};
$scope.getNotes = function () {
$scope.notes.loading = true;
$scope.notes.data = Note.query({ id: $scope.ticket.ticketGUID }, function (successResponse) {
$scope.notes.loading = false;
$scope.notes.loadError = '';
}, function (error) {
$scope.notes.loading = false;
$scope.notes.loadError = error.data;
});
};
//#endregion
//#region ELearning
$scope.learning.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withDOM('tr');
$scope.learning.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(0),
DTColumnDefBuilder.newColumnDef(1),
DTColumnDefBuilder.newColumnDef(2),
DTColumnDefBuilder.newColumnDef(3).notSortable()
];
$scope.getLearningData = function () {
$scope.learning.loading = true;
ELearning.query({ id: $scope.ticket.ticketGUID }, function (result) {
$scope.learning.loading = false;
$scope.learning.data = result;
});
};
$scope.markAsCompleted = function () {
ELearning.MarkAsCompleted({ id: $scope.ticket.ticketGUID }, function (successResponse) {
$scope.ticket = successResponse;
$scope.getHistory();
$scope.getLearningData();
Notification.success('Ticket has been marked as completed');
});
};
$scope.getLearningHistory = function (learningData) {
var dlg = dialogs.create('app/elearning/ResultDialog.html', 'learningDialogController', { data: learningData.onlineLearningResultId }, 'lg');
};
//#endregion
//#region History
$scope.getHistory = function () {
$scope.history.loading = true;
History.query({ id: $scope.ticket.ticketGUID }, function (successResponse) {
$scope.history.data = successResponse;
$scope.history.loading = false;
$scope.history.loadError = '';
}, function (error) {
$scope.history.loading = false;
$scope.history.loadError = error.data;
});
};
$scope.animateElementIn = function ($el) {
$el.removeClass('hidden');
$el.addClass('bounce-in');
};
// optional: not mandatory (uses angular-scroll-animate)
$scope.animateElementOut = function ($el) {
$el.addClass('hidden');
$el.removeClass('bounce-in');
};
//#endregion
//#region Correspondance
$scope.getCorrespondanceData = function () {
$scope.letters.loading = true;
Correspondance.query({ id: $scope.ticket.ticketGUID }, function (result) {
$scope.letters.loading = false;
$scope.letters.data = result;
});
};
$scope.resendLetter = function (letter) {
$scope.letters.laddaResendLetter = true;
Correspondance.resend({ id: letter.correspondanceID }, function (result) {
Notification.success('New ' + result.correspondanceType.toLowerCase() + ' ' + result.deliveryMethod.toLowerCase() + ' has been requested');
$scope.getCorrespondanceData();
$scope.letters.laddaResendLetter = false;
}, function (error) {
$scope.letters.laddaResendLetter = false;
});
};
$scope.cancelLetter = function (letter) {
$scope.letters.laddaCancelLetter = true;
Correspondance.cancelLetterRequest({ id: letter.correspondanceID }, function (result) {
Notification.success(result.correspondanceType.toLowerCase() + ' ' + result.deliveryMethod.toLowerCase() + ' has been cancelled');
$scope.getCorrespondanceData();
$scope.letters.laddaCancelLetter = false;
}, function (error) {
$scope.letters.laddaCancelLetter = false;
});
};
//#endregion
$scope.getPaymentData();
$scope.getNotes();
$scope.getLearningData();
$scope.getHistory();
$scope.getCorrespondanceData();}]);
Found the problem to be a third party module (angular-timeline) for animating the history

Jasmine spyon method returning undefined

I am getting an undefined error on my SpyOn method
This was what I had come up with
'use strict';
describe('WebApp: AccountController', function() {
return beforeEach(function() {
module('webApp');
module('tpls');
return inject(function($injector) {
this.q = $injector.get('$q');
this.userMock = {
id: 1,
email: 'pidsafs#gmail.com',
name: 'Adones Pitogo'
};
this.modalMock = {
open: (function(_this) {
return function(tpl, ctrl) {
_this.def = _this.q.defer();
_this.def.resolve(true);
return {
result: _this.def.promise
};
};
})(this)
};
this.teamMock = {
id: 1
};
this.repoMock = {
id: 1
};
this.httpBackend = $injector.get('$httpBackend');
this.httpBackend.whenGET('/api/v1/session').respond({
status: 'ok',
user: this.userMock
});
this.httpBackend.whenGET("/api/v1/users/" + this.userMock.id + "/teams").respond({
status: 'ok',
teams: [this.teamMock]
});
this.httpBackend.whenGET("/api/v1/users/" + this.userMock.id + "/repositories/remote").respond({
status: 'ok',
repositories: []
});
this.httpBackend.whenGET("/api/v1/users/" + this.userMock.id + "/repositories/followed").respond({
status: 'ok',
repositories: []
});
this.InvoiceService = $injector.get('Common.InvoiceService');
this.TeamService = $injector.get('Common.TeamService');
this.RepositoryService = $injector.get('Common.RepositoryService');
this.UserService = $injector.get('Common.UserService');
this.rootScope = $injector.get('$rootScope');
this.scope = this.rootScope.$new();
this.scope.user = this.userMock;
this.$controller = $injector.get('$controller');
this.timeout = $injector.get('$timeout');
this.compile = $injector.get('$compile');
this.rootElement = $injector.get('$rootElement');
this.toasterMock = {
pop: function(type, title, message) {
return true;
}
};
this.modalSpy = spyOn(this.modalMock, 'open').andCallThrough();
this.httpBackend.flush();
$('body').append('<div id="profile-pic-input"></div>');
this.openFileWindow = function() {
return this.timeout(function() {
return $('#profile-pic-input').trigger('click');
});
};
this.controller = this.$controller('AccountController', {
'$scope': this.scope,
'$rootScope': this.rootScope,
'Common.RepositoryService': this.RepositoryService,
'Common.UserService': this.UserService,
'Common.InvoiceService': this.InvoiceService,
'toaster': this.toasterMock,
'openFileWindow': this.openFileWindow,
'Common.TeamService': this.TeamService
});
return this.scope.$digest();
});
});
});
I always get this error
TypeError: 'undefined' is not a function (evaluating 'spyOn(this.modalMock, 'open').andCallThrough()')
It happens if I spy on all the other services as well
I saw this issue when using Jasmine version 2.x. The problem for me was that I was calling andCallThrough() which is the Jasmine 1.x syntax. The 2.x syntax is and.callThrough().

Resources