summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/general/browser_fxaccounts.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/general/browser_fxaccounts.js')
-rw-r--r--browser/base/content/test/general/browser_fxaccounts.js261
1 files changed, 261 insertions, 0 deletions
diff --git a/browser/base/content/test/general/browser_fxaccounts.js b/browser/base/content/test/general/browser_fxaccounts.js
new file mode 100644
index 000000000..0f68286dc
--- /dev/null
+++ b/browser/base/content/test/general/browser_fxaccounts.js
@@ -0,0 +1,261 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var {Log} = Cu.import("resource://gre/modules/Log.jsm", {});
+var {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+var {fxAccounts} = Cu.import("resource://gre/modules/FxAccounts.jsm", {});
+var FxAccountsCommon = {};
+Cu.import("resource://gre/modules/FxAccountsCommon.js", FxAccountsCommon);
+
+const TEST_ROOT = "http://example.com/browser/browser/base/content/test/general/";
+
+// instrument gFxAccounts to send observer notifications when it's done
+// what it does.
+(function() {
+ let unstubs = {}; // The original functions we stub out.
+
+ // The stub functions.
+ let stubs = {
+ updateAppMenuItem: function() {
+ return unstubs['updateAppMenuItem'].call(gFxAccounts).then(() => {
+ Services.obs.notifyObservers(null, "test:browser_fxaccounts:updateAppMenuItem", null);
+ });
+ },
+ // Opening preferences is trickier than it should be as leaks are reported
+ // due to the promises it fires off at load time and there's no clear way to
+ // know when they are done.
+ // So just ensure openPreferences is called rather than whether it opens.
+ openPreferences: function() {
+ Services.obs.notifyObservers(null, "test:browser_fxaccounts:openPreferences", null);
+ }
+ };
+
+ for (let name in stubs) {
+ unstubs[name] = gFxAccounts[name];
+ gFxAccounts[name] = stubs[name];
+ }
+ // and undo our damage at the end.
+ registerCleanupFunction(() => {
+ for (let name in unstubs) {
+ gFxAccounts[name] = unstubs[name];
+ }
+ stubs = unstubs = null;
+ });
+})();
+
+// Other setup/cleanup
+var newTab;
+
+Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri",
+ TEST_ROOT + "accounts_testRemoteCommands.html");
+
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("identity.fxaccounts.remote.signup.uri");
+ Services.prefs.clearUserPref("identity.fxaccounts.remote.profile.uri");
+ gBrowser.removeTab(newTab);
+});
+
+add_task(function* initialize() {
+ // Set a new tab with something other than about:blank, so it doesn't get reused.
+ // We must wait for it to load or the promiseTabOpen() call in the next test
+ // gets confused.
+ newTab = gBrowser.selectedTab = gBrowser.addTab("about:mozilla", {animate: false});
+ yield promiseTabLoaded(newTab);
+});
+
+// The elements we care about.
+var panelUILabel = document.getElementById("PanelUI-fxa-label");
+var panelUIStatus = document.getElementById("PanelUI-fxa-status");
+var panelUIFooter = document.getElementById("PanelUI-footer-fxa");
+
+// The tests
+add_task(function* test_nouser() {
+ let user = yield fxAccounts.getSignedInUser();
+ Assert.strictEqual(user, null, "start with no user signed in");
+ let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateAppMenuItem");
+ Services.obs.notifyObservers(null, this.FxAccountsCommon.ONLOGOUT_NOTIFICATION, null);
+ yield promiseUpdateDone;
+
+ // Check the world - the FxA footer area is visible as it is offering a signin.
+ Assert.ok(isFooterVisible())
+
+ Assert.equal(panelUILabel.getAttribute("label"), panelUIStatus.getAttribute("defaultlabel"));
+ Assert.equal(panelUIStatus.getAttribute("tooltiptext"), panelUIStatus.getAttribute("signedinTooltiptext"));
+ Assert.ok(!panelUIFooter.hasAttribute("fxastatus"), "no fxsstatus when signed out");
+ Assert.ok(!panelUIFooter.hasAttribute("fxaprofileimage"), "no fxaprofileimage when signed out");
+
+ let promisePreferencesOpened = promiseObserver("test:browser_fxaccounts:openPreferences");
+ panelUIStatus.click();
+ yield promisePreferencesOpened;
+});
+
+/*
+XXX - Bug 1191162 - need a better hawk mock story or this will leak in debug builds.
+
+add_task(function* test_unverifiedUser() {
+ let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateAppMenuItem");
+ yield setSignedInUser(false); // this will fire the observer that does the update.
+ yield promiseUpdateDone;
+
+ // Check the world.
+ Assert.ok(isFooterVisible())
+
+ Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
+ Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
+ panelUIStatus.getAttribute("signedinTooltiptext"));
+ Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
+ let promisePreferencesOpened = promiseObserver("test:browser_fxaccounts:openPreferences");
+ panelUIStatus.click();
+ yield promisePreferencesOpened
+ yield signOut();
+});
+*/
+
+add_task(function* test_verifiedUserEmptyProfile() {
+ // We see 2 updateAppMenuItem() calls - one for the signedInUser and one after
+ // we first fetch the profile. We want them both to fire or we aren't testing
+ // the state we think we are testing.
+ let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateAppMenuItem", 2);
+ gFxAccounts._cachedProfile = null;
+ configureProfileURL({}); // successful but empty profile.
+ yield setSignedInUser(true); // this will fire the observer that does the update.
+ yield promiseUpdateDone;
+
+ // Check the world.
+ Assert.ok(isFooterVisible())
+ Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
+ Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
+ panelUIStatus.getAttribute("signedinTooltiptext"));
+ Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
+
+ let promisePreferencesOpened = promiseObserver("test:browser_fxaccounts:openPreferences");
+ panelUIStatus.click();
+ yield promisePreferencesOpened;
+ yield signOut();
+});
+
+add_task(function* test_verifiedUserDisplayName() {
+ let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateAppMenuItem", 2);
+ gFxAccounts._cachedProfile = null;
+ configureProfileURL({ displayName: "Test User Display Name" });
+ yield setSignedInUser(true); // this will fire the observer that does the update.
+ yield promiseUpdateDone;
+
+ Assert.ok(isFooterVisible())
+ Assert.equal(panelUILabel.getAttribute("label"), "Test User Display Name");
+ Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
+ panelUIStatus.getAttribute("signedinTooltiptext"));
+ Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
+ yield signOut();
+});
+
+add_task(function* test_verifiedUserProfileFailure() {
+ // profile failure means only one observer fires.
+ let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateAppMenuItem", 1);
+ gFxAccounts._cachedProfile = null;
+ configureProfileURL(null, 500);
+ yield setSignedInUser(true); // this will fire the observer that does the update.
+ yield promiseUpdateDone;
+
+ Assert.ok(isFooterVisible())
+ Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
+ Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
+ panelUIStatus.getAttribute("signedinTooltiptext"));
+ Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
+ yield signOut();
+});
+
+// Helpers.
+function isFooterVisible() {
+ let style = window.getComputedStyle(panelUIFooter);
+ return style.getPropertyValue("display") == "flex";
+}
+
+function configureProfileURL(profile, responseStatus = 200) {
+ let responseBody = profile ? JSON.stringify(profile) : "";
+ let url = TEST_ROOT + "fxa_profile_handler.sjs?" +
+ "responseStatus=" + responseStatus +
+ "responseBody=" + responseBody +
+ // This is a bit cheeky - the FxA code will just append "/profile"
+ // to the preference value. We arrange for this to be seen by our
+ // .sjs as part of the query string.
+ "&path=";
+
+ Services.prefs.setCharPref("identity.fxaccounts.remote.profile.uri", url);
+}
+
+function promiseObserver(topic, count = 1) {
+ return new Promise(resolve => {
+ let obs = (aSubject, aTopic, aData) => {
+ if (--count == 0) {
+ Services.obs.removeObserver(obs, aTopic);
+ resolve(aSubject);
+ }
+ }
+ Services.obs.addObserver(obs, topic, false);
+ });
+}
+
+// Stolen from browser_aboutHome.js
+function promiseWaitForEvent(node, type, capturing) {
+ return new Promise((resolve) => {
+ node.addEventListener(type, function listener(event) {
+ node.removeEventListener(type, listener, capturing);
+ resolve(event);
+ }, capturing);
+ });
+}
+
+var promiseTabOpen = Task.async(function*(urlBase) {
+ info("Waiting for tab to open...");
+ let event = yield promiseWaitForEvent(gBrowser.tabContainer, "TabOpen", true);
+ let tab = event.target;
+ yield promiseTabLoadEvent(tab);
+ ok(tab.linkedBrowser.currentURI.spec.startsWith(urlBase),
+ "Got " + tab.linkedBrowser.currentURI.spec + ", expecting " + urlBase);
+ let whenUnloaded = promiseTabUnloaded(tab);
+ gBrowser.removeTab(tab);
+ yield whenUnloaded;
+});
+
+function promiseTabUnloaded(tab)
+{
+ return new Promise(resolve => {
+ info("Wait for tab to unload");
+ function handle(event) {
+ tab.linkedBrowser.removeEventListener("unload", handle, true);
+ info("Got unload event");
+ resolve(event);
+ }
+ tab.linkedBrowser.addEventListener("unload", handle, true, true);
+ });
+}
+
+// FxAccounts helpers.
+function setSignedInUser(verified) {
+ let data = {
+ email: "foo@example.com",
+ uid: "1234@lcip.org",
+ assertion: "foobar",
+ sessionToken: "dead",
+ kA: "beef",
+ kB: "cafe",
+ verified: verified,
+
+ oauthTokens: {
+ // a token for the profile server.
+ profile: "key value",
+ }
+ }
+ return fxAccounts.setSignedInUser(data);
+}
+
+var signOut = Task.async(function* () {
+ // This test needs to make sure that any updates for the logout have
+ // completed before starting the next test, or we see the observer
+ // notifications get out of sync.
+ let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateAppMenuItem");
+ // we always want a "localOnly" signout here...
+ yield fxAccounts.signOut(true);
+ yield promiseUpdateDone;
+});