Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 45 additions & 34 deletions lib/angular-facebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
// Declare module flags value
value('flags', flags).

/**
* Facebook provider
*/
/**
* Facebook provider
*/
provider('Facebook', [
function() {

Expand Down Expand Up @@ -253,7 +253,8 @@
'$rootScope',
'$timeout',
'$window',
function($q, $rootScope, $timeout, $window) {
'$log',
function($q, $rootScope, $timeout, $window,$log) {
/**
* This is the NgFacebook class to be retrieved on Facebook Service request.
*/
Expand Down Expand Up @@ -300,20 +301,20 @@
if (angular.isFunction(userFn)) {
userFn(response);
}
});
});
}
});
}

// review(mrzmyr): generalize behaviour of isReady check
if (this.isReady()) {
$window.FB.login.apply($window.FB, args);
} else {
$timeout(function() {
d.reject("Facebook.login() called before Facebook SDK has loaded.");
});
}
// review(mrzmyr): generalize behaviour of isReady check
if (this.isReady()) {
$window.FB.login.apply($window.FB, args);
} else {
$timeout(function() {
d.reject("Facebook.login() called before Facebook SDK has loaded.");
});
}

return d.promise;
return d.promise;
};

/**
Expand All @@ -328,9 +329,9 @@
NgFacebook.prototype[name] = function() {

var d = $q.defer(),
args = Array.prototype.slice.call(arguments), // Converts arguments passed into an array
userFn,
userFnIndex;
args = Array.prototype.slice.call(arguments), // Converts arguments passed into an array
userFn,
userFnIndex;

// Get user function and it's index in the arguments array,
// to replace it with custom function, allowing the usage of promises
Expand Down Expand Up @@ -363,6 +364,7 @@
$timeout(function() {
// Call when loadDeferred be resolved, meaning Service is ready to be used.
loadDeferred.promise.then(function() {
$log.info('Load deferred resolved');
$window.FB[name].apply(FB, args);
});
});
Expand All @@ -381,6 +383,7 @@
$timeout(function() {
// Call when loadDeferred be resolved, meaning Service is ready to be used
loadDeferred.promise.then(function() {
$log.info('Load deferred resolved');
$window.FB.XFBML.parse();
d.resolve();
});
Expand All @@ -396,15 +399,15 @@

angular.forEach([
'subscribe',
'unsubscribe',
'unsubscribe'
], function(name) {

NgFacebook.prototype[name] = function() {

var d = $q.defer(),
args = Array.prototype.slice.call(arguments), // Get arguments passed into an array
userFn,
userFnIndex;
args = Array.prototype.slice.call(arguments), // Get arguments passed into an array
userFn,
userFnIndex;

// Get user function and it's index in the arguments array,
// to replace it with custom function, allowing the usage of promises
Expand Down Expand Up @@ -438,6 +441,7 @@
$timeout(function() {
// Call when loadDeferred be resolved, meaning Service is ready to be used
loadDeferred.promise.then(function() {
$log.info('Load deferred resolved');
$window.FB.Event[name].apply(FB, args);
});
});
Expand All @@ -453,17 +457,20 @@
}
]).

/**
* Module initialization
*/
/**
* Module initialization
*/
run([
'$rootScope',
'$q',
'$window',
'$timeout',
function($rootScope, $q, $window, $timeout) {
'$document',
'$log',
function($rootScope, $q, $window, $timeout,$document,$log) {
// Define global loadDeffered to notify when Service callbacks are safe to use
loadDeferred = $q.defer();
var facebookDivLoad = $q.defer();

var loadSDK = settings.loadSDK;
delete(settings['loadSDK']); // Remove loadSDK from settings since this isn't part from Facebook API.
Expand All @@ -473,7 +480,7 @@
*/
$window.fbAsyncInit = function() {
// Initialize our Facebook app
$timeout(function() {
return facebookDivLoad.promise.then(function() {
if (!settings.appId) {
throw 'Missing appId setting.';
}
Expand Down Expand Up @@ -515,23 +522,27 @@
/**
* Inject Facebook root element in DOM
*/
(function addFBRoot() {

$document.ready(function(){
var fbroot = document.getElementById('fb-root');

if (!fbroot) {
$log.info('fb-root div not found, creating');
fbroot = document.createElement('div');
fbroot.id = 'fb-root';
document.body.insertBefore(fbroot, document.body.childNodes[0]);
} else {
$log.info('fb-root found');
}

facebookDivLoad.resolve(fbroot);
return fbroot;
})();
});

/**
* SDK script injecting
*/
if(loadSDK) {
(function injectScript() {
if(loadSDK) {
facebookDivLoad.promise.then(function() {
var src = '//connect.facebook.net/' + settings.locale + '/sdk.js',
script = document.createElement('script');
script.id = 'facebook-jssdk';
Expand All @@ -552,9 +563,9 @@

// Fix for IE < 9, and yet supported by latest browsers
document.getElementsByTagName('head')[0].appendChild(script);
})();
});
}
}
]);

})(window, angular);
})(window, angular);
73 changes: 46 additions & 27 deletions test/unit/service.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ describe('Service: Facebook', function () {
facebookProvider,
$window,
$timeout,
$q,
$rootScope,
fbSubscribeEventFunctions,
fbUnsubscribeEventFunctions,
getLoginStatusCallback,
Expand All @@ -17,10 +19,12 @@ describe('Service: Facebook', function () {
facebookProvider = _FacebookProvider_;
});

inject(function (_Facebook_, _$window_, _$timeout_) {
inject(function (_Facebook_, _$window_, _$timeout_,_$q_,_$rootScope_) {
facebook = _Facebook_;
$window = _$window_;
$timeout = _$timeout_;
$q = _$q_;
$rootScope = _$rootScope_;
});

fbSubscribeEventFunctions = {};
Expand Down Expand Up @@ -49,11 +53,17 @@ describe('Service: Facebook', function () {
};
});

it('should throw an error when no trying to initalize and no appId is provided', function() {
expect(function() {
$window.fbAsyncInit();
$timeout.flush();
}).toThrow('Missing appId setting.');
it('should throw an error when no trying to initalize and no appId is provided', function(done) {
$window.fbAsyncInit().then(function(){

},function(error){
expect(error).toBe('Missing appId setting.');
done();
});
//
// expect(function() {
// $window.fbAsyncInit();
// }).toThrow('Missing appId setting.');
});

// review(mrzymr): is this useful ?
Expand All @@ -73,31 +83,36 @@ describe('Service: Facebook', function () {

describe('after running $window.fbAsyncInit', function() {

beforeEach(function () {

beforeEach(function (done) {
facebookProvider.init('123456');
$window.fbAsyncInit();
$timeout.flush();
$window.fbAsyncInit().then(function(){
done();
});
});

it('isReady should answer with true', function() {
expect(facebook.isReady()).toBe(true);
});

it('should broadcast on $rootScope when facebook event is emitted', inject(function($rootScope) {
it('should broadcast on $rootScope when facebook event is emitted', function(done) {
spyOn($rootScope, '$broadcast');
var cbFn = function() {};
fbSubscribeEventFunctions['comment.remove'](cbFn);
$timeout.flush();
expect($rootScope.$broadcast).toHaveBeenCalledWith('Facebook:uncomment', cbFn);
}));
t = fbSubscribeEventFunctions['comment.remove'](cbFn);
t.then(function(){
expect($rootScope.$broadcast).toHaveBeenCalledWith('Facebook:uncomment', cbFn);
done();
});
// $timeout.flush();
});

it('should be mapped parseXFBML to window.FB.XFBML.parse', inject(function () {
facebook.parseXFBML();
$timeout.flush();
expect($window.FB.XFBML.parse).toHaveBeenCalled();
}));

it('should map the (un)subscribe method to window.FB.Event', function() {
it('should map the (un)subscribe method to window.FB.Event', function(done) {

var subCallbackFn = jasmine.createSpy('subCallbackFn');
var subCallbackEmptyResponseFn = jasmine.createSpy('subCallbackEmptyResponseFn');
Expand All @@ -114,19 +129,21 @@ describe('Service: Facebook', function () {

$timeout.flush();

fbSubscribeEventFunctions['comment.create'](null);
fbSubscribeEventFunctions['edge.remove'](testData);
fbUnsubscribeEventFunctions['edge.remove'](testData);

$timeout.flush();

expect($window.FB.Event.subscribe.calls.argsFor(0)[0]).toBe('comment.create');
expect($window.FB.Event.subscribe.calls.argsFor(1)[0]).toBe('edge.remove');
expect($window.FB.Event.unsubscribe.calls.argsFor(0)[0]).toBe('edge.remove');
$q.all([
fbSubscribeEventFunctions['comment.create'](null),
fbSubscribeEventFunctions['edge.remove'](testData),
fbUnsubscribeEventFunctions['edge.remove'](testData)
]).then(function(){
expect($window.FB.Event.subscribe.calls.argsFor(0)[0]).toBe('comment.create');
expect($window.FB.Event.subscribe.calls.argsFor(1)[0]).toBe('edge.remove');
expect($window.FB.Event.unsubscribe.calls.argsFor(0)[0]).toBe('edge.remove');

expect(subCallbackFn).toHaveBeenCalledWith(testData);
expect(unSubCallbackFn).toHaveBeenCalledWith(testData);
expect(subCallbackEmptyResponseFn).toHaveBeenCalledWith(null);
done()
});

expect(subCallbackFn).toHaveBeenCalledWith(testData);
expect(unSubCallbackFn).toHaveBeenCalledWith(testData);
expect(subCallbackEmptyResponseFn).toHaveBeenCalledWith(null);
});

it('should map the getLoginStatus/api method to window.FB', function() {
Expand All @@ -140,11 +157,13 @@ describe('Service: Facebook', function () {
facebook.api(apiCallbackFn);

$timeout.flush();
$rootScope.$digest();

getLoginStatusCallback({ user: true });
apiCallback(false);

$timeout.flush();
$rootScope.$digest();

expect($window.FB.getLoginStatus).toHaveBeenCalled();
expect(getLoginStatusCallbackFn).toHaveBeenCalled();
Expand Down