Bug 1047181 - Change the Loop toolbar button when FxA sign in completes. r=MattN

This commit is contained in:
Jared Wein 2014-09-18 16:14:44 -04:00
parent 4698186fd1
commit ac1da29c34
5 changed files with 107 additions and 12 deletions

View File

@ -32,6 +32,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel
}, true);
};
// Used to clear the temporary "login" state from the button.
Services.obs.notifyObservers(null, "loop-status-changed", null);
PanelFrame.showPopup(window, event.target, "loop", null,
"about:looppanel", null, callback);
},
@ -69,13 +72,25 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel
if (topic != "loop-status-changed") {
return;
}
this.updateToolbarState();
this.updateToolbarState(data);
},
updateToolbarState: function() {
/**
* Updates the toolbar/menu-button state to reflect Loop status.
*
* @param {string} [aReason] Some states are only shown if
* a related reason is provided.
*
* aReason="login": Used after a login is completed
* successfully. This is used so the state can be
* temporarily shown until the next state change.
*/
updateToolbarState: function(aReason = null) {
let state = "";
if (MozLoopService.errors.size) {
state = "error";
} else if (aReason == "login" && MozLoopService.userProfile) {
state = "active";
} else if (MozLoopService.doNotDisturb) {
state = "disabled";
}

View File

@ -160,8 +160,8 @@ let MozLoopServiceInternal = {
this.notifyStatusChanged();
},
notifyStatusChanged: function() {
Services.obs.notifyObservers(null, "loop-status-changed", null);
notifyStatusChanged: function(aReason = null) {
Services.obs.notifyObservers(null, "loop-status-changed", aReason);
},
/**
@ -1024,7 +1024,7 @@ this.MozLoopService = {
});
client.fetchProfile().then(result => {
gFxAOAuthProfile = result;
MozLoopServiceInternal.notifyStatusChanged();
MozLoopServiceInternal.notifyStatusChanged("login");
}, error => {
console.error("Failed to retrieve profile", error);
gFxAOAuthProfile = null;

View File

@ -219,20 +219,27 @@ add_task(function* basicAuthorizationAndRegistration() {
info("registering");
mockPushHandler.pushUrl = "https://localhost/pushUrl/guest";
// Notification observed due to the error being cleared upon successful registration.
let statusChangedPromise = promiseObserverNotified("loop-status-changed");
yield MozLoopService.register(mockPushHandler);
yield statusChangedPromise;
// Normally the same pushUrl would be registered but we change it in the test
// to be able to check for success on the second registration.
mockPushHandler.pushUrl = "https://localhost/pushUrl/fxa";
statusChangedPromise = promiseObserverNotified("loop-status-changed");
yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true});
yield statusChangedPromise;
let loopDoc = document.getElementById("loop").contentDocument;
let visibleEmail = loopDoc.getElementsByClassName("user-identity")[0];
is(visibleEmail.textContent, "Guest", "Guest should be displayed on the panel when not logged in");
is(MozLoopService.userProfile, null, "profile should be null before log-in");
let loopButton = document.getElementById("loop-call-button");
is(loopButton.getAttribute("state"), "", "state of loop button should be empty when not logged in");
let tokenData = yield MozLoopService.logInToFxA();
yield promiseObserverNotified("loop-status-changed");
yield promiseObserverNotified("loop-status-changed", "login");
ise(tokenData.access_token, "code1_access_token", "Check access_token");
ise(tokenData.scope, "profile", "Check scope");
ise(tokenData.token_type, "bearer", "Check token_type");
@ -240,9 +247,18 @@ add_task(function* basicAuthorizationAndRegistration() {
is(MozLoopService.userProfile.email, "test@example.com", "email should exist in the profile data");
is(MozLoopService.userProfile.uid, "1234abcd", "uid should exist in the profile data");
is(visibleEmail.textContent, "test@example.com", "the email should be correct on the panel");
is(loopButton.getAttribute("state"), "active", "state of loop button should be active when logged in");
let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
ise(registrationResponse.response.simplePushURL, "https://localhost/pushUrl/fxa", "Check registered push URL");
let loopPanel = document.getElementById("loop-notification-panel");
loopPanel.hidePopup();
statusChangedPromise = promiseObserverNotified("loop-status-changed");
yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true});
yield statusChangedPromise;
is(loopButton.getAttribute("state"), "", "state of loop button should return to empty after panel is opened");
loopPanel.hidePopup();
});
add_task(function* loginWithParams401() {

View File

@ -9,19 +9,69 @@
registerCleanupFunction(function*() {
MozLoopService.doNotDisturb = false;
setInternalLoopGlobal("gFxAOAuthProfile", null);
yield MozLoopServiceInternal.clearError("testing");
});
add_task(function* test_doNotDisturb() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopService.doNotDisturb = true;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state");
yield MozLoopService.doNotDisturb = false;
Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is not in disabled state");
});
add_task(function* test_doNotDisturb_with_login() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopService.doNotDisturb = true;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state");
setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
yield MozLoopServiceInternal.notifyStatusChanged("login");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state");
yield loadLoopPanel();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state after opening panel");
let loopPanel = document.getElementById("loop-notification-panel");
loopPanel.hidePopup();
yield MozLoopService.doNotDisturb = false;
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
setInternalLoopGlobal("gFxAOAuthProfile", null);
yield MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
});
add_task(function* test_error() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopServiceInternal.setError("testing", {});
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
yield MozLoopServiceInternal.clearError("testing");
Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is not in error state");
});
add_task(function* test_error_with_login() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
yield MozLoopServiceInternal.setError("testing", {});
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
MozLoopServiceInternal.notifyStatusChanged("login");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
yield MozLoopServiceInternal.clearError("testing");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
setInternalLoopGlobal("gFxAOAuthProfile", null);
MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
});
add_task(function* test_active() {
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
yield MozLoopServiceInternal.notifyStatusChanged("login");
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state");
yield loadLoopPanel();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state after opening panel");
let loopPanel = document.getElementById("loop-notification-panel");
loopPanel.hidePopup();
setInternalLoopGlobal("gFxAOAuthProfile", null);
MozLoopServiceInternal.notifyStatusChanged();
Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
});

View File

@ -7,6 +7,11 @@ const {
MozLoopServiceInternal,
} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
// Cache this value only once, at the beginning of a
// test run, so that it doesn't pick up the offline=true
// if offline mode is requested multiple times in a test run.
const WAS_OFFLINE = Services.io.offline;
var gMozLoopAPI;
function promiseGetMozLoopAPI() {
@ -46,7 +51,11 @@ function promiseGetMozLoopAPI() {
// life of the application.
registerCleanupFunction(function() {
loopPanel.hidePopup();
loopPanel.removeChild(document.getElementById(btn.getAttribute("notificationFrameId")));
let frameId = btn.getAttribute("notificationFrameId");
let frame = document.getElementById(frameId);
if (frame) {
loopPanel.removeChild(frame);
}
});
return deferred.promise;
@ -67,7 +76,6 @@ function loadLoopPanel(aOverrideOptions = {}) {
// try to access the remote servers. If we want to turn this
// back on in future, be careful to check for intermittent
// failures.
let wasOffline = Services.io.offline;
if (!aOverrideOptions.stayOnline) {
Services.io.offline = true;
}
@ -75,7 +83,7 @@ function loadLoopPanel(aOverrideOptions = {}) {
registerCleanupFunction(function() {
Services.prefs.clearUserPref("services.push.serverURL");
Services.prefs.clearUserPref("loop.server");
Services.io.offline = wasOffline;
Services.io.offline = WAS_OFFLINE;
});
// Turn off animations to make tests quicker.
@ -110,6 +118,11 @@ function resetFxA() {
Services.prefs.clearUserPref(fxASessionPref);
}
function setInternalLoopGlobal(aName, aValue) {
let global = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
global[aName] = aValue;
}
function promiseDeletedOAuthParams(baseURL) {
let deferred = Promise.defer();
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
@ -122,12 +135,13 @@ function promiseDeletedOAuthParams(baseURL) {
return deferred.promise;
}
function promiseObserverNotified(aTopic) {
function promiseObserverNotified(aTopic, aExpectedData = null) {
let deferred = Promise.defer();
Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) {
Services.obs.removeObserver(onNotification, aTopic);
deferred.resolve({subject: aSubject, data: aData});
}, aTopic, false);
is(aData, aExpectedData, "observer data should match expected data")
deferred.resolve({subject: aSubject, data: aData});
}, aTopic, false);
return deferred.promise;
}