Check out "Do you speak JavaScript?" - my latest video course on advanced JavaScript.
Language APIs, Popular Concepts, Design Patterns, Advanced Techniques In the Browser

Testing Facebook application

I had a lot of work these days and didn't have time to blog here, but I think that the tips in this article are very useful. The number of Facebook applications is increasing every day. We all know that the testing (debugging) of our code is really important. That's why I decided to share my experience in this area.

1. Creating facebook application

  • Go to https://developers.facebook.com/apps
  • Click on + Create New App [2]
  • Type the name of your application and click Continue [3]
  • Copy/remember your App ID and App Secret [4]
  • Set your App Domain and Site URL (I'm using a virtual host of my local machine. As far as I know currently Facebook doesn't allow the usage of multiple domains.) [5]

When you have a created application you are ready for testing. Because I have experience only with PHP and JavaScript SDK my examples are related to those areas.

2. Testing with PHP SDK

For my PHP tests I'm using my own version of SimpleTest. Here is a short script that illustrates the usage of Test class.

require_once("Test.php");
class MyCustomTestingCase extends TestCase {
  public function customMethod() {
    $this->describe("is 2 + 2 = 4")->isTrue(2 + 2 == 4);
    $this->describe("is 1 + 1 = 5")->isTrue(1 + 1 == 5);
  }
}
Test::run(new MyCustomTestingCase());

And the result is:[6]So, we have a tool for testing. The second thing that we need is the Facebook's PHP SDK. Download it from here and create a new php with the following content:

require_once("Facebook/facebook.php");
// including Facebook's SDK
require_once("Test.php");
// including the TestCase class
// Facebook application's configuration
$config = (object) array(
  "id" => "...", // set your App ID here
  "secret" => "..." // set your App ID here
);
class FacebookTestingCase extends TestCase {
  public $config;
  private $facebook;
  private $facebookToken;
  private $facebookUser;
}
$fb = new FacebookTestingCase();
$fb->config = $config; // passing the configuration to our test case class
Test::run($fb); // running the test

Firstly we should check if the configuration is available:

public function testConfig() {
  $this->describe("check if config is passed")->isNotNull($this->config);
}
public function testAppIDAndSecret() {
  $this->describe("id should not be empty")->isNotEmptyString($this->config->id);
  $this->describe("secret should not be empty")->isNotEmptyString($this->config->secret);
}

After that we have to initialize the SDK and check if there is a token available:

public function initSDK() {
  $this->facebook = new Facebook(array(
    'appId'  => $this->config->id,
    'secret' => $this->config->secret,
  ));
  $this->isNotNull($this->facebook);
}
public function getAccessToken() {
  $this->facebookToken = $this->facebook->getAccessToken();
  $this->isNotEmptyString($this->facebookToken);
}

And finally check if there is a logged Facebook user:

public function getCurrentLoggedUser() {
  $this->facebookUser = $this->facebook->getUser();
  $this->isNotEqual($this->facebookUser, 0);
  if($this->facebookUser == 0) {
    echo '<a href="'.$this->facebook->getLoginUrl().'">login</a>';
  } else {
    echo '<a href="'.$this->facebook->getLogoutUrl().'">logout</a>';
  }
}
public function getCurrentUserInformation() {
  if($this->facebookUser != 0) {
    var_dump($this->facebook->api('/me'));
  }
}

Of course the FacebookTestingCase class could be filled with more methods, which may check something else depending on your custom application's logic.

3. Testing with JavaScript SDK

I really like Jasmine for JavaScript testing. That's why I strongly recommend it and I'm using it for this example. I think that it is a good idea to wrap the Facebook's stuff in a module. You can use this module in some of your next projects and it is much more flexible for testing.

var Facebook = (function () {
  var _response = null;
  var _foundLogoutButton = false;
  var _facebookLoginButton = false;
  // initialize the JS SDK
  var init = function () {
    FB.init({
      appId: appID,
      status: true,
      cookie: true,
      xfbml: false,
      channelURL: "channel.html",
      oauth: true
    });
  };
  // checking if there is logged user
  var getLoginStatus = function () {
    FB.getLoginStatus(function (response) {
      _response = response;
      if (!response.authResponse) {
        document.getElementById("login").style.display = "block";
      };
    });
  };
  // getting the response of FB.getLoginStatus
  var getLoginStatusResponse = function () {
    return _response;
  };
  // forcing the Facebook's login  
  var login = function () {
    FB.login(function (response) {
      if (response.authResponse) {
        window.location = 'index.php';
      }
    });
  };
  return {
    init: init,
    login: login,
    getLoginStatus: getLoginStatus,
    getLoginStatusResponse: getLoginStatusResponse
  };
})();

Nothing fancy. Just simple usage of the SDK. Here it is the full Jasmine test:

var appID = "..."; // your id here
describe("Facebook", function () {
  it("We should have global Facebook object", function () {
    expect(typeof Facebook != "undefined").toEqual(true);
  });
  it("is FB available (i.e. is facebook library included)", function () {
    expect(typeof FB != "undefined").toEqual(true);
  });
  it("do we have an application id", function () {
    expect(appID != "").toEqual(true);
  });
  it("initialize the facebook library", function () {
    Facebook.init();
  });
  it("Checking for active facebook session", function () {
    Facebook.getLoginStatus();
    waitsFor(function () {
      return Facebook.getLoginStatusResponse() && Facebook.getLoginStatusResponse().authResponse;
    }, "response.authResponse", 7000);
  });
});
window.onload = function () {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 1000;
  var trivialReporter = new jasmine.TrivialReporter();
  jasmineEnv.addReporter(trivialReporter);
  jasmineEnv.execute();
};

The result if you are logged:[8]As a conclusion I could say that the testing of FB applications is not very pleasant task. Facebook still doesn't provide any information if something goes wrong. It will be good if we (as developers) know what exactly is not ok. For example if we use wrong application ID or wrong App Domain name. We should at least receive some result of our requests. I believe that Facebook are going in the right direction.

If you enjoy this post, share it on Twitter, Facebook or LinkedIn.