Close #931, [Async DB] Update long tag fixer
This commit is contained in:
parent
e2cbfbd0fe
commit
e7d27ee0f3
chrome
content/zotero
locale/en-US/zotero
test/tests
|
@ -132,7 +132,7 @@ var Zotero_Long_Tag_Fixer = new function () {
|
||||||
|
|
||||||
this.updateEditLength = function (len) {
|
this.updateEditLength = function (len) {
|
||||||
document.getElementById('zotero-new-tag-character-count').value = len;
|
document.getElementById('zotero-new-tag-character-count').value = len;
|
||||||
var invalid = len == 0 || len > 255;
|
var invalid = len == 0 || len > Zotero.Tags.MAX_SYNC_LENGTH;
|
||||||
document.getElementById('zotero-new-tag-characters').setAttribute('invalid', invalid);
|
document.getElementById('zotero-new-tag-characters').setAttribute('invalid', invalid);
|
||||||
document.getElementById('zotero-long-tag-fixer').getButton('accept').disabled = invalid;
|
document.getElementById('zotero-long-tag-fixer').getButton('accept').disabled = invalid;
|
||||||
}
|
}
|
||||||
|
@ -146,11 +146,9 @@ var Zotero_Long_Tag_Fixer = new function () {
|
||||||
this.save = function () {
|
this.save = function () {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var index = document.getElementById('zotero-new-tag-actions').selectedIndex;
|
var result = {};
|
||||||
|
|
||||||
// Search for all matching tags across all libraries
|
var index = document.getElementById('zotero-new-tag-actions').selectedIndex;
|
||||||
var sql = "SELECT tagID FROM tags WHERE name=?";
|
|
||||||
var oldTagIDs = Zotero.DB.columnQuery(sql, _oldTag);
|
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
// Split
|
// Split
|
||||||
|
@ -166,48 +164,23 @@ var Zotero_Long_Tag_Fixer = new function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Zotero.DB.beginTransaction();
|
result.op = 'split';
|
||||||
|
result.tags = newTags;
|
||||||
// Add new tags to all items linked to each matching old tag
|
|
||||||
for (var i=0; i<oldTagIDs.length; i++) {
|
|
||||||
var tag = Zotero.Tags.get(oldTagIDs[i]);
|
|
||||||
var items = tag.getLinkedItems();
|
|
||||||
if (items) {
|
|
||||||
for (var j=0; j<items.length; j++) {
|
|
||||||
items[j].addTags(newTags, tag.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove old tags
|
|
||||||
// TODO: Update
|
|
||||||
Zotero.Tags.erase(oldTagIDs);
|
|
||||||
Zotero.Tags.purge();
|
|
||||||
Zotero.DB.commitTransaction();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Edit
|
// Edit
|
||||||
case 1:
|
case 1:
|
||||||
var value = document.getElementById('zotero-new-tag-editor').value;
|
result.op = 'edit';
|
||||||
Zotero.DB.beginTransaction();
|
result.tag = document.getElementById('zotero-new-tag-editor').value;
|
||||||
for (var i=0; i<oldTagIDs.length; i++) {
|
|
||||||
var tag = Zotero.Tags.get(oldTagIDs[i]);
|
|
||||||
tag.name = value;
|
|
||||||
tag.save();
|
|
||||||
}
|
|
||||||
Zotero.DB.commitTransaction();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
case 2:
|
case 2:
|
||||||
Zotero.DB.beginTransaction();
|
result.op = 'delete';
|
||||||
Zotero.Tags.erase(oldTagIDs);
|
|
||||||
Zotero.Tags.purge();
|
|
||||||
Zotero.DB.commitTransaction();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dataOut.result = true;
|
_dataOut.result = result;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
*/
|
*/
|
||||||
Zotero.Tags = new function() {
|
Zotero.Tags = new function() {
|
||||||
this.MAX_COLORED_TAGS = 6;
|
this.MAX_COLORED_TAGS = 6;
|
||||||
|
this.MAX_SYNC_LENGTH = 255;
|
||||||
|
|
||||||
var _initialized = false;
|
var _initialized = false;
|
||||||
var _tagsByID = new Map();
|
var _tagsByID = new Map();
|
||||||
|
@ -123,6 +124,15 @@ Zotero.Tags = new function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.getLongTagsInLibrary = Zotero.Promise.coroutine(function* (libraryID) {
|
||||||
|
var sql = "SELECT DISTINCT tagID FROM tags "
|
||||||
|
+ "JOIN itemTags USING (tagID) "
|
||||||
|
+ "JOIN items USING (itemID) "
|
||||||
|
+ "WHERE libraryID=? AND LENGTH(name)>?"
|
||||||
|
return yield Zotero.DB.columnQueryAsync(sql, [libraryID, this.MAX_SYNC_LENGTH]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tags in library
|
* Get all tags in library
|
||||||
*
|
*
|
||||||
|
|
|
@ -339,36 +339,6 @@ Zotero.Sync.Server = new function () {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'TAG_TOO_LONG':
|
|
||||||
if (!Zotero.Sync.Runner.background) {
|
|
||||||
var tag = xmlhttp.responseXML.firstChild.getElementsByTagName('tag');
|
|
||||||
if (tag.length) {
|
|
||||||
var tag = tag[0].firstChild.nodeValue;
|
|
||||||
setTimeout(function () {
|
|
||||||
var callback = function () {
|
|
||||||
var sql = "SELECT DISTINCT name FROM tags WHERE LENGTH(name)>255 LIMIT 1";
|
|
||||||
var tag = Zotero.DB.valueQuery(sql);
|
|
||||||
if (tag) {
|
|
||||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
||||||
.getService(Components.interfaces.nsIWindowMediator);
|
|
||||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
|
||||||
var dataOut = { result: null };
|
|
||||||
lastWin.openDialog('chrome://zotero/content/longTagFixer.xul', '', 'chrome,modal,centerscreen', tag, dataOut);
|
|
||||||
if (dataOut.result) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Zotero.Sync.Runner.sync();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
callback();
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// We can't reproduce it, but we can fix it
|
// We can't reproduce it, but we can fix it
|
||||||
case 'WRONG_LIBRARY_TAG_ITEM':
|
case 'WRONG_LIBRARY_TAG_ITEM':
|
||||||
var background = Zotero.Sync.Runner.background;
|
var background = Zotero.Sync.Runner.background;
|
||||||
|
|
|
@ -905,10 +905,13 @@ Zotero.Sync.Data.Engine.prototype._uploadObjects = Zotero.Promise.coroutine(func
|
||||||
|
|
||||||
// Handle failed objects
|
// Handle failed objects
|
||||||
for (let index in json.results.failed) {
|
for (let index in json.results.failed) {
|
||||||
let { code, message } = json.results.failed[index];
|
let { code, message, data } = json.results.failed[index];
|
||||||
let e = new Error(message);
|
let e = new Error(message);
|
||||||
e.name = "ZoteroUploadObjectError";
|
e.name = "ZoteroObjectUploadError";
|
||||||
e.code = code;
|
e.code = code;
|
||||||
|
if (data) {
|
||||||
|
e.data = data;
|
||||||
|
}
|
||||||
Zotero.logError("Error for " + objectType + " " + batch[index].key + " in "
|
Zotero.logError("Error for " + objectType + " " + batch[index].key + " in "
|
||||||
+ this.library.name + ":\n\n" + e);
|
+ this.library.name + ":\n\n" + e);
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
|
|
||||||
|
|
||||||
this.getAPIClient = function (options = {}) {
|
this.getAPIClient = function (options = {}) {
|
||||||
|
|
||||||
return new Zotero.Sync.APIClient({
|
return new Zotero.Sync.APIClient({
|
||||||
baseURL: this.baseURL,
|
baseURL: this.baseURL,
|
||||||
apiVersion: this.apiVersion,
|
apiVersion: this.apiVersion,
|
||||||
|
@ -141,7 +140,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
|
|
||||||
let emptyLibraryContinue = yield this.checkEmptyLibrary(keyInfo);
|
let emptyLibraryContinue = yield this.checkEmptyLibrary(keyInfo);
|
||||||
if (!emptyLibraryContinue) {
|
if (!emptyLibraryContinue) {
|
||||||
this.end();
|
yield this.end(options);
|
||||||
Zotero.debug("Syncing cancelled because user library is empty");
|
Zotero.debug("Syncing cancelled because user library is empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +167,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
firstInSession: _firstInSession
|
firstInSession: _firstInSession
|
||||||
};
|
};
|
||||||
|
|
||||||
let librariesToSync = yield this.checkLibraries(
|
let librariesToSync = options.libraries = yield this.checkLibraries(
|
||||||
client,
|
client,
|
||||||
options,
|
options,
|
||||||
keyInfo,
|
keyInfo,
|
||||||
|
@ -217,10 +216,17 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
this.end();
|
yield this.end(options);
|
||||||
}
|
|
||||||
|
|
||||||
Zotero.debug("Done syncing");
|
if (options.restartSync) {
|
||||||
|
delete options.restartSync;
|
||||||
|
Zotero.debug("Restarting sync");
|
||||||
|
yield this.sync(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zotero.debug("Done syncing");
|
||||||
|
}
|
||||||
|
|
||||||
/*if (results.changesMade) {
|
/*if (results.changesMade) {
|
||||||
Zotero.debug("Changes made during file sync "
|
Zotero.debug("Changes made during file sync "
|
||||||
|
@ -682,33 +688,14 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.end = function () {
|
this.end = Zotero.Promise.coroutine(function* (options) {
|
||||||
this.updateIcons(_errors);
|
yield this.checkErrors(_errors, options);
|
||||||
|
if (!options.restartSync) {
|
||||||
|
this.updateIcons(_errors);
|
||||||
|
}
|
||||||
_errors = [];
|
_errors = [];
|
||||||
_syncInProgress = false;
|
_syncInProgress = false;
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log a warning, but don't throw an error
|
|
||||||
*/
|
|
||||||
this.warning = function (e) {
|
|
||||||
Zotero.debug(e, 2);
|
|
||||||
Components.utils.reportError(e);
|
|
||||||
e.errorType = 'warning';
|
|
||||||
_warning = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.error = function (e) {
|
|
||||||
if (typeof e == 'string') {
|
|
||||||
e = new Error(e);
|
|
||||||
e.errorType = 'error';
|
|
||||||
}
|
|
||||||
Zotero.debug(e, 1);
|
|
||||||
this.updateIcons(e);
|
|
||||||
throw (e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -846,7 +833,17 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.checkError = function (e, background) {
|
this.checkErrors = Zotero.Promise.coroutine(function* (errors, options = {}) {
|
||||||
|
for (let e of errors) {
|
||||||
|
let handled = yield this.checkError(e, options);
|
||||||
|
if (handled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.checkError = Zotero.Promise.coroutine(function* (e, options = {}) {
|
||||||
if (e.name && e.name == 'Zotero Error') {
|
if (e.name && e.name == 'Zotero Error') {
|
||||||
switch (e.error) {
|
switch (e.error) {
|
||||||
case Zotero.Error.ERROR_SYNC_USERNAME_NOT_SET:
|
case Zotero.Error.ERROR_SYNC_USERNAME_NOT_SET:
|
||||||
|
@ -859,9 +856,9 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
var msg = Zotero.getString('sync.error.invalidLogin.text');
|
var msg = Zotero.getString('sync.error.invalidLogin.text');
|
||||||
e.message = msg;
|
e.message = msg;
|
||||||
e.data = {};
|
e.data = {};
|
||||||
e.data.dialogText = msg;
|
e.dialogText = msg;
|
||||||
e.data.dialogButtonText = Zotero.getString('sync.openSyncPreferences');
|
e.dialogButtonText = Zotero.getString('sync.openSyncPreferences');
|
||||||
e.data.dialogButtonCallback = function () {
|
e.dialogButtonCallback = function () {
|
||||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||||
.getService(Components.interfaces.nsIWindowMediator);
|
.getService(Components.interfaces.nsIWindowMediator);
|
||||||
var win = wm.getMostRecentWindow("navigator:browser");
|
var win = wm.getMostRecentWindow("navigator:browser");
|
||||||
|
@ -905,6 +902,83 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (e.name && e.name == 'ZoteroObjectUploadError') {
|
||||||
|
// Tag too long
|
||||||
|
if (e.code == 413 && e.data && e.data.tag !== undefined) {
|
||||||
|
// Show long tag fixer and handle result
|
||||||
|
e.dialogButtonText = Zotero.getString('general.fix');
|
||||||
|
e.dialogButtonCallback = Zotero.Promise.coroutine(function* () {
|
||||||
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||||
|
.getService(Components.interfaces.nsIWindowMediator);
|
||||||
|
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||||
|
|
||||||
|
// Open long tag fixer for every long tag in every editable library we're syncing
|
||||||
|
var editableLibraries = options.libraries
|
||||||
|
.filter(x => Zotero.Libraries.get(x).editable);
|
||||||
|
for (let libraryID of editableLibraries) {
|
||||||
|
let oldTagIDs = yield Zotero.Tags.getLongTagsInLibrary(libraryID);
|
||||||
|
for (let oldTagID of oldTagIDs) {
|
||||||
|
let oldTag = Zotero.Tags.getName(oldTagID);
|
||||||
|
let dataOut = { result: null };
|
||||||
|
lastWin.openDialog(
|
||||||
|
'chrome://zotero/content/longTagFixer.xul',
|
||||||
|
'',
|
||||||
|
'chrome,modal,centerscreen',
|
||||||
|
oldTag,
|
||||||
|
dataOut
|
||||||
|
);
|
||||||
|
// If dialog was cancelled, stop
|
||||||
|
if (!dataOut.result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (dataOut.result.op) {
|
||||||
|
case 'split':
|
||||||
|
for (let libraryID of editableLibraries) {
|
||||||
|
let itemIDs = yield Zotero.Tags.getTagItems(libraryID, oldTagID);
|
||||||
|
yield Zotero.DB.executeTransaction(function* () {
|
||||||
|
for (let itemID of itemIDs) {
|
||||||
|
let item = yield Zotero.Items.getAsync(itemID);
|
||||||
|
for (let tag of dataOut.result.tags) {
|
||||||
|
item.addTag(tag);
|
||||||
|
}
|
||||||
|
item.removeTag(oldTag);
|
||||||
|
yield item.save();
|
||||||
|
}
|
||||||
|
yield Zotero.Tags.purge(oldTagID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'edit':
|
||||||
|
for (let libraryID of editableLibraries) {
|
||||||
|
let itemIDs = yield Zotero.Tags.getTagItems(libraryID, oldTagID);
|
||||||
|
yield Zotero.DB.executeTransaction(function* () {
|
||||||
|
for (let itemID of itemIDs) {
|
||||||
|
let item = yield Zotero.Items.getAsync(itemID);
|
||||||
|
item.replaceTag(oldTag, dataOut.result.tag);
|
||||||
|
yield item.save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
for (let libraryID of editableLibraries) {
|
||||||
|
yield Zotero.Tags.removeFromLibrary(libraryID, oldTagID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options.restartSync = true;
|
||||||
|
});
|
||||||
|
// If not a background sync, show fixer dialog immediately
|
||||||
|
if (!options.background) {
|
||||||
|
yield e.dialogButtonCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TEMP
|
// TEMP
|
||||||
return;
|
return;
|
||||||
|
@ -920,8 +994,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
if (!skipReload) {
|
if (!skipReload) {
|
||||||
Zotero.reloadDataObjects();
|
Zotero.reloadDataObjects();
|
||||||
}
|
}
|
||||||
Zotero.Sync.EventListener.resetIgnored();
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1099,20 +1172,20 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
|
|
||||||
/*// If not an error and there's no explicit button text, don't show
|
/*// If not an error and there's no explicit button text, don't show
|
||||||
// button to report errors
|
// button to report errors
|
||||||
if (e.errorType != 'error' && e.data.dialogButtonText === undefined) {
|
if (e.errorType != 'error' && e.dialogButtonText === undefined) {
|
||||||
e.data.dialogButtonText = null;
|
e.dialogButtonText = null;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (e.data && e.data.dialogButtonText !== null) {
|
if (e.data && e.dialogButtonText !== null) {
|
||||||
if (e.data.dialogButtonText === undefined) {
|
if (e.dialogButtonText === undefined) {
|
||||||
var buttonText = Zotero.getString('errorReport.reportError');
|
var buttonText = Zotero.getString('errorReport.reportError');
|
||||||
var buttonCallback = function () {
|
var buttonCallback = function () {
|
||||||
doc.defaultView.ZoteroPane.reportErrors();
|
doc.defaultView.ZoteroPane.reportErrors();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var buttonText = e.data.dialogButtonText;
|
var buttonText = e.dialogButtonText;
|
||||||
var buttonCallback = e.data.dialogButtonCallback;
|
var buttonCallback = e.dialogButtonCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
var button = doc.createElement('button');
|
var button = doc.createElement('button');
|
||||||
|
|
|
@ -56,6 +56,7 @@ general.openPreferences = Open Preferences
|
||||||
general.keys.ctrlShift = Ctrl+Shift+
|
general.keys.ctrlShift = Ctrl+Shift+
|
||||||
general.keys.cmdShift = Cmd+Shift+
|
general.keys.cmdShift = Cmd+Shift+
|
||||||
general.dontShowAgain = Don’t Show Again
|
general.dontShowAgain = Don’t Show Again
|
||||||
|
general.fix = Fix…
|
||||||
|
|
||||||
general.operationInProgress = A Zotero operation is currently in progress.
|
general.operationInProgress = A Zotero operation is currently in progress.
|
||||||
general.operationInProgress.waitUntilFinished = Please wait until it has finished.
|
general.operationInProgress.waitUntilFinished = Please wait until it has finished.
|
||||||
|
|
|
@ -670,58 +670,9 @@ describe("Zotero.Sync.Runner", function () {
|
||||||
assert.isAbove(lastSyncTime, new Date().getTime() - 1000);
|
assert.isAbove(lastSyncTime, new Date().getTime() - 1000);
|
||||||
assert.isBelow(lastSyncTime, new Date().getTime());
|
assert.isBelow(lastSyncTime, new Date().getTime());
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
it("should show the sync error icon on error", function* () {
|
|
||||||
let pubLib = Zotero.Libraries.get(publicationsLibraryID);
|
|
||||||
pubLib.libraryVersion = 5;
|
|
||||||
yield pubLib.save();
|
|
||||||
|
|
||||||
setResponse('keyInfo.fullAccess');
|
|
||||||
setResponse('userGroups.groupVersionsEmpty');
|
|
||||||
// My Library
|
|
||||||
setResponse({
|
|
||||||
method: "GET",
|
|
||||||
url: "users/1/settings",
|
|
||||||
status: 200,
|
|
||||||
headers: {
|
|
||||||
"Last-Modified-Version": 5
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
INVALID: true // TODO: Find a cleaner error
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// No publications changes
|
|
||||||
setResponse({
|
|
||||||
method: "GET",
|
|
||||||
url: "users/1/publications/settings?since=5",
|
|
||||||
status: 304,
|
|
||||||
headers: {
|
|
||||||
"Last-Modified-Version": 5
|
|
||||||
},
|
|
||||||
json: {}
|
|
||||||
});
|
|
||||||
setResponse({
|
|
||||||
method: "GET",
|
|
||||||
url: "users/1/publications/fulltext",
|
|
||||||
status: 200,
|
|
||||||
headers: {
|
|
||||||
"Last-Modified-Version": 5
|
|
||||||
},
|
|
||||||
json: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
spy = sinon.spy(runner, "updateIcons");
|
|
||||||
yield runner.sync();
|
|
||||||
assert.isTrue(spy.calledTwice);
|
|
||||||
assert.isArray(spy.args[1][0]);
|
|
||||||
assert.lengthOf(spy.args[1][0], 1);
|
|
||||||
// Not an instance of Error for some reason
|
|
||||||
var error = spy.args[1][0][0];
|
|
||||||
assert.equal(Object.getPrototypeOf(error).constructor.name, "Error");
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
describe("#createAPIKeyFromCredentials()", function() {
|
describe("#createAPIKeyFromCredentials()", function() {
|
||||||
var data = {
|
var data = {
|
||||||
name: "Automatic Zotero Client Key",
|
name: "Automatic Zotero Client Key",
|
||||||
|
@ -785,5 +736,211 @@ describe("Zotero.Sync.Runner", function () {
|
||||||
|
|
||||||
yield runner.deleteAPIKey();
|
yield runner.deleteAPIKey();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("Error Handling", function () {
|
||||||
|
var win;
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
if (win) {
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show the sync error icon on error", function* () {
|
||||||
|
let pubLib = Zotero.Libraries.get(publicationsLibraryID);
|
||||||
|
pubLib.libraryVersion = 5;
|
||||||
|
yield pubLib.save();
|
||||||
|
|
||||||
|
setResponse('keyInfo.fullAccess');
|
||||||
|
setResponse('userGroups.groupVersionsEmpty');
|
||||||
|
// My Library
|
||||||
|
setResponse({
|
||||||
|
method: "GET",
|
||||||
|
url: "users/1/settings",
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"Last-Modified-Version": 5
|
||||||
|
},
|
||||||
|
json: {
|
||||||
|
INVALID: true // TODO: Find a cleaner error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// No publications changes
|
||||||
|
setResponse({
|
||||||
|
method: "GET",
|
||||||
|
url: "users/1/publications/settings?since=5",
|
||||||
|
status: 304,
|
||||||
|
headers: {
|
||||||
|
"Last-Modified-Version": 5
|
||||||
|
},
|
||||||
|
json: {}
|
||||||
|
});
|
||||||
|
setResponse({
|
||||||
|
method: "GET",
|
||||||
|
url: "users/1/publications/fulltext",
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"Last-Modified-Version": 5
|
||||||
|
},
|
||||||
|
json: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
spy = sinon.spy(runner, "updateIcons");
|
||||||
|
yield runner.sync();
|
||||||
|
assert.isTrue(spy.calledTwice);
|
||||||
|
assert.isArray(spy.args[1][0]);
|
||||||
|
assert.lengthOf(spy.args[1][0], 1);
|
||||||
|
// Not an instance of Error for some reason
|
||||||
|
var error = spy.args[1][0][0];
|
||||||
|
assert.equal(Object.getPrototypeOf(error).constructor.name, "Error");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Test multiple long tags and tags across libraries
|
||||||
|
describe("Long Tag Fixer", function () {
|
||||||
|
it("should split a tag", function* () {
|
||||||
|
win = yield loadZoteroPane();
|
||||||
|
|
||||||
|
var item = yield createDataObject('item');
|
||||||
|
var tag = "title;feeling;matter;drum;treatment;caring;earthy;shrill;unit;obedient;hover;healthy;cheap;clever;wren;wicked;clip;shoe;jittery;shape;clear;dime;increase;complete;level;milk;false;infamous;lamentable;measure;cuddly;tasteless;peace;top;pencil;caption;unusual;depressed;frantic";
|
||||||
|
item.addTag(tag, 1);
|
||||||
|
yield item.saveTx();
|
||||||
|
|
||||||
|
setResponse('keyInfo.fullAccess');
|
||||||
|
setResponse('userGroups.groupVersions');
|
||||||
|
setResponse('groups.ownerGroup');
|
||||||
|
setResponse('groups.memberGroup');
|
||||||
|
|
||||||
|
server.respond(function (req) {
|
||||||
|
if (req.method == "POST" && req.url == baseURL + "users/1/items") {
|
||||||
|
var json = JSON.parse(req.requestBody);
|
||||||
|
if (json[0].tags.length == 1) {
|
||||||
|
req.respond(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"Last-Modified-Version": 5
|
||||||
|
},
|
||||||
|
JSON.stringify({
|
||||||
|
successful: {},
|
||||||
|
success: {},
|
||||||
|
unchanged: {},
|
||||||
|
failed: {
|
||||||
|
"0": {
|
||||||
|
code: 413,
|
||||||
|
message: "Tag 'title;feeling;matter;drum;treatment;caring;earthy;shrill;unit;obedient;hover…' is too long to sync",
|
||||||
|
data: {
|
||||||
|
tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let itemJSON = item.toResponseJSON();
|
||||||
|
itemJSON.version = 6;
|
||||||
|
itemJSON.data.version = 6;
|
||||||
|
|
||||||
|
req.respond(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"Last-Modified-Version": 6
|
||||||
|
},
|
||||||
|
JSON.stringify({
|
||||||
|
successful: {
|
||||||
|
"0": itemJSON
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
"0": json[0].key
|
||||||
|
},
|
||||||
|
unchanged: {},
|
||||||
|
failed: {}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
waitForDialog(null, 'accept', 'chrome://zotero/content/longTagFixer.xul');
|
||||||
|
yield runner.sync({ libraries: [Zotero.Libraries.userLibraryID] });
|
||||||
|
|
||||||
|
assert.isFalse(Zotero.Tags.getID(tag));
|
||||||
|
assert.isNumber(Zotero.Tags.getID('feeling'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should delete a tag", function* () {
|
||||||
|
win = yield loadZoteroPane();
|
||||||
|
|
||||||
|
var item = yield createDataObject('item');
|
||||||
|
var tag = "title;feeling;matter;drum;treatment;caring;earthy;shrill;unit;obedient;hover;healthy;cheap;clever;wren;wicked;clip;shoe;jittery;shape;clear;dime;increase;complete;level;milk;false;infamous;lamentable;measure;cuddly;tasteless;peace;top;pencil;caption;unusual;depressed;frantic";
|
||||||
|
item.addTag(tag, 1);
|
||||||
|
yield item.saveTx();
|
||||||
|
|
||||||
|
setResponse('keyInfo.fullAccess');
|
||||||
|
setResponse('userGroups.groupVersions');
|
||||||
|
setResponse('groups.ownerGroup');
|
||||||
|
setResponse('groups.memberGroup');
|
||||||
|
|
||||||
|
server.respond(function (req) {
|
||||||
|
if (req.method == "POST" && req.url == baseURL + "users/1/items") {
|
||||||
|
var json = JSON.parse(req.requestBody);
|
||||||
|
if (json[0].tags.length == 1) {
|
||||||
|
req.respond(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"Last-Modified-Version": 5
|
||||||
|
},
|
||||||
|
JSON.stringify({
|
||||||
|
successful: {},
|
||||||
|
success: {},
|
||||||
|
unchanged: {},
|
||||||
|
failed: {
|
||||||
|
"0": {
|
||||||
|
code: 413,
|
||||||
|
message: "Tag 'title;feeling;matter;drum;treatment;caring;earthy;shrill;unit;obedient;hover…' is too long to sync",
|
||||||
|
data: {
|
||||||
|
tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let itemJSON = item.toResponseJSON();
|
||||||
|
itemJSON.version = 6;
|
||||||
|
itemJSON.data.version = 6;
|
||||||
|
|
||||||
|
req.respond(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"Last-Modified-Version": 6
|
||||||
|
},
|
||||||
|
JSON.stringify({
|
||||||
|
successful: {
|
||||||
|
"0": itemJSON
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
"0": json[0].key
|
||||||
|
},
|
||||||
|
unchanged: {},
|
||||||
|
failed: {}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
waitForDialog(function (dialog) {
|
||||||
|
dialog.Zotero_Long_Tag_Fixer.switchMode(2);
|
||||||
|
}, 'accept', 'chrome://zotero/content/longTagFixer.xul');
|
||||||
|
yield runner.sync({ libraries: [Zotero.Libraries.userLibraryID] });
|
||||||
|
|
||||||
|
assert.isFalse(Zotero.Tags.getID(tag));
|
||||||
|
assert.isFalse(Zotero.Tags.getID('feeling'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user