franDayz
franDayz

Reputation: 943

Ionic Jasmin test: $scope.$digest() not resolving promise

I have the following service which I keep simple for now for the sake of the problem:

angular.module('handheld')
.factory('database', ['$ionicPlatform', '$cordovaSQLite', 
    function ($ionicPlatform, $cordovaSQLite) {

    return {
        insert: function(table, attributes) {
            return $cordovaSQLite.execute({}, 'query', []);
        }   
    };

}]);

The test below mocks $cordovaSQLite.execute to return a promise:

describe('database', function() {

  var database, $scope;

  beforeEach(function() {
    module('handheld');

    module(function($provide, $urlRouterProvider) {
      $provide.value('$ionicTemplateCache', function(){});
      $urlRouterProvider.deferIntercept();  

      $provide.service('$cordovaSQLite', function($q) {
        this.execute = jasmine.createSpy('execute').and.callFake(function(db, query, values) {
          return $q.when(true);
        });
      });
    });
  });

  beforeEach(inject(function($injector) {
    database = $injector.get('database');
    $scope = $injector.get('$rootScope').$new();
  }));

  describe("when inserting", function() { 
    var result;

    beforeEach(function(done) {
      database.insert('table', {}).then(
        function(success){
          result = success;
          done();
        },
        function(err){
          result = err;
          done();
        }
      );
    });

    it("should be successful", function() { 
      $scope.$digest();
      expect(result).toEqual(true);
    });
  });
});

I've followed this link (point Mocking Methods Returning Promises)

And also this other link (point Disable $ionicTemplateCache)

But still get the error Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. (Please note that I'm calling $scope.$digest(); already)

I'd like to mention that the mocking is working correctly as I'm able to place a breakpoint at return $q.when(true); and trace from there, so the service is invoking the mock version.

I've tried to search on this site and the rest of the internet, but couldn't find any satisfactory solution as it seems to me I'm doing what everybody does.

Any help would be much appreciated.

Upvotes: 0

Views: 87

Answers (1)

franDayz
franDayz

Reputation: 943

I finally found what's wrong. With Angular we don't need to use the nested beforeEach with the done() callback since $scope.$digest blocks and resolves promises so we can place the assertions right after.

See link

Here is how the nested describe block should be:

describe("when inserting", function() { 

    it("should be successful", function() {
      var result;

      database.insert('table', {}).then(
        function(success){
          result = success;
        },
        function(err){
          result = err;
        }
      );

      $scope.$digest();
      expect(result).toEqual(true);
    });
});

Upvotes: 0

Related Questions