mirror of
https://github.com/zotero/zotero.git
synced 2026-09-05 08:06:16 +00:00
Fetch emails from /keys response and login session result, persist them in the local database, and display them in the sync settings for both logged-in and logged-out-but-linked states. Also unify the separate logged-out-linked and logged-in containers into a single layout that toggles elements based on login state. Requires dataserver and stream-server changes
204 lines
6.9 KiB
JavaScript
204 lines
6.9 KiB
JavaScript
describe("Sync Preferences", function () {
|
|
var win, doc;
|
|
before(function* () {
|
|
// Load prefs with sync pane
|
|
win = yield loadWindow("chrome://zotero/content/preferences/preferences.xhtml", {
|
|
pane: 'zotero-prefpane-sync'
|
|
});
|
|
doc = win.document;
|
|
yield win.Zotero_Preferences.waitForFirstPaneLoad();
|
|
});
|
|
|
|
after(function () {
|
|
win.close();
|
|
});
|
|
|
|
describe("Settings", function () {
|
|
describe("Data Syncing", function () {
|
|
var createLoginSessionStub, checkLoginSessionStub, deleteAPIKey, launchURLStub,
|
|
streamerSubscribeStub, streamerUnsubscribeStub, indicatorElem, apiKey;
|
|
|
|
var performLogin = async function (username) {
|
|
apiKey = Zotero.Utilities.randomString(24);
|
|
|
|
createLoginSessionStub.resolves({
|
|
sessionToken: 'test-session-token',
|
|
loginURL: 'https://www.zotero.org/authorize?token=test-session-token'
|
|
});
|
|
checkLoginSessionStub.resolves({
|
|
status: 'completed',
|
|
apiKey,
|
|
userID: 1,
|
|
username
|
|
});
|
|
|
|
await win.Zotero_Preferences.Sync.linkAccount();
|
|
};
|
|
|
|
before(function* () {
|
|
createLoginSessionStub = sinon.stub(
|
|
Zotero.Sync.APIClient.prototype, 'createLoginSession');
|
|
checkLoginSessionStub = sinon.stub(
|
|
Zotero.Sync.APIClient.prototype, 'checkLoginSession');
|
|
deleteAPIKey = sinon.stub(Zotero.Sync.APIClient.prototype, 'deleteAPIKey').resolves();
|
|
launchURLStub = sinon.stub(Zotero, 'launchURL');
|
|
streamerSubscribeStub = sinon.stub(Zotero.Streamer, 'subscribe').returns(false);
|
|
streamerUnsubscribeStub = sinon.stub(Zotero.Streamer, 'unsubscribe');
|
|
indicatorElem = doc.querySelector('.account-login-status-indicator');
|
|
sinon.stub(Zotero, 'alert');
|
|
// Speed up polling for tests
|
|
win.Zotero_Preferences.Sync._pollInterval = 10;
|
|
});
|
|
|
|
beforeEach(function* () {
|
|
yield win.Zotero_Preferences.Sync.unlinkAccount(false);
|
|
deleteAPIKey.resetHistory();
|
|
createLoginSessionStub.resetHistory();
|
|
checkLoginSessionStub.resetHistory();
|
|
launchURLStub.resetHistory();
|
|
streamerSubscribeStub.resetHistory();
|
|
streamerUnsubscribeStub.resetHistory();
|
|
Zotero.alert.reset();
|
|
});
|
|
|
|
after(function () {
|
|
Zotero.HTTP.mock = null;
|
|
Zotero.alert.restore();
|
|
createLoginSessionStub.restore();
|
|
checkLoginSessionStub.restore();
|
|
deleteAPIKey.restore();
|
|
launchURLStub.restore();
|
|
streamerSubscribeStub.restore();
|
|
streamerUnsubscribeStub.restore();
|
|
win.Zotero_Preferences.Sync._pollInterval = 3000;
|
|
});
|
|
|
|
it("should set API key and display full controls after successful login", async function () {
|
|
await performLogin("Username");
|
|
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), apiKey);
|
|
assert.equal(doc.getElementById('sync-unauthorized').getAttribute('hidden'), 'true');
|
|
assert.isTrue(launchURLStub.calledOnce);
|
|
});
|
|
|
|
|
|
it("should show error when login session expires", async function () {
|
|
createLoginSessionStub.resolves({
|
|
sessionToken: 'test-session-token',
|
|
loginURL: 'https://www.zotero.org/authorize?token=test-session-token'
|
|
});
|
|
let expiredError = new Error("Login session expired");
|
|
expiredError.expired = true;
|
|
checkLoginSessionStub.rejects(expiredError);
|
|
|
|
await win.Zotero_Preferences.Sync.linkAccount();
|
|
|
|
assert.isTrue(Zotero.alert.called);
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), "");
|
|
assert.equal(doc.querySelector('.sync-settings').hidden, true);
|
|
});
|
|
|
|
|
|
it("should reset UI when login session is cancelled on server", async function () {
|
|
createLoginSessionStub.resolves({
|
|
sessionToken: 'test-session-token',
|
|
loginURL: 'https://www.zotero.org/authorize?token=test-session-token'
|
|
});
|
|
checkLoginSessionStub.resolves({
|
|
status: 'cancelled'
|
|
});
|
|
|
|
await win.Zotero_Preferences.Sync.linkAccount();
|
|
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), "");
|
|
assert.equal(doc.querySelector('.account-login-default').hidden, false);
|
|
assert.equal(doc.querySelector('.account-login-pending').hidden, true);
|
|
});
|
|
|
|
|
|
it("should delete API key and display auth form when 'Unlink Account' clicked", async function () {
|
|
await performLogin("Username");
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), apiKey);
|
|
|
|
await win.Zotero_Preferences.Sync.unlinkAccount(false);
|
|
|
|
assert.isTrue(deleteAPIKey.called);
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), "");
|
|
assert.equal(doc.querySelector('.sync-settings').hidden, true);
|
|
});
|
|
|
|
it("should reset the storage controller when unlinking", async function () {
|
|
await performLogin("Username");
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), apiKey);
|
|
|
|
let options = {
|
|
apiClient: Zotero.Sync.Runner.getAPIClient({ apiKey })
|
|
};
|
|
let controller = Zotero.Sync.Runner.getStorageController('zfs', options);
|
|
let apiKey1 = controller.apiClient.apiKey;
|
|
|
|
await win.Zotero_Preferences.Sync.unlinkAccount(false);
|
|
await performLogin("Username");
|
|
|
|
options = {
|
|
apiClient: Zotero.Sync.Runner.getAPIClient({ apiKey })
|
|
};
|
|
controller = Zotero.Sync.Runner.getStorageController('zfs', options);
|
|
assert.notEqual(controller.apiClient.apiKey, apiKey1);
|
|
});
|
|
|
|
it("should not unlink on pressing cancel", async function () {
|
|
await performLogin("Username");
|
|
|
|
waitForDialog(null, 'cancel');
|
|
|
|
await win.Zotero_Preferences.Sync.unlinkAccount();
|
|
assert.equal(await Zotero.Sync.Data.Local.getAPIKey(), apiKey);
|
|
assert.equal(doc.getElementById('sync-unauthorized').getAttribute('hidden'), 'true');
|
|
});
|
|
|
|
it("should clear sync errors from the toolbar after logging in", async function () {
|
|
let win = await loadZoteroPane();
|
|
|
|
let syncError = win.document.getElementById('zotero-tb-sync-error');
|
|
|
|
Zotero.Sync.Runner.updateIcons(new Error("a sync error"));
|
|
assert.isFalse(syncError.hidden);
|
|
|
|
await performLogin("Username");
|
|
assert.isTrue(syncError.hidden);
|
|
|
|
win.close();
|
|
});
|
|
|
|
it("should cancel login and reset UI when cancelLogin is called", async function () {
|
|
let cancelLoginSessionStub = sinon.stub(
|
|
Zotero.Sync.APIClient.prototype, 'cancelLoginSession').resolves();
|
|
|
|
createLoginSessionStub.resolves({
|
|
sessionToken: 'test-session-token',
|
|
loginURL: 'https://www.zotero.org/authorize?token=test-session-token'
|
|
});
|
|
// Return "pending" so the poll loop keeps iterating
|
|
checkLoginSessionStub.resolves({ status: 'pending' });
|
|
|
|
// Start login but don't await -- it will keep polling
|
|
let loginPromise = win.Zotero_Preferences.Sync.linkAccount();
|
|
|
|
// Wait for the poll loop to start
|
|
await Zotero.Promise.delay(50);
|
|
|
|
win.Zotero_Preferences.Sync.cancelLogin();
|
|
|
|
// Wait for the login promise to resolve after cancellation
|
|
await loginPromise;
|
|
|
|
assert.equal(doc.querySelector('.account-login-default').hidden, false);
|
|
assert.equal(doc.querySelector('.account-login-pending').hidden, true);
|
|
assert.isTrue(cancelLoginSessionStub.calledWith('test-session-token'));
|
|
|
|
cancelLoginSessionStub.restore();
|
|
});
|
|
});
|
|
});
|
|
});
|