michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: XPCOMUtils.defineLazyModuleGetter(this, "Promise", michael@0: "resource://gre/modules/Promise.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "Task", michael@0: "resource://gre/modules/Task.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts", michael@0: "resource://gre/modules/FxAccounts.jsm"); michael@0: michael@0: const CHROME_BASE = "chrome://mochitests/content/browser/browser/base/content/test/general/"; michael@0: // Preference helpers. michael@0: let changedPrefs = new Set(); michael@0: michael@0: function setPref(name, value) { michael@0: changedPrefs.add(name); michael@0: Services.prefs.setCharPref(name, value); michael@0: } michael@0: michael@0: registerCleanupFunction(function() { michael@0: // Ensure we don't pollute prefs for next tests. michael@0: for (let name of changedPrefs) { michael@0: Services.prefs.clearUserPref(name); michael@0: } michael@0: }); michael@0: michael@0: let gTests = [ michael@0: { michael@0: desc: "Test the remote commands", michael@0: teardown: function* () { michael@0: gBrowser.removeCurrentTab(); michael@0: yield fxAccounts.signOut(); michael@0: }, michael@0: run: function* () michael@0: { michael@0: setPref("identity.fxaccounts.remote.signup.uri", michael@0: "https://example.com/browser/browser/base/content/test/general/accounts_testRemoteCommands.html"); michael@0: yield promiseNewTabLoadEvent("about:accounts"); michael@0: michael@0: let deferred = Promise.defer(); michael@0: michael@0: let results = 0; michael@0: try { michael@0: let win = gBrowser.contentWindow; michael@0: win.addEventListener("message", function testLoad(e) { michael@0: if (e.data.type == "testResult") { michael@0: ok(e.data.pass, e.data.info); michael@0: results++; michael@0: } michael@0: else if (e.data.type == "testsComplete") { michael@0: is(results, e.data.count, "Checking number of results received matches the number of tests that should have run"); michael@0: win.removeEventListener("message", testLoad, false, true); michael@0: deferred.resolve(); michael@0: } michael@0: michael@0: }, false, true); michael@0: michael@0: } catch(e) { michael@0: ok(false, "Failed to get all commands"); michael@0: deferred.reject(); michael@0: } michael@0: yield deferred.promise; michael@0: } michael@0: }, michael@0: { michael@0: desc: "Test action=signin - no user logged in", michael@0: teardown: () => gBrowser.removeCurrentTab(), michael@0: run: function* () michael@0: { michael@0: // When this loads with no user logged-in, we expect the "normal" URL michael@0: const expected_url = "https://example.com/?is_sign_in"; michael@0: setPref("identity.fxaccounts.remote.signin.uri", expected_url); michael@0: let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?action=signin"); michael@0: is(url, expected_url, "action=signin got the expected URL"); michael@0: // we expect the remote iframe to be shown. michael@0: yield checkVisibilities(tab, { michael@0: stage: false, // parent of 'manage' and 'intro' michael@0: manage: false, michael@0: intro: false, // this is "get started" michael@0: remote: true michael@0: }); michael@0: } michael@0: }, michael@0: { michael@0: desc: "Test action=signin - user logged in", michael@0: teardown: function* () { michael@0: gBrowser.removeCurrentTab(); michael@0: yield signOut(); michael@0: }, michael@0: run: function* () michael@0: { michael@0: // When this loads with a user logged-in, we expect the normal URL to michael@0: // have been ignored and the "manage" page to be shown. michael@0: const expected_url = "https://example.com/?is_sign_in"; michael@0: setPref("identity.fxaccounts.remote.signin.uri", expected_url); michael@0: yield setSignedInUser(); michael@0: let tab = yield promiseNewTabLoadEvent("about:accounts?action=signin"); michael@0: // about:accounts initializes after fetching the current user from Fxa - michael@0: // so we also request it - by the time we get it we know it should have michael@0: // done its thing. michael@0: yield fxAccounts.getSignedInUser(); michael@0: // we expect "manage" to be shown. michael@0: yield checkVisibilities(tab, { michael@0: stage: true, // parent of 'manage' and 'intro' michael@0: manage: true, michael@0: intro: false, // this is "get started" michael@0: remote: false michael@0: }); michael@0: } michael@0: }, michael@0: { michael@0: desc: "Test action=signup - no user logged in", michael@0: teardown: () => gBrowser.removeCurrentTab(), michael@0: run: function* () michael@0: { michael@0: const expected_url = "https://example.com/?is_sign_up"; michael@0: setPref("identity.fxaccounts.remote.signup.uri", expected_url); michael@0: let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?action=signup"); michael@0: is(url, expected_url, "action=signup got the expected URL"); michael@0: // we expect the remote iframe to be shown. michael@0: yield checkVisibilities(tab, { michael@0: stage: false, // parent of 'manage' and 'intro' michael@0: manage: false, michael@0: intro: false, // this is "get started" michael@0: remote: true michael@0: }); michael@0: }, michael@0: }, michael@0: { michael@0: desc: "Test action=signup - user logged in", michael@0: teardown: () => gBrowser.removeCurrentTab(), michael@0: run: function* () michael@0: { michael@0: const expected_url = "https://example.com/?is_sign_up"; michael@0: setPref("identity.fxaccounts.remote.signup.uri", expected_url); michael@0: yield setSignedInUser(); michael@0: let tab = yield promiseNewTabLoadEvent("about:accounts?action=signup"); michael@0: yield fxAccounts.getSignedInUser(); michael@0: // we expect "manage" to be shown. michael@0: yield checkVisibilities(tab, { michael@0: stage: true, // parent of 'manage' and 'intro' michael@0: manage: true, michael@0: intro: false, // this is "get started" michael@0: remote: false michael@0: }); michael@0: }, michael@0: }, michael@0: { michael@0: desc: "Test action=reauth", michael@0: teardown: function* () { michael@0: gBrowser.removeCurrentTab(); michael@0: yield signOut(); michael@0: }, michael@0: run: function* () michael@0: { michael@0: const expected_url = "https://example.com/?is_force_auth"; michael@0: setPref("identity.fxaccounts.remote.force_auth.uri", expected_url); michael@0: let userData = { michael@0: email: "foo@example.com", michael@0: uid: "1234@lcip.org", michael@0: assertion: "foobar", michael@0: sessionToken: "dead", michael@0: kA: "beef", michael@0: kB: "cafe", michael@0: verified: true michael@0: }; michael@0: michael@0: yield setSignedInUser(); michael@0: let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?action=reauth"); michael@0: // The current user will be appended to the url michael@0: let expected = expected_url + "&email=foo%40example.com"; michael@0: is(url, expected, "action=reauth got the expected URL"); michael@0: }, michael@0: }, michael@0: { michael@0: desc: "Test observers about:accounts", michael@0: teardown: function() { michael@0: gBrowser.removeCurrentTab(); michael@0: }, michael@0: run: function* () { michael@0: setPref("identity.fxaccounts.remote.signup.uri", "https://example.com/"); michael@0: yield setSignedInUser(); michael@0: let tab = yield promiseNewTabLoadEvent("about:accounts"); michael@0: // sign the user out - the tab should have action=signin michael@0: yield signOut(); michael@0: // wait for the new load. michael@0: yield promiseOneMessage(tab, "test:document:load"); michael@0: is(tab.linkedBrowser.contentDocument.location.href, "about:accounts?action=signin"); michael@0: } michael@0: }, michael@0: ]; // gTests michael@0: michael@0: function test() michael@0: { michael@0: waitForExplicitFinish(); michael@0: michael@0: Task.spawn(function () { michael@0: for (let test of gTests) { michael@0: info(test.desc); michael@0: try { michael@0: yield test.run(); michael@0: } finally { michael@0: yield test.teardown(); michael@0: } michael@0: } michael@0: michael@0: finish(); michael@0: }); michael@0: } michael@0: michael@0: function promiseOneMessage(tab, messageName) { michael@0: let mm = tab.linkedBrowser.messageManager; michael@0: let deferred = Promise.defer(); michael@0: mm.addMessageListener(messageName, function onmessage(message) { michael@0: mm.removeMessageListener(messageName, onmessage); michael@0: deferred.resolve(message); michael@0: }); michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function promiseNewTabLoadEvent(aUrl) michael@0: { michael@0: let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl); michael@0: let browser = tab.linkedBrowser; michael@0: let mm = browser.messageManager; michael@0: michael@0: // give it an e10s-friendly content script to help with our tests. michael@0: mm.loadFrameScript(CHROME_BASE + "content_aboutAccounts.js", true); michael@0: // and wait for it to tell us about the load. michael@0: return promiseOneMessage(tab, "test:document:load").then( michael@0: () => tab michael@0: ); michael@0: } michael@0: michael@0: // Returns a promise which is resolved with the iframe's URL after a new michael@0: // tab is created and the iframe in that tab loads. michael@0: function promiseNewTabWithIframeLoadEvent(aUrl) { michael@0: let deferred = Promise.defer(); michael@0: let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl); michael@0: let browser = tab.linkedBrowser; michael@0: let mm = browser.messageManager; michael@0: michael@0: // give it an e10s-friendly content script to help with our tests. michael@0: mm.loadFrameScript(CHROME_BASE + "content_aboutAccounts.js", true); michael@0: // and wait for it to tell us about the iframe load. michael@0: mm.addMessageListener("test:iframe:load", function onFrameLoad(message) { michael@0: mm.removeMessageListener("test:iframe:load", onFrameLoad); michael@0: deferred.resolve([tab, message.data.url]); michael@0: }); michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function checkVisibilities(tab, data) { michael@0: let ids = Object.keys(data); michael@0: let mm = tab.linkedBrowser.messageManager; michael@0: let deferred = Promise.defer(); michael@0: mm.addMessageListener("test:check-visibilities-response", function onResponse(message) { michael@0: mm.removeMessageListener("test:check-visibilities-response", onResponse); michael@0: for (let id of ids) { michael@0: is(message.data[id], data[id], "Element '" + id + "' has correct visibility"); michael@0: } michael@0: deferred.resolve(); michael@0: }); michael@0: mm.sendAsyncMessage("test:check-visibilities", {ids: ids}); michael@0: return deferred.promise; michael@0: } michael@0: michael@0: // watch out - these will fire observers which if you aren't careful, may michael@0: // interfere with the tests. michael@0: function setSignedInUser(data) { michael@0: if (!data) { michael@0: data = { michael@0: email: "foo@example.com", michael@0: uid: "1234@lcip.org", michael@0: assertion: "foobar", michael@0: sessionToken: "dead", michael@0: kA: "beef", michael@0: kB: "cafe", michael@0: verified: true michael@0: } michael@0: } michael@0: return fxAccounts.setSignedInUser(data); michael@0: } michael@0: michael@0: function signOut() { michael@0: return fxAccounts.signOut(); michael@0: }