AngularJS Promise Callback Not Trigged in JasmineJS Test

TL;DR

Call $rootScope.$digest() from your test code and it’ll pass:

it('should return false if user is not logged into Facebook', function () {
  ...

  var userLoggedIn;

  inject(function (Facebook, $rootScope) {
    Facebook.getUserLoginStatus($rootScope).then(function (data) {
      console.log("Found data!");
      userLoggedIn = data;
    });

    $rootScope.$digest(); // <-- This will resolve the promise created above
    expect(userLoggedIn).toEqual(false);
  });
});

Plunker here.

Note: I removed run() and wait() calls because they’re not needed here (no actual async calls being performed).

Long explanation

Here’s what’s happening: When you call getUserLoginStatus(), it internally runs FB.getLoginStatus() which in turn executes its callback immediately, as it should, since you’ve mocked it to do precisely that. But your $scope.$apply() call is within that callback, so it gets executed before the .then() statement in the test. And since then() creates a new promise, a new digest is required for that promise to get resolved.

I believe this problem doesn’t happen in the browser because of one out of two reasons:

  1. FB.getLoginStatus() doesn’t invoke its callback immediately so any then() calls run first; or
  2. Something else in the application triggers a new digest cycle.

So, to wrap it up, if you create a promise within a test, explicitly or not, you’ll have to trigger a digest cycle at some point in order for that promise to get resolved.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)