javascript - Cannot get Karma/Jasmine to work with my angular controller -
ok. have spent several hours trying in vain karma work angular controller. whatever do, following error. seems if remove expectget() calls, still error; call $http.flush();
typeerror: cannot set property 'totalbeforediscounts' of undefined the code controller follows:
var quotepadcontrollers = angular.module('quotepadcontrollers', []); quotepadcontrollers.controller('quotescontroller', ['$scope', '$http', '$q', function($scope, $http, $q){ var blankaddon; // setup initial state , default values var ajaxgetaddons = $http.get('/?ajax=dbase&where=aons'), ajaxgetframes = $http.get('/?ajax=dbase&where=fcats'); $q.all([ajaxgetaddons, ajaxgetframes]).then(function(results){ $scope.addons = results[0].data; $scope.frames = results[1].data; $scope.pairs = [ { "frames" : angular.copy($scope.frames), "addons" : angular.copy($scope.addons), } ]; }); // function 'add pair' button $scope.addpair = function() { $scope.pairs.push({ "frames" : angular.copy($scope.frames), "addons" : angular.copy($scope.addons) }); }; // function 'remove pair' button $scope.removepair = function() { if ( $scope.pairs.length > 1 ) { $scope.pairs.pop(); } }; // continually update subtotal , total $scope.$watch('pairs', function(pairs) { var totalbeforediscounts = 0; angular.foreach(pairs, function(pair) { var subtotal = 0; angular.foreach(pair.addons, function(addon) { subtotal += addon.added ? addon.price : 0; }); subtotal += pair.currentframe !== undefined ? pair.currentframe.price : 0; pair.subtotal = subtotal; totalbeforediscounts += subtotal; }); pairs.totalbeforediscounts = totalbeforediscounts; }, true); }]); and test code:
describe('quotescontroller', function() { beforeeach(module('quotepadapp')); var ctrl, $scope, $http, framecatshandler, addonshandler, createcontroller; // setup tests beforeeach(inject(function($controller, $rootscope, $httpbackend, _$q_) { $scope = $rootscope.$new(); $http = $httpbackend; framecatsresponse = [{"id":145,"price":25,"brand":"mybrand"}, {"id":147,"price":45,"brand":"mybrand"}, {"id":148,"price":69,"brand":"mybrand"}]; addonshandler = [{"id":1,"name":"addon1","price":30,"includein241":0,"description":null}, {"id":2,"name":"addon2","price":60,"includein241":0,"description":null}]; framecatshandler = $http.when('get', '/?ajax=dbase&where=fcats').respond(framecatsresponse); addonshandler = $http.when('get', '/?ajax=dbase&where=aons').respond(addonshandler); createcontroller = function() { return $controller('quotescontroller', {'$scope' : $scope }); }; })); it('should request frame cats , addons database', function() { $http.expectget('/?ajax=dbase&where=aons'); $http.expectget('/?ajax=dbase&where=fcats'); createcontroller(); $http.flush(); }); });
this because have following watch statement in controller trying set totalbeforediscounts property on $scope.pairs.
$scope.$watch('pairs', function(pairs) { // ... pairs.totalbeforediscounts = totalbeforediscounts; }, true); in tests, when create controller , call $http.flush(), that's triggering $digest cycle. kicks off watchers.
createcontroller(); $http.flush(); the watch handler above execute , since executes before $scope.pairs has value, pairs argument passed watch handler undefined, resulting in error.
as per documentation:
after watcher registered scope, listener fn called asynchronously (via $evalasync) initialize watcher. in rare cases, undesirable because listener called when result of watchexpression didn't change. detect scenario within listener fn, can compare newval , oldval. if these 2 values identical (===) listener called due initialization. https://docs.angularjs.org/api/ng/type/$rootscope.scope#$watch
also, in rest of code have $scope.pairs array, in watch trying set property totalbeforediscounts on it. doesn't right.
Comments
Post a Comment