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