forked from mirrors/gecko-dev
205 lines
8 KiB
JavaScript
205 lines
8 KiB
JavaScript
/* 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 {Weave} = Cu.import("resource://services-sync/main.js", {});
|
|
|
|
var stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]
|
|
.getService(Ci.nsIStringBundleService)
|
|
.createBundle("chrome://weave/locale/services/sync.properties");
|
|
|
|
// ensure test output sees log messages.
|
|
Log.repository.getLogger("browserwindow.syncui").addAppender(new Log.DumpAppender());
|
|
|
|
// Send the specified sync-related notification and return a promise that
|
|
// resolves once gSyncUI._promiseUpateUI is complete and the UI is ready to check.
|
|
function notifyAndPromiseUIUpdated(topic) {
|
|
return new Promise(resolve => {
|
|
// Instrument gSyncUI so we know when the update is complete.
|
|
let oldPromiseUpdateUI = gSyncUI._promiseUpdateUI.bind(gSyncUI);
|
|
gSyncUI._promiseUpdateUI = function() {
|
|
return oldPromiseUpdateUI().then(() => {
|
|
// Restore our override.
|
|
gSyncUI._promiseUpdateUI = oldPromiseUpdateUI;
|
|
// Resolve the promise so the caller knows the update is done.
|
|
resolve();
|
|
});
|
|
};
|
|
// Now send the notification.
|
|
Services.obs.notifyObservers(null, topic, null);
|
|
});
|
|
}
|
|
|
|
// Sync manages 3 broadcasters so the menus correctly reflect the Sync state.
|
|
// Only one of these 3 should ever be visible - pass the ID of the broadcaster
|
|
// you expect to be visible and it will check it's the only one that is.
|
|
function checkBroadcasterVisible(broadcasterId) {
|
|
let all = ["sync-reauth-state", "sync-setup-state", "sync-syncnow-state"];
|
|
Assert.ok(all.indexOf(broadcasterId) >= 0, "valid id");
|
|
for (let check of all) {
|
|
let eltHidden = document.getElementById(check).hidden;
|
|
Assert.equal(eltHidden, check == broadcasterId ? false : true, check);
|
|
}
|
|
}
|
|
|
|
function promiseObserver(topic) {
|
|
return new Promise(resolve => {
|
|
let obs = (subject, topic, data) => {
|
|
Services.obs.removeObserver(obs, topic);
|
|
resolve(subject);
|
|
}
|
|
Services.obs.addObserver(obs, topic, false);
|
|
});
|
|
}
|
|
|
|
function checkButtonTooltips(stringPrefix) {
|
|
for (let butId of ["PanelUI-remotetabs-syncnow", "PanelUI-fxa-icon"]) {
|
|
let text = document.getElementById(butId).getAttribute("tooltiptext");
|
|
let desc = `Text is "${text}", expecting it to start with "${stringPrefix}"`
|
|
Assert.ok(text.startsWith(stringPrefix), desc);
|
|
}
|
|
}
|
|
|
|
add_task(function* prepare() {
|
|
// add the Sync button to the toolbar so we can get it!
|
|
CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_NAVBAR);
|
|
registerCleanupFunction(() => {
|
|
CustomizableUI.removeWidgetFromArea("sync-button");
|
|
});
|
|
|
|
let xps = Components.classes["@mozilla.org/weave/service;1"]
|
|
.getService(Components.interfaces.nsISupports)
|
|
.wrappedJSObject;
|
|
yield xps.whenLoaded();
|
|
// Put Sync and the UI into a known state.
|
|
Weave.Status.login = Weave.LOGIN_FAILED_NO_USERNAME;
|
|
yield notifyAndPromiseUIUpdated("weave:service:login:error");
|
|
|
|
checkBroadcasterVisible("sync-setup-state");
|
|
checkButtonTooltips("Sign In To Sync");
|
|
// mock out the "_needsSetup()" function so we don't short-circuit.
|
|
let oldNeedsSetup = window.gSyncUI._needsSetup;
|
|
window.gSyncUI._needsSetup = () => Promise.resolve(false);
|
|
registerCleanupFunction(() => {
|
|
window.gSyncUI._needsSetup = oldNeedsSetup;
|
|
// and an observer to set the state back to what it should be now we've
|
|
// restored the stub.
|
|
Services.obs.notifyObservers(null, "weave:service:login:finish", null);
|
|
});
|
|
// and a notification to have the state change away from "needs setup"
|
|
yield notifyAndPromiseUIUpdated("weave:service:login:finish");
|
|
checkBroadcasterVisible("sync-syncnow-state");
|
|
// open the sync-button panel so we can check elements in that.
|
|
document.getElementById("sync-button").click();
|
|
});
|
|
|
|
add_task(function* testSyncNeedsVerification() {
|
|
// mock out the "_needsVerification()" function
|
|
let oldNeedsVerification = window.gSyncUI._needsVerification;
|
|
window.gSyncUI._needsVerification = () => true;
|
|
try {
|
|
// a notification for the state change
|
|
yield notifyAndPromiseUIUpdated("weave:service:login:finish");
|
|
checkButtonTooltips("Verify");
|
|
} finally {
|
|
window.gSyncUI._needsVerification = oldNeedsVerification;
|
|
}
|
|
});
|
|
|
|
|
|
add_task(function* testSyncLoginError() {
|
|
checkBroadcasterVisible("sync-syncnow-state");
|
|
|
|
// Pretend we are in a "login failed" error state
|
|
Weave.Status.sync = Weave.LOGIN_FAILED;
|
|
Weave.Status.login = Weave.LOGIN_FAILED_LOGIN_REJECTED;
|
|
yield notifyAndPromiseUIUpdated("weave:ui:sync:error");
|
|
|
|
// But the menu *should* reflect the login error.
|
|
checkBroadcasterVisible("sync-reauth-state");
|
|
// The tooltips for the buttons should also reflect it.
|
|
checkButtonTooltips("Reconnect");
|
|
|
|
// Now pretend we just had a successful login - the error notification should go away.
|
|
Weave.Status.sync = Weave.STATUS_OK;
|
|
Weave.Status.login = Weave.LOGIN_SUCCEEDED;
|
|
yield notifyAndPromiseUIUpdated("weave:service:login:start");
|
|
yield notifyAndPromiseUIUpdated("weave:service:login:finish");
|
|
// The menus should be back to "all good"
|
|
checkBroadcasterVisible("sync-syncnow-state");
|
|
});
|
|
|
|
function checkButtonsStatus(shouldBeActive) {
|
|
for (let eid of [
|
|
"sync-status", // the broadcaster itself.
|
|
"sync-button", // the main sync button which observes the broadcaster
|
|
"PanelUI-fxa-icon", // the sync icon in the fxa footer that observes it.
|
|
]) {
|
|
let elt = document.getElementById(eid);
|
|
if (shouldBeActive) {
|
|
Assert.equal(elt.getAttribute("syncstatus"), "active", `${eid} should be active`);
|
|
} else {
|
|
Assert.ok(!elt.hasAttribute("syncstatus"), `${eid} should have no status attr`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function* testButtonActions(startNotification, endNotification, expectActive = true) {
|
|
checkButtonsStatus(false);
|
|
// pretend a sync is starting.
|
|
yield notifyAndPromiseUIUpdated(startNotification);
|
|
checkButtonsStatus(expectActive);
|
|
// and has stopped
|
|
yield notifyAndPromiseUIUpdated(endNotification);
|
|
checkButtonsStatus(false);
|
|
}
|
|
|
|
function *doTestButtonActivities() {
|
|
// logins do not "activate" the spinner/button as they may block and make
|
|
// the UI look like Sync is never completing.
|
|
yield testButtonActions("weave:service:login:start", "weave:service:login:finish", false);
|
|
yield testButtonActions("weave:service:login:start", "weave:service:login:error", false);
|
|
|
|
// But notifications for Sync itself should activate it.
|
|
yield testButtonActions("weave:service:sync:start", "weave:service:sync:finish");
|
|
yield testButtonActions("weave:service:sync:start", "weave:service:sync:error");
|
|
|
|
// and ensure the counters correctly handle multiple in-flight syncs
|
|
yield notifyAndPromiseUIUpdated("weave:service:sync:start");
|
|
checkButtonsStatus(true);
|
|
// sync stops.
|
|
yield notifyAndPromiseUIUpdated("weave:service:sync:finish");
|
|
// Button should not be active.
|
|
checkButtonsStatus(false);
|
|
}
|
|
|
|
add_task(function* testButtonActivitiesInNavBar() {
|
|
// check the button's functionality while the button is in the NavBar - which
|
|
// it already is.
|
|
yield doTestButtonActivities();
|
|
});
|
|
|
|
add_task(function* testFormatLastSyncDateNow() {
|
|
let now = new Date();
|
|
let nowString = gSyncUI.formatLastSyncDate(now);
|
|
Assert.equal(nowString, "Last sync: " + now.toLocaleDateString(undefined, {weekday: 'long', hour: 'numeric', minute: 'numeric'}));
|
|
});
|
|
|
|
add_task(function* testFormatLastSyncDateMonthAgo() {
|
|
let monthAgo = new Date();
|
|
monthAgo.setMonth(monthAgo.getMonth() - 1);
|
|
let monthAgoString = gSyncUI.formatLastSyncDate(monthAgo);
|
|
Assert.equal(monthAgoString, "Last sync: " + monthAgo.toLocaleDateString(undefined, {month: 'long', day: 'numeric'}));
|
|
});
|
|
|
|
add_task(function* testButtonActivitiesInPanel() {
|
|
// check the button's functionality while the button is in the panel - it's
|
|
// currently in the NavBar - move it to the panel and open it.
|
|
CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL);
|
|
yield PanelUI.show();
|
|
try {
|
|
yield doTestButtonActivities();
|
|
} finally {
|
|
PanelUI.hide();
|
|
}
|
|
});
|