javascript - How to avoid $digest already in progress during testing -


i'm banging head around testing service uses google maps geoencoding service. thought going easy since it's straightforward code. seems it's not.

here service:

(function () {     'use strict';      var googlegeocodingservice = function ($q, googleapiloaderservice, $rootscope) {          var geocoder,             mapsreadypromise;          mapsreadypromise = googleapiloaderservice.load('maps', '3', {other_params: 'sensor=false'}).then(function() {             geocoder = new google.maps.geocoder();         });          var getlatlng = function (searchkeyword) {             var deferred = $q.defer();              mapsreadypromise.then(function () {                 geocoder.geocode({'address': searchkeyword}, function (results, status) {                     $rootscope.$apply(function () {                         if (status === google.maps.geocoderstatus.ok) {                             deferred.resolve(results);                         } else {                             deferred.reject(status);                         }                     });                 });             });              return deferred.promise;         };          return {             getlatlng: getlatlng         };      };      app.factory('googlegeocodingservice', ['$q', 'googleapiloaderservice', '$rootscope', googlegeocodingservice]); }()); 

in order not use real google.maps i'm mocking both googleapiloaderservice , google.maps.

however, when try test it, $digest in progress. i've tried safeapply won't work.

it('should call geocoder.geocode retrieve results', function () {     googlegeocoding.getlatlng('canada');     $rootscope.$apply();     expect(geocodermock.prototype.geocode).tohavebeencalledwith({ address : 'canada'}); }); 

this full spec:

(function () {     "use strict";     var geocodingok, geocodingerror, geocodermock, googleapiloadermock, $rootscope, $q, $timeout, googlegeocoding;      describe('google geocoding service', function () {          beforeeach(angular.mock.module('app', function($provide){             googleapiloadermock = jasmine.createspyobj('googleapiloaderservice',['load']);             $provide.value('googleapiloaderservice',googleapiloadermock);         }));          beforeeach(inject(function (_$q_,_$rootscope_) {             $q = _$q_;             $rootscope = _$rootscope_;              googleapiloadermock.load.andcallfake(function () {                 var deferred = $q.defer();                 deferred.resolve('library loaded');                              return deferred.promise;             });         }));          beforeeach(inject(function (googlegeocodingservice) {             googlegeocoding = googlegeocodingservice;              window.google = jasmine.createspy('google');             window.google.maps = jasmine.createspy('maps');             window.google.maps.geocoderstatus = jasmine.createspy('geocoderstatus');             window.google.maps.geocoderstatus.ok = 'ok';              geocodingok = function (params, callback) {                 callback({data: 'fake'}, 'ok');             };              geocodingerror = function (params, callback) {                 callback({data: 'fake'}, 'error');             };              geocodermock = window.google.maps.geocoder = jasmine.createspy('geocoder');             geocodermock.prototype.geocode = jasmine.createspy('geocode').andcallfake(geocodingok);         }));          it('should expose functions', function(){             expect(typeof googlegeocoding.getlatlng).tobe('function');         });         describe('getlatlng function', function () {             it('shouldn\'t call if promise hasn\'t been resolved', function () {                 googlegeocoding.getlatlng('canada');                 expect(geocodermock.prototype.geocode).not.tohavebeencalled();             });             it('should return promise', function () {                 var promise = googlegeocoding.getlatlng('canada');                 expect(typeof promise.then).tobe('function');             });             it('should call geocoder.geocode retrieve results', function () {                 googlegeocoding.getlatlng('canada');                 $rootscope.$apply();                 expect(geocodermock.prototype.geocode).tohavebeencalledwith({ address : 'canada'});             });             it('should resolve promise when receiving data', function () {                 var okmock = jasmine.createspy();                 googlegeocoding.getlatlng('canada').then(okmock);                 $rootscope.$apply();                 expect(okmock).tohavebeencalledwith({ address : 'canada'});             });         });     }); }()); 

faq:

  • have tried $$phase checking?

yes. doesn't work. somehow phase null @ point. fear calling $apply i'm unleashing 2 of them how, causing issue.

  • can provide plunker this?

yes of course! link plunker

the problem simple. $apply inside mapsreadypromise not needed when $apply on test, gets crazy. removing $apply resolved $digest problem, needed fix couple of issues , ready :)

http://plnkr.co/edit/wrdjnqak9rz7vg3dli6k?p=preview


Comments

Popular posts from this blog

c# - How to get the current UAC mode -

postgresql - Lazarus + Postgres: incomplete startup packet -

javascript - Ajax jqXHR.status==0 fix error -