www

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

commit ed49b867ac3405c10963ae979d4310fb9ccc6d01
parent 076658824184f61cc5a49c86608c974952de92d8
Author: Simon Kornblith <simon@simonster.com>
Date:   Sat, 14 Jul 2012 16:43:28 -0400

Merge branch '3.0'

Conflicts:
	chrome/content/zotero/locale/csl

Diffstat:
Mchrome/content/zotero/tools/testTranslators/translatorTester.js | 169++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mchrome/content/zotero/xpcom/connector/cachedTypes.js | 2+-
Mchrome/content/zotero/xpcom/utilities.js | 21++++++++++++++-------
3 files changed, 122 insertions(+), 70 deletions(-)

diff --git a/chrome/content/zotero/tools/testTranslators/translatorTester.js b/chrome/content/zotero/tools/testTranslators/translatorTester.js @@ -506,6 +506,11 @@ Zotero_TranslatorTester.prototype._checkResult = function(test, translate, retur var translatedItem = Zotero_TranslatorTester._sanitizeItem(translate.newItems[i]); if(!this._compare(testItem, translatedItem)) { + // Show diff + this._debug(this, "TranslatorTester: Data mismatch detected:"); + this._debug(this, this._generateDiff(testItem, translatedItem)); + + // Save items. This makes it easier to correct tests automatically. var m = translate.newItems.length; test.itemsReturned = new Array(m); for(var j=0; j<m; j++) { @@ -584,77 +589,116 @@ Zotero_TranslatorTester.prototype._createTest = function(translate, multipleMode /** * Compare items or sets thereof */ -Zotero_TranslatorTester.prototype._compare = function(i, j) { - var match = false; - if (Object.prototype.toString.apply(i) === '[object Array]') { - if (Object.prototype.toString.apply(j) === '[object Array]') { - do { - match = this._compare(i.pop(), j.pop()); - } while (match && i.length && j.length); - if (match) - return true; - else - return false; - } else { - this._debug(this, "TranslatorTester: i is array, j is not"); +Zotero_TranslatorTester.prototype._compare = function(a, b) { + // If a is false, comparisons always succeed. This allows us to explicitly set that + // certain properties are allowed. + if(a === false) return true; + + if(((typeof a === "object" && a !== null) || typeof a === "function") + && ((typeof a === "object" && b !== null) || typeof b === "function")) { + if((Object.prototype.toString.apply(a) === "[object Array]") + !== (Object.prototype.toString.apply(b) === "[object Array]")) { return false; } - } else if (Object.prototype.toString.apply(j) === '[object Array]') { - this._debug(this, "TranslatorTester: j is array, i is not"); - return false; - } - - // Neither is an array - if(this._objectCompare(i, j)) { + for(var key in a) { + if(!a.hasOwnProperty(key)) continue; + if(a[key] !== false && !b.hasOwnProperty(key)) return false; + if(!this._compare(a[key], b[key])) return false; + } + for(var key in b) { + if(!b.hasOwnProperty(key)) continue; + if(!a.hasOwnProperty(key)) return false; + } return true; - } else { - this._debug(this, JSON.stringify({i:i, j:j})); - this._debug(this, "TranslatorTester: Items don't match"); - return false; + } else if(typeof a === "string" && typeof b === "string") { + // Ignore whitespace mismatches on strings + return a === b || Zotero.Utilities.trimInternal(a) === Zotero.Utilities.trimInternal(b); } + return a === b; }; -Zotero_TranslatorTester.prototype._objectCompare = function(x, y) { - // Special handlers - var _debug = this._debug; - - var returner = function(param) { - if (special[param]) return special[param](x[param], y[param]); - else return false; - } - - if ((y === undefined && x !== undefined) - || (x === undefined && y !== undefined)) { - return false; +/** + * Generate a diff of items + */ +Zotero_TranslatorTester.prototype._generateDiff = new function() { + function show(a, action, prefix, indent) { + if((typeof a === "object" && a !== null) || typeof a === "function") { + var isArray = Object.prototype.toString.apply(a) === "[object Array]", + startBrace = (isArray ? "[" : "{"), + endBrace = (isArray ? "]" : "}"), + changes = "", + haveKeys = false; + + for(var key in a) { + if(!a.hasOwnProperty(key)) continue; + + haveKeys = true; + changes += show(a[key], action, + isArray ? "" : JSON.stringify(key)+": ", indent+" "); + } + + if(haveKeys) { + return action+" "+indent+prefix+startBrace+"\n"+ + changes+action+" "+indent+endBrace+"\n"; + } + return action+" "+indent+prefix+startBrace+endBrace+"\n"; + } + + return action+" "+indent+prefix+JSON.stringify(a)+"\n"; } - - for(p in y) { - if(y[p] || y[p] === 0) { - switch(typeof(y[p])) { - case 'object': - if (!this._objectCompare(x[p],y[p])) { - 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, "TranslatorTester: Param "+p+" differs: " + JSON.stringify({x:x[p], y:y[p]})); - return false; + + function compare(a, b, prefix, indent) { + if(!prefix) prefix = ""; + if(!indent) indent = ""; + + if(((typeof a === "object" && a !== null) || typeof a === "function") + && ((typeof b === "object" && b !== null) || typeof b === "function")) { + var aIsArray = Object.prototype.toString.apply(a) === "[object Array]", + bIsArray = Object.prototype.toString.apply(b) === "[object Array]"; + if(aIsArray === bIsArray) { + var startBrace = (aIsArray ? "[" : "{"), + endBrace = (aIsArray ? "]" : "}"), + changes = "", + haveKeys = false; + + for(var key in a) { + if(!a.hasOwnProperty(key)) continue; + + haveKeys = true; + var keyPrefix = aIsArray ? "" : JSON.stringify(key)+": "; + if(b.hasOwnProperty(key)) { + changes += compare(a[key], b[key], keyPrefix, indent+" "); + } else { + changes += show(a[key], "-", keyPrefix, indent+" "); } + } + for(var key in b) { + if(!b.hasOwnProperty(key)) continue; + + haveKeys = true; + if(!a.hasOwnProperty(key)) { + var keyPrefix = aIsArray ? "" : JSON.stringify(key)+": "; + changes += show(b[key], "+", keyPrefix, indent+" "); + } + } + + if(haveKeys) { + return " "+indent+prefix+startBrace+"\n"+ + changes+" "+indent+(aIsArray ? "]" : "}")+"\n"; + } + return " "+indent+prefix+startBrace+endBrace+"\n"; } - } else if(x[p] || x[p] === 0) { - this._debug(this, "TranslatorTester: Param "+p+" true in x, not in y"); - return false; } - } - - for(p in x) { - if((x[p] || x[p] === 0) && typeof(y[p])=='undefined') { - this._debug(this, "TranslatorTester: Param "+p+" in x not defined in y"); - return false; + + if(a === b) { + return show(a, " ", prefix, indent); } + return show(a, "-", prefix, indent)+show(b, "+", prefix, indent); } - return true; -}; + + return function(a, b) { + // Remove last newline + var txt = compare(a, b); + return txt.substr(0, txt.length-1); + }; +}; +\ No newline at end of file diff --git a/chrome/content/zotero/xpcom/connector/cachedTypes.js b/chrome/content/zotero/xpcom/connector/cachedTypes.js @@ -143,7 +143,7 @@ Zotero.Connector_Types = new function() { // loop through base fields for item type var baseFields = itemType[5]; - for(var i=0, n=baseFields.length; i<n; i++) { + for(var i in baseFields) { if(baseFields[i] === baseField) { return i; } diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js @@ -1340,7 +1340,11 @@ Zotero.Utilities = { if(!creatorType) continue; - var nameObj = {'family':creator.lastName, 'given':creator.firstName}; + if(creator.fieldMode == 1) { + var nameObj = {'literal':creator.lastName}; + } else { + var nameObj = {'family':creator.lastName, 'given':creator.firstName}; + } if(cslItem[creatorType]) { cslItem[creatorType].push(nameObj); @@ -1483,11 +1487,14 @@ Zotero.Utilities = { date = cslDate.literal; } } else { - var newDate = Zotero.Utilities.deepCopy(cslDate);; - if(cslDate.dateParts && typeof cslDate.dateParts == "object") { - if(cslDate.dateParts[0]) newDate.year = cslDate.dateParts[0]; - if(cslDate.dateParts[1]) newDate.month = cslDate.dateParts[1]; - if(cslDate.dateParts[2]) newDate.day = cslDate.dateParts[2]; + var newDate = Zotero.Utilities.deepCopy(cslDate); + if(cslDate["date-parts"] && typeof cslDate["date-parts"] === "object" + && cslDate["date-parts"] !== null + && typeof cslDate["date-parts"][0] === "object" + && cslDate["date-parts"][0] !== null) { + if(cslDate["date-parts"][0][0]) newDate.year = cslDate["date-parts"][0][0]; + if(cslDate["date-parts"][0][1]) newDate.month = cslDate["date-parts"][0][1]; + if(cslDate["date-parts"][0][2]) newDate.day = cslDate["date-parts"][0][2]; } if(newDate.year) { @@ -1495,7 +1502,7 @@ Zotero.Utilities = { // Need to convert to SQL var date = Zotero.Utilities.lpad(newDate.year, "0", 4); if(newDate.month) { - date += "-"+Zotero.Utilities.lpad(newDate.month+1, "0", 2); + date += "-"+Zotero.Utilities.lpad(newDate.month, "0", 2); if(newDate.day) { date += "-"+Zotero.Utilities.lpad(newDate.day, "0", 2); }