commit 45c944e7313aeb05a3e8c7275786e07a344067a8
parent 1b67ed071e80f1091fa77ec910f098495fbf6a40
Author: Adomas VenĨkauskas <adomas.ven@gmail.com>
Date: Wed, 30 Nov 2016 13:53:58 +0200
Fix server_connector tests broken in 69ab4b0b
Don't display error prompt in standalone when style install fails.
Fixes an import bug when import input is invalid.
Diffstat:
5 files changed, 88 insertions(+), 33 deletions(-)
diff --git a/chrome/content/zotero/xpcom/server_connector.js b/chrome/content/zotero/xpcom/server_connector.js
@@ -605,7 +605,7 @@ Zotero.Server.Connector.Import.prototype = {
translate.setString(data);
let translators = yield translate.getTranslators();
if (!translators || !translators.length) {
- return sendResponseCallback(404);
+ return sendResponseCallback(400);
}
translate.setTranslator(translators[0]);
let items = yield translate.translate();
@@ -628,7 +628,11 @@ Zotero.Server.Connector.InstallStyle.prototype = {
permitBookmarklet: false,
init: Zotero.Promise.coroutine(function* (url, data, sendResponseCallback){
- let styleName = yield Zotero.Styles.install(data, url.query.origin || null, true);
+ try {
+ var styleName = yield Zotero.Styles.install(data, url.query.origin || null, true);
+ } catch (e) {
+ sendResponseCallback(400, "text/plain", e.message)
+ }
sendResponseCallback(201, "application/json", JSON.stringify({name: styleName}));
})
};
diff --git a/chrome/content/zotero/xpcom/style.js b/chrome/content/zotero/xpcom/style.js
@@ -242,31 +242,40 @@ Zotero.Styles = new function() {
* containing the style data
* @param {String} origin The origin of the style, either a filename or URL, to be
* displayed in dialogs referencing the style
- * @param {Boolean} [noPrompt=false] Skip the confirmation prompt
+ * @param {Boolean} [silent=false] Skip prompts
*/
- this.install = Zotero.Promise.coroutine(function* (style, origin, noPrompt=false) {
+ this.install = Zotero.Promise.coroutine(function* (style, origin, silent=false) {
var styleTitle;
+ origin = origin || Zotero.getString('styles.unknownOrigin');
try {
if (style instanceof Components.interfaces.nsIFile) {
// handle nsIFiles
var url = Services.io.newFileURI(style);
var xmlhttp = yield Zotero.HTTP.request("GET", url.spec);
- styleTitle = yield _install(xmlhttp.responseText, style.leafName, false, noPrompt);
+ styleTitle = yield _install(xmlhttp.responseText, style.leafName, false, silent);
} else {
- styleTitle = yield _install(style, origin, false, noPrompt);
+ styleTitle = yield _install(style, origin, false, silent);
}
}
catch (error) {
// Unless user cancelled, show an alert with the error
if(typeof error === "object" && error instanceof Zotero.Exception.UserCancelled) return;
if(typeof error === "object" && error instanceof Zotero.Exception.Alert) {
- error.present();
error.log();
+ if (silent) {
+ throw (error)
+ } else {
+ error.present();
+ }
} else {
Zotero.logError(error);
- (new Zotero.Exception.Alert("styles.install.unexpectedError",
- origin, "styles.install.title", error)).present();
+ if (silent) {
+ throw error
+ } else {
+ (new Zotero.Exception.Alert("styles.install.unexpectedError",
+ origin, "styles.install.title", error)).present();
+ }
}
}
return styleTitle;
@@ -278,10 +287,10 @@ Zotero.Styles = new function() {
* @param {String} origin The origin of the style, either a filename or URL, to be
* displayed in dialogs referencing the style
* @param {Boolean} [hidden] Whether style is to be hidden.
- * @param {Boolean} [noPrompt=false] Skip the confirmation prompt
+ * @param {Boolean} [silent=false] Skip prompts
* @return {Promise}
*/
- var _install = Zotero.Promise.coroutine(function* (style, origin, hidden, noPrompt=false) {
+ var _install = Zotero.Promise.coroutine(function* (style, origin, hidden, silent=false) {
if (!_initialized) yield Zotero.Styles.init();
var existingFile, destFile, source;
@@ -364,7 +373,7 @@ Zotero.Styles = new function() {
// display a dialog to tell the user we're about to install the style
if(hidden) {
destFile = destFileHidden;
- } else if (!noPrompt) {
+ } else if (!silent) {
if(existingTitle) {
var text = Zotero.getString('styles.updateStyle', [existingTitle, title, origin]);
} else {
diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js
@@ -1094,6 +1094,8 @@ Zotero.Translate.Base.prototype = {
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect";
this._getAllTranslators = getAllTranslators;
+ this._potentialTranslators = [];
+ this._foundTranslators = [];
if(checkSetTranslator) {
// setTranslator must be called beforehand if checkSetTranslator is set
@@ -1123,8 +1125,6 @@ Zotero.Translate.Base.prototype = {
return potentialTranslators.then(function(result) {
var allPotentialTranslators = result[0];
var properToProxyFunctions = result[1];
- this._potentialTranslators = [];
- this._foundTranslators = [];
// this gets passed out by Zotero.Translators.getWebTranslatorsForLocation() because it is
// specific for each translator, but we want to avoid making a copy of a translator whenever
@@ -1441,7 +1441,6 @@ Zotero.Translate.Base.prototype = {
var errorString = null;
if(!returnValue && error) errorString = this._generateErrorString(error);
-
if(this._currentState === "detect") {
if(this._potentialTranslators.length) {
var lastTranslator = this._potentialTranslators.shift();
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
@@ -832,6 +832,7 @@ styles.validationWarning = "%S" is not a valid CSL 1.0.1 style file, and may n
styles.installSourceError = %1$S references an invalid or non-existent CSL file at %2$S as its source.
styles.deleteStyle = Are you sure you want to delete the style "%1$S"?
styles.deleteStyles = Are you sure you want to delete the selected styles?
+styles.unknownOrigin = External Style
styles.abbreviations.title = Load Abbreviations
styles.abbreviations.parseError = The abbreviations file "%1$S" is not valid JSON.
diff --git a/test/tests/server_connectorTest.js b/test/tests/server_connectorTest.js
@@ -6,11 +6,13 @@ describe("Connector Server", function () {
var testServerPort = 16213;
before(function* () {
+ this.timeout(20000);
Zotero.Prefs.set("httpServer.enabled", true);
yield resetDB({
thisArg: this,
skipBundledFiles: true
});
+ yield Zotero.Translators.init();
win = yield loadZoteroPane();
connectorServerPath = 'http://127.0.0.1:' + Zotero.Prefs.get('httpServer.port');
@@ -314,30 +316,30 @@ describe("Connector Server", function () {
});
});
- describe('/connector/importStyle', function() {
+ describe('/connector/installStyle', function() {
var endpoint;
before(function() {
- endpoint = connectorServerPath + "/connector/importStyle";
+ endpoint = connectorServerPath + "/connector/installStyle";
});
- it('should reject application/json requests', function* () {
- try {
- var response = yield Zotero.HTTP.request(
- 'POST',
- endpoint,
- {
- headers: { "Content-Type": "application/json" },
- body: '{}'
- }
- );
- } catch(e) {
- assert.instanceOf(e, Zotero.HTTP.UnexpectedStatusException);
- assert.equal(e.xmlhttp.status, 400);
- }
+ it('should reject styles with invalid text', function* () {
+ var error = yield getPromiseError(Zotero.HTTP.request(
+ 'POST',
+ endpoint,
+ {
+ headers: { "Content-Type": "application/json" },
+ body: '{}'
+ }
+ ));
+ assert.instanceOf(error, Zotero.HTTP.UnexpectedStatusException);
+ assert.equal(error.xmlhttp.status, 400);
+ assert.equal(error.xmlhttp.responseText,
+ Zotero.getString("styles.installError",
+ Zotero.getString('styles.unknownOrigin')));
});
- it('should import a style with text/x-csl content-type', function* () {
+ it('should import a style with application/vnd.citationstyles.style+xml content-type', function* () {
sinon.stub(Zotero.Styles, 'install', function(style) {
var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser),
@@ -362,7 +364,7 @@ describe("Connector Server", function () {
'POST',
endpoint,
{
- headers: { "Content-Type": "text/x-csl" },
+ headers: { "Content-Type": "application/vnd.citationstyles.style+xml" },
body: style
}
);
@@ -371,4 +373,44 @@ describe("Connector Server", function () {
Zotero.Styles.install.restore();
});
});
+
+ describe('/connector/import', function() {
+ var endpoint;
+
+ before(function() {
+ endpoint = connectorServerPath + "/connector/import";
+ });
+
+ it('should reject resources that do not contain import data', function* () {
+ var error = yield getPromiseError(Zotero.HTTP.request(
+ 'POST',
+ endpoint,
+ {
+ headers: { "Content-Type": "text/plain" },
+ body: 'Owl'
+ }
+ ));
+ assert.instanceOf(error, Zotero.HTTP.UnexpectedStatusException);
+ assert.equal(error.xmlhttp.status, 400);
+ });
+
+ it('should import resources (BibTeX)', function* () {
+ var resource = `@book{test1,
+ title={Test1},
+ author={Owl},
+ year={1000},
+ publisher={Curly Braces Publishing}
+}`;
+ var response = yield Zotero.HTTP.request(
+ 'POST',
+ endpoint,
+ {
+ headers: { "Content-Type": "application/x-bibtex" },
+ body: resource
+ }
+ );
+ assert.equal(response.status, 201);
+ assert.equal(JSON.parse(response.responseText)[0].title, 'Test1');
+ });
+ });
});