diff --git a/chrome/content/zotero/xpcom/data/dataObject.js b/chrome/content/zotero/xpcom/data/dataObject.js index 661c5aacd..ea883997f 100644 --- a/chrome/content/zotero/xpcom/data/dataObject.js +++ b/chrome/content/zotero/xpcom/data/dataObject.js @@ -569,9 +569,15 @@ Zotero.DataObject.prototype._recoverFromSaveError = Zotero.Promise.coroutine(fun }); Zotero.DataObject.prototype._initSave = Zotero.Promise.coroutine(function* (env) { + if (!this.libraryID) { + throw new Error("libraryID must be set before saving " + this._objectType); + } + env.isNew = !this.id; - if (!env.options.skipEditCheck) this.editCheck(); + if (!env.options.skipEditCheck) { + this.editCheck(); + } if (!this.hasChanged()) { Zotero.debug(this._ObjectType + ' ' + this.id + ' has not changed', 4); diff --git a/chrome/content/zotero/xpcom/search.js b/chrome/content/zotero/xpcom/search.js index 76c17bd2b..b5ff008c9 100644 --- a/chrome/content/zotero/xpcom/search.js +++ b/chrome/content/zotero/xpcom/search.js @@ -172,7 +172,7 @@ Zotero.Search.prototype.loadFromRow = function (row) { Zotero.Search.prototype._initSave = Zotero.Promise.coroutine(function* (env) { if (!this.name) { - throw('Name not provided for saved search'); + throw new Error('Name not provided for saved search'); } return Zotero.Search._super.prototype._initSave.apply(this, arguments); @@ -199,7 +199,6 @@ Zotero.Search.prototype._saveData = Zotero.Promise.coroutine(function* (env) { var sqlValues = [ searchID ? { int: searchID } : null, { string: this.name }, - Zotero.DB.transactionDateTime, this.libraryID, key, this.version ? this.version : 0, @@ -478,14 +477,14 @@ Zotero.Search.prototype.getCondition = function(searchConditionID){ /* - * Returns a multidimensional array of conditions/operator/value sets - * used in the search, indexed by searchConditionID + * Returns an object of conditions/operator/value sets used in the search, + * indexed by searchConditionID */ Zotero.Search.prototype.getConditions = function(){ this._requireData('conditions'); - var conditions = []; - for (var id in this._conditions) { - var condition = this._conditions[id]; + var conditions = {}; + for (let id in this._conditions) { + let condition = this._conditions[id]; conditions[id] = { id: id, condition: condition.condition, @@ -2340,7 +2339,7 @@ Zotero.SearchConditions = new function(){ } if (!_conditions[condition]){ - throw ("Invalid condition '" + condition + "' in hasOperator()"); + throw new Error("Invalid condition '" + condition + "' in hasOperator()"); } if (!operator && typeof _conditions[condition]['operators'] == 'undefined'){ diff --git a/test/content/support.js b/test/content/support.js index 2ef920f58..16f6656d4 100644 --- a/test/content/support.js +++ b/test/content/support.js @@ -114,6 +114,13 @@ function waitForCallback(cb, interval, timeout) { return deferred.promise; } +/** + * Return a promise for the error thrown by a promise, or false if none + */ +function getPromiseError(promise) { + return promise.thenReturn(false).catch(e => e); +} + /** * Ensures that the PDF tools are installed, or installs them if not. * Returns a promise. diff --git a/test/tests/searchTests.js b/test/tests/searchTests.js new file mode 100644 index 000000000..c19185149 --- /dev/null +++ b/test/tests/searchTests.js @@ -0,0 +1,47 @@ +describe("Zotero.Search", function() { + describe("#save()", function () { + it("should fail without a libraryID", function* () { + var s = new Zotero.Search; + s.name = "Test"; + s.addCondition('title', 'is', 'test'); + var e = yield getPromiseError(s.save()); + assert.ok(e); + assert.equal(e.constructor.name, Error.prototype.constructor.name); // TEMP: Error mismatch + assert.equal(e.message, "libraryID must be set before saving search"); + }); + + it("should fail without a name", function* () { + var s = new Zotero.Search; + s.libraryID = Zotero.Libraries.userLibraryID; + s.addCondition('title', 'is', 'test'); + var e = yield getPromiseError(s.save()); + assert.ok(e); + assert.equal(e.constructor.name, Error.prototype.constructor.name); // TEMP: Error mismatch + assert.equal(e.message, "Name not provided for saved search"); + }); + + it("should save a new search", function* () { + // Save search + var s = new Zotero.Search; + s.libraryID = Zotero.Libraries.userLibraryID; + s.name = "Test"; + s.addCondition('title', 'is', 'test'); + var id = yield s.save(); + assert.typeOf(id, 'number'); + + // Check saved search + s = yield Zotero.Searches.getAsync(id); + assert.ok(s); + assert.instanceOf(s, Zotero.Search); + assert.equal(s.name, "Test"); + yield s.loadConditions(); + var conditions = s.getConditions(); + assert.lengthOf(Object.keys(conditions), 1); + assert.property(conditions, "1"); // searchConditionIDs start at 1 + var condition = conditions[1]; + assert.propertyVal(condition, 'condition', 'title') + assert.propertyVal(condition, 'operator', 'is') + assert.propertyVal(condition, 'value', 'test') + }); + }); +});