From 5aa511cf6dd09fdb5d2f0a3de547e9aad2fbaf6d Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Thu, 23 Jun 2011 08:03:29 +0000 Subject: [PATCH] - Closes #1839, [patch] Pluralization in translatorTester.js (thanks to Avram) - Fixes a bug with XMLHttpRequests for XML files on Chrome/Safari - Adds support for running tests for search translators and (untested) support for running tests for import translators - If a test specifies "items":"multiple", the testing framework ensures that multiple items are available, but only tests saving one - Properties explicitly defined as false are now ignored --- .../tools/testTranslators/translatorTester.js | 201 ++++++++++++------ 1 file changed, 135 insertions(+), 66 deletions(-) diff --git a/chrome/content/zotero/tools/testTranslators/translatorTester.js b/chrome/content/zotero/tools/testTranslators/translatorTester.js index 40364aaf2..64f712e73 100644 --- a/chrome/content/zotero/tools/testTranslators/translatorTester.js +++ b/chrome/content/zotero/tools/testTranslators/translatorTester.js @@ -79,20 +79,26 @@ Zotero_TranslatorTester = function(translator, type, debug) { * Removes document objects, which contain cyclic references, and other fields to be ignored from items * @param {Object} Item, in the format returned by Zotero.Item.serialize() */ -Zotero_TranslatorTester._sanitizeItem = function(item) { - // remove cyclic references +Zotero_TranslatorTester._sanitizeItem = function(item, forSave) { + // remove cyclic references if(item.attachments && item.attachments.length) { + // don't actually test URI equality for (var i=0; i 1 || - test.items.length === 1 && translators[0].itemType !== test.items[0].itemType) { + } else if(this._type === "web" && (translators[0].itemType !== "multiple" && test.items.length > 1 || + test.items.length === 1 && translators[0].itemType !== test.items[0].itemType)) { + // this handles "items":"multiple" too, since the string has length 8 testDoneCallback(this, test, "failed", "Detection returned wrong item type"); return; } @@ -217,19 +268,21 @@ Zotero_TranslatorTester.prototype._checkResult = function(test, translate, retur return; } - if(translate.newItems.length !== test.items.length) { - testDoneCallback(this, test, "unknown", "Expected "+test.items.length+" items; got "+translate.newItems.length); - return; - } - - for(var i in test.items) { - var testItem = Zotero_TranslatorTester._sanitizeItem(test.items[i]); - var translatedItem = Zotero_TranslatorTester._sanitizeItem(translate.newItems[i]); - - if(!this._compare(testItem, translatedItem)) { - testDoneCallback(this, test, "unknown", "Item "+i+" does not match"); + if(test.items !== "multiple") { + if(translate.newItems.length !== test.items.length) { + testDoneCallback(this, test, "unknown", "Expected "+test.items.length+" items; got "+translate.newItems.length); return; } + + for(var i in test.items) { + var testItem = Zotero_TranslatorTester._sanitizeItem(test.items[i]); + var translatedItem = Zotero_TranslatorTester._sanitizeItem(translate.newItems[i]); + + if(!this._compare(testItem, translatedItem)) { + testDoneCallback(this, test, "unknown", "Item "+i+" does not match"); + return; + } + } } testDoneCallback(this, test, "succeeded", "Test succeeded"); @@ -241,12 +294,26 @@ Zotero_TranslatorTester.prototype._checkResult = function(test, translate, retur * @param {Function} testReadyCallback A callback to be passed test (as object) when complete */ Zotero_TranslatorTester.prototype.newTest = function(doc, testReadyCallback) { + // keeps track of whether select was called + var multipleMode = false; + var me = this; var translate = Zotero.Translate.newInstance(this._type); translate.setDocument(doc); translate.setTranslator(this._translator); translate.setHandler("debug", this._debug); - translate.setHandler("done", function(obj, returnValue) { me._createTest(obj, returnValue, testReadyCallback) }); + translate.setHandler("select", function(obj, items, callback) { + multipleMode = true; + + var newItems = {}; + for(var i in items) { + newItems[i] = items[i]; + break; + } + + callback(newItems); + }); + translate.setHandler("done", function(obj, returnValue) { me._createTest(obj, multipleMode, returnValue, testReadyCallback) }); translate.translate(false); }; @@ -255,16 +322,26 @@ Zotero_TranslatorTester.prototype.newTest = function(doc, testReadyCallback) { * @param {Zotero.Translate} translate The Zotero.Translate instance * @param {Function} testDoneCallback A callback to be passed test (as object) when complete */ -Zotero_TranslatorTester.prototype._createTest = function(translate, returnValue, testReadyCallback) { +Zotero_TranslatorTester.prototype._createTest = function(translate, multipleMode, returnValue, testReadyCallback) { if(!returnValue) { testReadyCallback(returnValue); return; } - for(var i in translate.newItems) Zotero_TranslatorTester._sanitizeItem(translate.newItems[i]); - testReadyCallback(this, {"type":this._type, - "url":translate.document.location.href, - "items":translate.newItems}); + if(!translate.newItems.length) { + testReadyCallback(false); + return; + } + + if(multipleMode) { + var items = "multiple"; + } else { + for(var i in translate.newItems) Zotero_TranslatorTester._sanitizeItem(translate.newItems[i], true); + var items = translate.newItems; + } + + testReadyCallback(this, {"type":this._type, "url":translate.document.location.href, + "items":items}); }; @@ -304,12 +381,7 @@ Zotero_TranslatorTester.prototype._compare = function(i, j) { Zotero_TranslatorTester.prototype._objectCompare = function(x, y) { // Special handlers var _debug = this._debug; - var special = { - "complete" : function(a,b) { _debug(this, "Ignoring non-matching parameter 'complete'"); return true }, - "accessDate" : function(a,b) { _debug(this, "Ignoring non-matching parameter 'accessDate'"); return true }, - "checkFields" : function(a,b) { _debug(this, "Ignoring non-matching parameter 'checkFields'"); return true } - }; - + var returner = function(param) { if (special[param]) return special[param](x[param], y[param]); else return false; @@ -320,42 +392,39 @@ Zotero_TranslatorTester.prototype._objectCompare = function(x, y) { return false; } - for(p in y) { if(typeof(x[p])=='undefined') { - this._debug(this, "Param "+p+" in y not defined in x"); - return returner(p); + for(p in y) { + if(y[p] || y[p] === 0) { + switch(typeof(y[p])) { + case 'object': + if (!this._objectCompare(y[p],x[p])) { + return false; + }; + break; + case 'function': + if (typeof(x[p])=='undefined' + || (y[p].toString() != x[p].toString())) { + this._debug(this, "Function "+p+" defined in y, not in x, or definitions differ"); + return false; + } + break; + default: + if (y[p] != x[p] && x[p] !== false) { // special exemption: x (test item) + // can have a property set to false + // and we will ignore it here + this._debug(this, "Param "+p+" differs: " + JSON.stringify({x:x[p], y:y[p]})); + return false; + } + } + } else if(x[p] || x[p] === 0) { + this._debug(this, "Param "+p+" true in x, not in y"); + return false; } } - for(p in y) { if (y[p]) { - switch(typeof(y[p])) { - case 'object': - if (!this._objectCompare(y[p],x[p])) { - return returner(p); - }; - break; - case 'function': - if (typeof(x[p])=='undefined' - || (y[p].toString() != x[p].toString())) { - this._debug(this, "Function "+p+" defined in y, not in x, or definitions differ"); - return returner(p) }; - break; - default: - if (y[p] != x[p]) { - this._debug(this, "Param "+p+" differs: " + JSON.stringify({x:x[p], y:y[p]})); - return returner(p); - } - } - } else { - if (x[p]) { - this._debug(this, "Param "+p+" true in x, not in y"); - return returner(p); - } - } } - for(p in x) { - if(typeof(y[p])=='undefined') { + if((x[p] || x[p] === 0) && typeof(y[p])=='undefined') { this._debug(this, "Param "+p+" in x not defined in y"); - return returner(p); + return false; } } return true;