I\'m trying to unit test an AngularJS service that wraps the Facebook
JavaScript SDK FB
object; however, the test isn\'t working,
and I have
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:
FB.getLoginStatus()
doesn't invoke its callback immediately so any then()
calls run first; orSo, 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.