www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit 11e7cef0575143e555e88709808b1be33617447c
parent 455facee95685da4c60939212f29955b257a2427
Author: Adomas Ven <adomas.ven@gmail.com>
Date:   Mon, 27 Jun 2016 19:40:38 +0300

Show hard warning dialog when unlinking or linking to a different account (#1047)

And give option to delete local data when unlinking

This removes the old behavior of merging accounts when syncing with a different username.
Diffstat:
Achrome/content/zotero/hardConfirmationDialog.js | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Achrome/content/zotero/hardConfirmationDialog.xul | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mchrome/content/zotero/preferences/preferences_sync.js | 26+++++++++++++++++++++++---
Mchrome/content/zotero/xpcom/notifier.js | 8++++----
Mchrome/content/zotero/xpcom/sync/syncLocal.js | 106+++++++++++++++++++++++++++++++++----------------------------------------------
Mchrome/content/zotero/xpcom/sync/syncRunner.js | 6+++---
Mchrome/content/zotero/xpcom/utilities_internal.js | 9+++++++++
Mchrome/content/zotero/xpcom/zotero.js | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mchrome/content/zotero/zoteroPane.js | 6+++---
Mchrome/locale/en-US/zotero/zotero.properties | 19++++++++++++-------
Mtest/tests/preferences_syncTest.js | 11+++++++++++
Mtest/tests/syncLocalTest.js | 79+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
12 files changed, 353 insertions(+), 122 deletions(-)

diff --git a/chrome/content/zotero/hardConfirmationDialog.js b/chrome/content/zotero/hardConfirmationDialog.js @@ -0,0 +1,78 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2016 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + http://zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see <http://www.gnu.org/licenses/>. + + ***** END LICENSE BLOCK ***** +*/ + +Zotero.HardConfirmationDialog = { + init: function() { + var label, content; + this.io = window.arguments[0]; + + var vbox = document.getElementById('infoContainer'); + var sep = vbox.firstChild; + for (let text of this.io.text) { + label = document.createElement('label'); + content = document.createTextNode(text); + label.appendChild(content); + vbox.insertBefore(label, sep); + } + if (this.io.checkboxLabel) { + var checkbox = document.getElementById('zotero-hardConfirmationDialog-checkbox'); + checkbox.hidden = false; + checkbox.setAttribute('label', this.io.checkboxLabel); + this.onCheckbox(); + } + if (this.io.confirmationText) { + document.getElementById('zotero-hardConfirmationDialog-textbox').hidden = false; + this.onKeyUp(); + } + + if (this.io.extra1Label) { + document.documentElement.buttons = document.documentElement.buttons + ',extra1'; + document.documentElement.getButton('extra1').label = this.io.extra1Label + } if (this.io.acceptLabel) { + document.documentElement.getButton('accept').label = this.io.acceptLabel + } + + document.documentElement.setAttribute('title', this.io.title); + }, + + onCheckbox: function(event) { + document.documentElement.getButton('accept').disabled = + !document.getElementById('zotero-hardConfirmationDialog-checkbox').checked; + }, + + onKeyUp: function(event) { + document.documentElement.getButton('accept').disabled = + document.getElementById('zotero-hardConfirmationDialog-textbox').value != this.io.confirmationText; + }, + + onAccept: function() { + this.io.accept = true; + }, + + onExtra1: function() { + this.io.extra1 = true; + document.documentElement.cancelDialog(); + } +}; diff --git a/chrome/content/zotero/hardConfirmationDialog.xul b/chrome/content/zotero/hardConfirmationDialog.xul @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<!-- + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2016 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + http://zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see <http://www.gnu.org/licenses/>. + + ***** END LICENSE BLOCK ***** +--> + + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://global/content/commonDialog.css" type="text/css"?> +<?xml-stylesheet href="chrome://global/skin/commonDialog.css" type="text/css"?> + +<!DOCTYPE overlay [ <!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd"> %zoteroDTD; ]> + +<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="" buttons="cancel,accept" + id="zotero-hardConfirmationDialog" + onload="Zotero.HardConfirmationDialog.init(); sizeToContent();" + ondialogaccept="Zotero.HardConfirmationDialog.onAccept();" + ondialogextra1="Zotero.HardConfirmationDialog.onExtra1();"> + + <script src="chrome://zotero/content/include.js"/> + <script src="hardConfirmationDialog.js"/> + + <grid> + <columns> + <column/> + <column flex="1"/> + </columns> + <rows> + <row> + <hbox id="iconContainer" align="start"><image id="info.icon" class="spaced alert-icon"/></hbox> + <vbox id="infoContainer"> + <separator class="thin"/> + + <checkbox id="zotero-hardConfirmationDialog-checkbox" hidden="true" oncommand="Zotero.HardConfirmationDialog.onCheckbox(event)"/> + <textbox id="zotero-hardConfirmationDialog-textbox" hidden="true" onkeyup="Zotero.HardConfirmationDialog.onKeyUp(event)"/> + </vbox> + </row> + </rows> + </grid> + +</dialog> diff --git a/chrome/content/zotero/preferences/preferences_sync.js b/chrome/content/zotero/preferences/preferences_sync.js @@ -25,6 +25,7 @@ "use strict"; Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/osfile.jsm"); Zotero_Preferences.Sync = { init: Zotero.Promise.coroutine(function* () { @@ -100,6 +101,7 @@ Zotero_Preferences.Sync = { if (event.keyCode == 13) { Zotero_Preferences.Sync.linkAccount(event); + event.preventDefault(); } }, @@ -165,11 +167,29 @@ Zotero_Preferences.Sync = { unlinkAccount: Zotero.Promise.coroutine(function* (showAlert=true) { if (showAlert) { - if (!Services.prompt.confirm( + var check = {value: false}; + var ps = Services.prompt; + var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) + + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL); + var index = ps.confirmEx( null, Zotero.getString('general.warning'), - Zotero.getString('sync.unlinkWarning', Zotero.clientName) - )) { + Zotero.getString('account.unlinkWarning', Zotero.clientName), + buttonFlags, + Zotero.getString('account.unlinkWarning.button'), null, null, + Zotero.getString('account.unlinkWarning.removeData', Zotero.clientName), + check + ); + if (index == 0) { + if (check.value) { + var resetDataDirFile = OS.Path.join(Zotero.getZoteroDirectory().path, 'reset-data-directory'); + yield Zotero.File.putContentsAsync(resetDataDirFile, ''); + + yield Zotero.Sync.Runner.deleteAPIKey(); + Zotero.Prefs.clear('sync.server.username'); + return Zotero.Utilities.Internal.quitZotero(true); + } + } else { return; } } diff --git a/chrome/content/zotero/xpcom/notifier.js b/chrome/content/zotero/xpcom/notifier.js @@ -37,10 +37,10 @@ Zotero.Notifier = new function(){ /** - * @param ref {Object} - signature {notify: function(event, type, ids, extraData) {}} - * @param types {Array} - a list of types of events observer should be triggered on - * @param id {String} - an id of the observer used in debug output - * @param priority {Integer} - lower numbers correspond to higher priority of observer execution + * @param {Object} [ref] signature {notify: function(event, type, ids, extraData) {}} + * @param {Array} [types] a list of types of events observer should be triggered on + * @param {String} [id] an id of the observer used in debug output + * @param {Integer} [priority] lower numbers correspond to higher priority of observer execution * @returns {string} */ this.registerObserver = function (ref, types, id, priority) { diff --git a/chrome/content/zotero/xpcom/sync/syncLocal.js b/chrome/content/zotero/xpcom/sync/syncLocal.js @@ -88,12 +88,12 @@ Zotero.Sync.Data.Local = { /** * Make sure we're syncing with the same account we used last time, and prompt if not. - * If user accepts, change the current user, delete existing groups, and update relation - * URIs to point to the new user's library. + * If user accepts, change the current user and initiate deletion of all user data after a + * restart. * * @param {Window|null} * @param {Integer} userID - New userID - * @param {Integer} libraryID - New libraryID + * @param {Integer} username - New username * @return {Boolean} - True to continue, false to cancel */ checkUser: Zotero.Promise.coroutine(function* (win, userID, username) { @@ -101,73 +101,55 @@ Zotero.Sync.Data.Local = { var lastUsername = Zotero.Users.getCurrentUsername(); if (lastUserID && lastUserID != userID) { - var groups = Zotero.Groups.getAll(); - - var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService); - var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) - + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL) - + (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_IS_STRING) - + ps.BUTTON_POS_1_DEFAULT - + ps.BUTTON_DELAY_ENABLE; - - var msg = Zotero.getString( - 'sync.lastSyncWithDifferentAccount', [ZOTERO_CONFIG.CLIENT_NAME, lastUsername, username] - ); - var syncButtonText = Zotero.getString('sync.sync'); - - msg += " " + Zotero.getString('sync.localDataWillBeCombined', [username, ZOTERO_CONFIG.DOMAIN_NAME]); - // If there are local groups belonging to the previous user, - // we need to remove them - if (groups.length) { - msg += " " + Zotero.getString('sync.localGroupsWillBeRemoved1'); - var syncButtonText = Zotero.getString('sync.removeGroupsAndSync'); + var io = { + title: Zotero.getString('general.warning'), + text: [Zotero.getString('account.lastSyncWithDifferentAccount', [ZOTERO_CONFIG.CLIENT_NAME, lastUsername, username])], + checkboxLabel: Zotero.getString('account.confirmDelete', lastUsername), + acceptLabel: Zotero.getString('account.confirmDelete.button') + }; + win.openDialog("chrome://zotero/content/hardConfirmationDialog.xul", "", + "chrome, dialog, modal, centerscreen", io); + + var accept = false; + if (io.accept) { + var resetDataDirFile = OS.Path.join(Zotero.getZoteroDirectory().path, 'reset-data-directory'); + yield Zotero.File.putContentsAsync(resetDataDirFile, ''); + + Zotero.Utilities.Internal.quitZotero(true); + accept = true; } - msg += "\n\n" + Zotero.getString('sync.avoidCombiningData', lastUsername); - - var index = ps.confirmEx( - win, - Zotero.getString('general.warning'), - msg, - buttonFlags, - syncButtonText, - null, - Zotero.getString('sync.openSyncPreferences'), - null, {} - ); - - if (index > 0) { - if (index == 2) { - win.ZoteroPane.openPreferences('zotero-prefpane-sync'); - } - return false; + // else if (io.extra1) { + // if (Zotero.forceNewDataDirectory(win)) { + // var ps = Services.prompt; + // ps.alert(null, + // Zotero.getString('general.restartRequired'), + // Zotero.getString('general.restartRequiredForChange', Zotero.appName) + // ); + // Zotero.Utilities.Internal.quitZotero(true); + // accept = true; + // } + // } + if (accept) { + Zotero.Prefs.clear('sync.storage.downloadMode.groups'); + Zotero.Prefs.clear('sync.storage.groups.enabled'); + Zotero.Prefs.clear('sync.storage.downloadMode.personal'); + Zotero.Prefs.clear('sync.storage.username'); + Zotero.Prefs.clear('sync.storage.url'); + Zotero.Prefs.clear('sync.storage.scheme'); + Zotero.Prefs.clear('sync.storage.protocol'); + Zotero.Prefs.clear('sync.storage.enabled'); } + return accept; } yield Zotero.DB.executeTransaction(function* () { - if (lastUserID != userID) { - if (lastUserID) { - // Delete all local groups if changing users - for (let group of groups) { - yield group.erase(); - } - - // Update relations pointing to the old library to point to this one - yield Zotero.Relations.updateUser(userID); - } - // Replace local user key with libraryID, in case duplicates were - // merged before the first sync - else { - yield Zotero.Relations.updateUser(userID); - } - - yield Zotero.Users.setCurrentUserID(userID); - } - if (lastUsername != username) { yield Zotero.Users.setCurrentUsername(username); + } + if (!lastUserID) { + yield Zotero.Users.setCurrentUserID(userID); } - }) + }); return true; }), diff --git a/chrome/content/zotero/xpcom/sync/syncRunner.js b/chrome/content/zotero/xpcom/sync/syncRunner.js @@ -255,13 +255,13 @@ Zotero.Sync.Runner_Module = function (options = {}) { if (!userID) { let hasItems = yield library.hasItems(); - if (!hasItems && feeds.length <= 0) { + if (!hasItems && feeds.length <= 0 && !Zotero.resetDataDir) { let ps = Services.prompt; let index = ps.confirmEx( null, Zotero.getString('general.warning'), - Zotero.getString('sync.warning.emptyLibrary', [keyInfo.username, Zotero.clientName]) + "\n\n" - + Zotero.getString('sync.warning.existingDataElsewhere', Zotero.clientName), + Zotero.getString('account.warning.emptyLibrary', [keyInfo.username, Zotero.clientName]) + "\n\n" + + Zotero.getString('account.warning.existingDataElsewhere', Zotero.clientName), (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) + (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) + (ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING), diff --git a/chrome/content/zotero/xpcom/utilities_internal.js b/chrome/content/zotero/xpcom/utilities_internal.js @@ -1052,6 +1052,15 @@ Zotero.Utilities.Internal = { } elem.appendChild(menu); return menu; + }, + + /** + * Quits Zotero, optionally restarting. + * @param {Boolean} [restart=false] + */ + quitZotero: function(restart=false) { + var startup = Services.startup; + startup.quit(startup.eAttemptQuit | (restart ? startup.eRestart : 0) ); } } diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js @@ -479,27 +479,40 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); var _initFull = Zotero.Promise.coroutine(function* () { Zotero.VersionHeader.init(); - // Check for DB restore + // Check for data reset/restore var dataDir = Zotero.getZoteroDirectory(); - var restoreFile = dataDir.clone(); - restoreFile.append('restore-from-server'); - if (restoreFile.exists()) { + var restoreFile = OS.Path.join(dataDir.path, 'restore-from-server'); + var resetDataDirFile = OS.Path.join(dataDir.path, 'reset-data-directory'); + + var result = yield Zotero.Promise.all([OS.File.exists(restoreFile), OS.File.exists(resetDataDirFile)]); + if (result.some(r => r)) { + [Zotero.restoreFromServer, Zotero.resetDataDir] = result; try { // TODO: better error handling // TODO: prompt for location // TODO: Back up database - restoreFile.remove(false); - var dbfile = Zotero.getZoteroDatabase(); - dbfile.remove(false); + var dbfile = Zotero.getZoteroDatabase().path; + yield OS.File.remove(dbfile, {ignoreAbsent: true}); + + if (Zotero.restoreFromServer) { + yield OS.File.remove(restoreFile); + Zotero.restoreFromServer = true; + } else if (Zotero.resetDataDir) { + Zotero.initAutoSync = true; + var storageDir = OS.Path.join(dataDir.path, 'storage'); + yield Zotero.Promise.all([ + OS.File.removeDir(storageDir, {ignoreAbsent: true}), + OS.File.remove(resetDataDirFile) + ]); + } // Recreate database with no quick start guide Zotero.Schema.skipDefaultData = true; yield Zotero.Schema.updateSchema(); - Zotero.restoreFromServer = true; } catch (e) { // Restore from backup? @@ -1190,6 +1203,42 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); return useProfileDir ? true : file; } + + + this.forceNewDataDirectory = function(win) { + if (!win) { + win = Services.wm.getMostRecentWindow('navigator:browser'); + } + var ps = Services.prompt; + + var nsIFilePicker = Components.interfaces.nsIFilePicker; + while (true) { + var fp = Components.classes["@mozilla.org/filepicker;1"] + .createInstance(nsIFilePicker); + fp.init(win, Zotero.getString('dataDir.selectNewDir', Zotero.clientName), nsIFilePicker.modeGetFolder); + fp.displayDirectory = Zotero.getZoteroDirectory(); + fp.appendFilters(nsIFilePicker.filterAll); + if (fp.show() == nsIFilePicker.returnOK) { + var file = fp.file; + + if (file.directoryEntries.hasMoreElements()) { + ps.alert(null, + Zotero.getString('dataDir.mustSelectEmpty.title'), + Zotero.getString('dataDir.mustSelectEmpty.text') + ); + continue; + } + + // Set new data directory + Zotero.Prefs.set('dataDir', file.persistentDescriptor); + Zotero.Prefs.set('lastDataDir', file.path); + Zotero.Prefs.set('useDataDir', true); + return file; + } else { + return false; + } + } + }; this.warnOnUnsafeDataDir = true; diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js @@ -408,8 +408,8 @@ var ZoteroPane = new function() var d2 = new Date(); Zotero.debug("Purged data tables in " + (d2 - d) + " ms"); - // Auto-sync on pane open - if (Zotero.Prefs.get('sync.autoSync')) { + // Auto-sync on pane open or if new account + if (Zotero.Prefs.get('sync.autoSync') || Zotero.initAutoSync) { yield Zotero.proxyAuthComplete.delay(1000); if (!Zotero.Sync.Runner.enabled) { @@ -424,7 +424,7 @@ var ZoteroPane = new function() else { Zotero.Sync.Runner.sync({ background: true - }); + }).then(() => Zotero.initAutoSync = false); } } diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties @@ -113,13 +113,17 @@ dataDir.notFound = The Zotero data directory could not be found. dataDir.previousDir = Previous directory: dataDir.useProfileDir = Use %S profile directory dataDir.selectDir = Select a Zotero data directory +dataDir.selectNewDir = Select a new %S data directory dataDir.changeDataDirectory = Change Data Directory… +dataDir.chooseNewDataDirectory = Choose New Data Directory… dataDir.unsafeLocation.selected.dropbox = Choosing a data directory within Dropbox may corrupt your database. dataDir.unsafeLocation.selected.useAnyway = Use this directory anyway? dataDir.unsafeLocation.existing.dropbox = Your Zotero data directory is within Dropbox, which may lead to data corruption. dataDir.unsafeLocation.existing.chooseDifferent = Would you like to choose a different location now? dataDir.selectedDirNonEmpty.title = Directory Not Empty dataDir.selectedDirNonEmpty.text = The directory you selected is not empty and does not appear to be a Zotero data directory.\n\nCreate Zotero files in this directory anyway? +dataDir.mustSelectEmpty.title = Directory Not Empty +dataDir.mustSelectEmpty.text = The directory you selected is not empty. You must select an empty directory to continue. dataDir.selectedDirEmpty.title = Directory Empty dataDir.selectedDirEmpty.text = The directory you selected is empty. To move an existing Zotero data directory, you will need to manually move files from the existing data directory to the new location after %1$S has closed. dataDir.selectedDirEmpty.useNewDir = Use the new directory? @@ -846,13 +850,14 @@ sync.error.emptyResponseServer = Empty response from server. sync.error.invalidCharsFilename = The filename '%S' contains invalid characters.\n\nRename the file and try again. If you rename the file via the OS, you will need to relink it in Zotero. sync.error.apiKeyInvalid = %S could not authenticate your account. Please re-enter your account details. -sync.lastSyncWithDifferentAccount = This Zotero database was last synced with a different %1$S account (‘%2$S’) from the current one (‘%3$S’). -sync.localDataWillBeCombined = If you continue, local data will be combined with data from the ‘%1$S’ account on %2$S. -sync.localGroupsWillBeRemoved1 = Local groups, including any with changed items, will also be removed from this computer. -sync.avoidCombiningData = To avoid combining data, revert to the ‘%S’ account or use the Reset options in the Sync pane of the Zotero preferences. -sync.unlinkWarning = Are you sure you want to unlink this account?\n\n%S will no longer sync your data, but your data will remain locally. -sync.warning.emptyLibrary = You are about to sync the ‘%1$S’ account to an empty %2$S database. This could happen if you removed your previous database or if the location of your %2$S data directory changed. -sync.warning.existingDataElsewhere = If your %S data exists elsewhere on your computer, you should move it to your current data directory or change your data directory to point to the existing data. +account.unlinkWarning = Unlinking your account will prevent %S from syncing your data. +account.unlinkWarning.removeData = Remove my %S data from this computer +account.unlinkWarning.button = Unlink Account +account.warning.emptyLibrary = You are about to sync the ‘%1$S’ account to an empty %2$S database. This could happen if you removed your previous database or if the location of your %2$S data directory changed. +account.warning.existingDataElsewhere = If your %S data exists elsewhere on your computer, you should move it to your current data directory or change your data directory to point to the existing data. +account.lastSyncWithDifferentAccount = This %1$S database was last synced with a different account (‘%2$S’) from the current one (‘%3$S’). If you continue, data associated with the ‘%2$S’ account will be removed from this computer. +account.confirmDelete = Remove data associated with the ‘%S’ account +account.confirmDelete.button = Switch Accounts sync.conflict.autoChange.alert = One or more locally deleted Zotero %S have been modified remotely since the last sync. sync.conflict.autoChange.log = A Zotero %S has changed both locally and remotely since the last sync: diff --git a/test/tests/preferences_syncTest.js b/test/tests/preferences_syncTest.js @@ -95,6 +95,17 @@ describe("Sync Preferences", function () { assert.equal(Zotero.Sync.Data.Local.getAPIKey(), ""); assert.equal(doc.getElementById('sync-authorized').getAttribute('hidden'), 'true'); }); + + it("should not unlink on pressing cancel", function* () { + getAPIKeyFromCredentialsStub.resolves(apiResponse); + yield setCredentials("Username", "correctPassword"); + + waitForDialog(null, 'cancel'); + + yield win.Zotero_Preferences.Sync.unlinkAccount(); + assert.equal(Zotero.Sync.Data.Local.getAPIKey(), apiKey); + assert.equal(doc.getElementById('sync-unauthorized').getAttribute('hidden'), 'true'); + }); }) }) diff --git a/test/tests/syncLocalTest.js b/test/tests/syncLocalTest.js @@ -22,7 +22,22 @@ describe("Zotero.Sync.Data.Local", function() { describe("#checkUser()", function () { - it("should prompt for user update and perform on accept", function* () { + var resetDataDirFile = OS.Path.join(Zotero.getZoteroDirectory().path, 'reset-data-directory'); + + before(function() { + sinon.stub(Zotero.Utilities.Internal, 'quitZotero'); + }); + + beforeEach(function* () { + yield OS.File.remove(resetDataDirFile, {ignoreAbsent: true}); + Zotero.Utilities.Internal.quitZotero.reset(); + }); + + after(function() { + Zotero.Utilities.Internal.quitZotero.restore(); + }); + + it("should prompt for data reset and create a temp 'reset-data-directory' file on accept", function* (){ yield Zotero.Users.setCurrentUserID(1); yield Zotero.Users.setCurrentUsername("A"); @@ -30,54 +45,54 @@ describe("Zotero.Sync.Data.Local", function() { waitForDialog(function (dialog) { var text = dialog.document.documentElement.textContent; var matches = text.match(/‘[^’]*’/g); - assert.equal(matches.length, 4); + assert.equal(matches.length, 3); assert.equal(matches[0], "‘A’"); assert.equal(matches[1], "‘B’"); - assert.equal(matches[2], "‘B’"); - assert.equal(matches[3], "‘A’"); + assert.equal(matches[2], "‘A’"); + + dialog.document.getElementById('zotero-hardConfirmationDialog-checkbox').checked = true; + dialog.document.getElementById('zotero-hardConfirmationDialog-checkbox') + .dispatchEvent(new Event('command')); + handled = true; - }); - var cont = yield Zotero.Sync.Data.Local.checkUser(null, 2, "B"); + }, 'accept', 'chrome://zotero/content/hardConfirmationDialog.xul'); + var cont = yield Zotero.Sync.Data.Local.checkUser(window, 2, "B"); + var resetDataDirFileExists = yield OS.File.exists(resetDataDirFile); assert.isTrue(handled); assert.isTrue(cont); - - assert.equal(Zotero.Users.getCurrentUserID(), 2); - assert.equal(Zotero.Users.getCurrentUsername(), "B"); - }) + assert.isTrue(resetDataDirFileExists); + }); - it("should prompt for user update and cancel", function* () { + it("should prompt for data reset and cancel", function* () { yield Zotero.Users.setCurrentUserID(1); yield Zotero.Users.setCurrentUsername("A"); - waitForDialog(false, 'cancel'); - var cont = yield Zotero.Sync.Data.Local.checkUser(null, 2, "B"); + waitForDialog(false, 'cancel', 'chrome://zotero/content/hardConfirmationDialog.xul'); + var cont = yield Zotero.Sync.Data.Local.checkUser(window, 2, "B"); + var resetDataDirFileExists = yield OS.File.exists(resetDataDirFile); assert.isFalse(cont); + assert.isFalse(resetDataDirFileExists); assert.equal(Zotero.Users.getCurrentUserID(), 1); assert.equal(Zotero.Users.getCurrentUsername(), "A"); - }) + }); - it("should update local relations when syncing for the first time", function* () { - yield resetDB({ - thisArg: this, - skipBundledFiles: true - }); - - var item1 = yield createDataObject('item'); - var item2 = yield createDataObject( - 'item', { libraryID: Zotero.Libraries.publicationsLibraryID } - ); - - yield item1.addLinkedItem(item2); + // extra1 functionality not used at the moment + it.skip("should prompt for data reset and allow to choose a new data directory", function* (){ + sinon.stub(Zotero, 'forceNewDataDirectory').returns(true); + yield Zotero.Users.setCurrentUserID(1); + yield Zotero.Users.setCurrentUsername("A"); - var cont = yield Zotero.Sync.Data.Local.checkUser(null, 1, "A"); + waitForDialog(null, 'extra1', 'chrome://zotero/content/hardConfirmationDialog.xul'); + waitForDialog(); + var cont = yield Zotero.Sync.Data.Local.checkUser(window, 2, "B"); + var resetDataDirFileExists = yield OS.File.exists(resetDataDirFile); assert.isTrue(cont); + assert.isTrue(Zotero.forceNewDataDirectory.called); + assert.isFalse(resetDataDirFileExists); - var json = item1.toJSON(); - var uri = json.relations[Zotero.Relations.linkedObjectPredicate][0]; - assert.notInclude(uri, 'users/local'); - assert.include(uri, 'users/1/publications'); - }) + Zotero.forceNewDataDirectory.restore(); + }); });