/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/DOMIdentity.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FirefoxAccounts", "resource://gre/modules/identity/FirefoxAccounts.jsm"); // Make the profile dir available; this is necessary so that // services/fxaccounts/FxAccounts.jsm can read and write its signed-in user // data. do_get_profile(); function MockFXAManager() { this.signedInUser = true; } MockFXAManager.prototype = { getAssertion: function(audience) { let result = this.signedInUser ? TEST_ASSERTION : null; return Promise.resolve(result); }, signOut: function() { this.signedInUser = false; return Promise.resolve(null); }, signIn: function(user) { this.signedInUser = user; return Promise.resolve(user); }, } var originalManager = FirefoxAccounts.fxAccountsManager; FirefoxAccounts.fxAccountsManager = new MockFXAManager(); do_register_cleanup(() => { log("restoring fxaccountsmanager"); FirefoxAccounts.fxAccountsManager = originalManager; }); function withNobodySignedIn() { return FirefoxAccounts.fxAccountsManager.signOut(); } function withSomebodySignedIn() { return FirefoxAccounts.fxAccountsManager.signIn('Pertelote'); } function test_overall() { do_check_neq(FirefoxAccounts, null); run_next_test(); } function test_mock() { do_test_pending(); withSomebodySignedIn().then(() => { FirefoxAccounts.fxAccountsManager.getAssertion().then(assertion => { do_check_eq(assertion, TEST_ASSERTION); do_test_finished(); run_next_test(); }); }); } function test_watch_signed_in() { do_test_pending(); let received = []; let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, data) { received.push([method, data]); if (method == "ready") { // confirm that we were signed in and then ready was called do_check_eq(received.length, 2); do_check_eq(received[0][0], "login"); do_check_eq(received[0][1], TEST_ASSERTION); do_check_eq(received[1][0], "ready"); do_test_finished(); run_next_test(); } }); withSomebodySignedIn().then(() => { FirefoxAccounts.RP.watch(mockedRP); }); } function test_watch_signed_out() { do_test_pending(); let received = []; let mockedRP = mock_fxa_rp(null, TEST_URL, function(method) { received.push(method); if (method == "ready") { // confirm that we were signed out and then ready was called do_check_eq(received.length, 2); do_check_eq(received[0], "logout"); do_check_eq(received[1], "ready"); do_test_finished(); run_next_test(); } }); withNobodySignedIn().then(() => { FirefoxAccounts.RP.watch(mockedRP); }); } function test_request() { do_test_pending(); let received = []; let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, data) { received.push([method, data]); // On watch(), we are signed out. Then we call request(). if (received.length === 2) { do_check_eq(received[0][0], "logout"); do_check_eq(received[1][0], "ready"); // Pretend request() showed ux and the user signed in withSomebodySignedIn().then(() => { FirefoxAccounts.RP.request(mockedRP.id); }); } if (received.length === 3) { do_check_eq(received[2][0], "login"); do_check_eq(received[2][1], TEST_ASSERTION); do_test_finished(); run_next_test(); } }); // First, call watch() with nobody signed in withNobodySignedIn().then(() => { FirefoxAccounts.RP.watch(mockedRP); }); } function test_logout() { do_test_pending(); let received = []; let mockedRP = mock_fxa_rp(null, TEST_URL, function(method) { received.push(method); // At first, watch() signs us in automatically. Then we sign out. if (received.length === 2) { do_check_eq(received[0], "login"); do_check_eq(received[1], "ready"); FirefoxAccounts.RP.logout(mockedRP.id); } if (received.length === 3) { do_check_eq(received[2], "logout"); do_test_finished(); run_next_test(); } }); // First, call watch() withSomebodySignedIn().then(() => { FirefoxAccounts.RP.watch(mockedRP); }); } function test_error() { do_test_pending(); let received = []; // Mock the fxAccountsManager so that getAssertion rejects its promise and // triggers our onerror handler. (This is the method that's used internally // by FirefoxAccounts.RP.request().) let originalGetAssertion = FirefoxAccounts.fxAccountsManager.getAssertion; FirefoxAccounts.fxAccountsManager.getAssertion = function(audience) { return Promise.reject(new Error("barf!")); }; let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, message) { // We will immediately receive an error, due to watch()'s attempt // to getAssertion(). do_check_eq(method, "error"); do_check_true(/barf/.test(message)); // Put things back the way they were FirefoxAccounts.fxAccountsManager.getAssertion = originalGetAssertion; do_test_finished(); run_next_test(); }); // First, call watch() withSomebodySignedIn().then(() => { FirefoxAccounts.RP.watch(mockedRP); }); } function test_child_process_shutdown() { do_test_pending(); let rpCount = FirefoxAccounts.RP._rpFlows.size; makeObserver("identity-child-process-shutdown", (aTopic, aSubject, aData) => { // Last of all, the shutdown observer message will be fired. // This takes place after the RP has a chance to delete flows // and clean up. do_check_eq(FirefoxAccounts.RP._rpFlows.size, rpCount); do_test_finished(); run_next_test(); }); let mockedRP = mock_fxa_rp(null, TEST_URL, (method) => { // We should enter this function for 'ready' and 'child-process-shutdown'. // After we have a chance to do our thing, the shutdown observer message // will fire and be caught by the function above. do_check_eq(FirefoxAccounts.RP._rpFlows.size, rpCount + 1); switch (method) { case "ready": DOMIdentity._childProcessShutdown("my message manager"); break; case "child-process-shutdown": // We have to call this explicitly because there's no real // dom window here. FirefoxAccounts.RP.childProcessShutdown(mockedRP._mm); break; default: break; } }); mockedRP._mm = "my message manager"; withSomebodySignedIn().then(() => { FirefoxAccounts.RP.watch(mockedRP); }); // fake a dom window context DOMIdentity.newContext(mockedRP, mockedRP._mm); } var TESTS = [ test_overall, test_mock, test_watch_signed_in, test_watch_signed_out, test_request, test_logout, test_error, test_child_process_shutdown, ]; TESTS.forEach(add_test); function run_test() { run_next_test(); }