www

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

searchTest.js (15597B)


      1 describe("Zotero.Search", function() {
      2 	describe("#addCondition()", function () {
      3 		it("should convert old-style 'collection' condition value", function* () {
      4 			var col = yield createDataObject('collection');
      5 			var item = yield createDataObject('item', { collections: [col.id] });
      6 			
      7 			var s = new Zotero.Search();
      8 			s.libraryID = item.libraryID;
      9 			s.name = "Test";
     10 			s.addCondition('collection', 'is', '0_' + col.key);
     11 			var matches = yield s.search();
     12 			assert.sameMembers(matches, [item.id]);
     13 		});
     14 	});
     15 	
     16 	// This is for Zotero.Search._loadConditions()
     17 	describe("Loading", function () {
     18 		it("should convert old-style 'collection' condition value", function* () {
     19 			var col = yield createDataObject('collection');
     20 			var item = yield createDataObject('item', { collections: [col.id] });
     21 			
     22 			var s = new Zotero.Search();
     23 			s.libraryID = item.libraryID;
     24 			s.name = "Test";
     25 			s.addCondition('collection', 'is', col.key);
     26 			yield s.saveTx();
     27 			yield Zotero.DB.queryAsync(
     28 				"UPDATE savedSearchConditions SET value=? WHERE savedSearchID=? AND condition=?",
     29 				["0_" + col.key, s.id, 'collection']
     30 			);
     31 			yield s.reload(['conditions'], true);
     32 			var matches = yield s.search();
     33 			assert.sameMembers(matches, [item.id]);
     34 		});
     35 	});
     36 	
     37 	
     38 	describe("#save()", function () {
     39 		it("should fail without a name", function* () {
     40 			var s = new Zotero.Search;
     41 			s.addCondition('title', 'is', 'test');
     42 			var e = yield getPromiseError(s.saveTx());
     43 			assert.ok(e);
     44 			assert.equal(e.constructor.name, Error.prototype.constructor.name); // TEMP: Error mismatch
     45 			assert.equal(e.message, "Name not provided for saved search");
     46 		});
     47 		
     48 		it("should save a new search", function* () {
     49 			// Save search
     50 			var s = new Zotero.Search;
     51 			s.name = "Test";
     52 			s.addCondition('title', 'is', 'test');
     53 			var id = yield s.saveTx();
     54 			assert.typeOf(id, 'number');
     55 			
     56 			// Check saved search
     57 			s = Zotero.Searches.get(id);
     58 			assert.ok(s);
     59 			assert.instanceOf(s, Zotero.Search);
     60 			assert.equal(s.libraryID, Zotero.Libraries.userLibraryID);
     61 			assert.equal(s.name, "Test");
     62 			var conditions = s.getConditions();
     63 			assert.lengthOf(Object.keys(conditions), 1);
     64 			assert.property(conditions, "0");
     65 			var condition = conditions[0];
     66 			assert.propertyVal(condition, 'condition', 'title')
     67 			assert.propertyVal(condition, 'operator', 'is')
     68 			assert.propertyVal(condition, 'value', 'test')
     69 			assert.propertyVal(condition, 'required', false)
     70 		});
     71 		
     72 		it("should add a condition to an existing search", function* () {
     73 			// Save search
     74 			var s = new Zotero.Search;
     75 			s.libraryID = Zotero.Libraries.userLibraryID;
     76 			s.name = "Test";
     77 			s.addCondition('title', 'is', 'test');
     78 			var id = yield s.saveTx();
     79 			assert.typeOf(id, 'number');
     80 			
     81 			// Add condition
     82 			s = yield Zotero.Searches.getAsync(id);
     83 			s.addCondition('title', 'contains', 'foo');
     84 			var saved = yield s.saveTx();
     85 			assert.isTrue(saved);
     86 			
     87 			// Check saved search
     88 			s = yield Zotero.Searches.getAsync(id);
     89 			var conditions = s.getConditions();
     90 			assert.lengthOf(Object.keys(conditions), 2);
     91 		});
     92 		
     93 		it("should remove a condition from an existing search", function* () {
     94 			// Save search
     95 			var s = new Zotero.Search;
     96 			s.libraryID = Zotero.Libraries.userLibraryID;
     97 			s.name = "Test";
     98 			s.addCondition('title', 'is', 'test');
     99 			s.addCondition('title', 'contains', 'foo');
    100 			var id = yield s.saveTx();
    101 			assert.typeOf(id, 'number');
    102 			
    103 			// Remove condition
    104 			s = yield Zotero.Searches.getAsync(id);
    105 			s.removeCondition(0);
    106 			var saved = yield s.saveTx();
    107 			assert.isTrue(saved);
    108 			
    109 			// Check saved search
    110 			s = yield Zotero.Searches.getAsync(id);
    111 			var conditions = s.getConditions();
    112 			assert.lengthOf(Object.keys(conditions), 1);
    113 			assert.property(conditions, "0");
    114 			assert.propertyVal(conditions[0], 'value', 'foo')
    115 		});
    116 	});
    117 
    118 	describe("#search()", function () {
    119 		var win;
    120 		var userLibraryID;
    121 		var fooItem;
    122 		var foobarItem;
    123 		var fooItemGroup;
    124 		var foobarItemGroup;
    125 
    126 		before(function* () {
    127 			// Hidden browser, which requires a browser window, needed for charset detection
    128 			// (until we figure out a better way)
    129 			win = yield loadBrowserWindow();
    130 			fooItem = yield importFileAttachment("search/foo.html");
    131 			foobarItem = yield importFileAttachment("search/foobar.html");
    132 			userLibraryID = fooItem.libraryID;
    133 			
    134 			let group = yield getGroup();
    135 			fooItemGroup = yield importFileAttachment("search/foo.html", { libraryID: group.libraryID });
    136 			foobarItemGroup = yield importFileAttachment("search/foobar.html", { libraryID: group.libraryID });
    137 		});
    138 
    139 		after(function* () {
    140 			if (win) {
    141 				win.close();
    142 			}
    143 			yield fooItem.eraseTx();
    144 			yield foobarItem.eraseTx();
    145 			yield fooItemGroup.eraseTx();
    146 			yield foobarItemGroup.eraseTx();
    147 		});
    148 		
    149 		describe("Conditions", function () {
    150 			describe("collection", function () {
    151 				it("should find item in collection", function* () {
    152 					var col = yield createDataObject('collection');
    153 					var item = yield createDataObject('item', { collections: [col.id] });
    154 					
    155 					var s = new Zotero.Search();
    156 					s.libraryID = item.libraryID;
    157 					s.addCondition('collection', 'is', col.key);
    158 					var matches = yield s.search();
    159 					assert.sameMembers(matches, [item.id]);
    160 				});
    161 				
    162 				it("should find items not in collection", function* () {
    163 					var col = yield createDataObject('collection');
    164 					var item = yield createDataObject('item', { collections: [col.id] });
    165 					
    166 					var s = new Zotero.Search();
    167 					s.libraryID = item.libraryID;
    168 					s.addCondition('collection', 'isNot', col.key);
    169 					var matches = yield s.search();
    170 					assert.notInclude(matches, item.id);
    171 				});
    172 				
    173 				it("shouldn't find item in collection with no items", function* () {
    174 					var col = yield createDataObject('collection');
    175 					var item = yield createDataObject('item');
    176 					
    177 					var s = new Zotero.Search();
    178 					s.libraryID = item.libraryID;
    179 					s.addCondition('collection', 'is', col.key);
    180 					var matches = yield s.search();
    181 					assert.lengthOf(matches, 0);
    182 				});
    183 				
    184 				it("should find item in subcollection in recursive mode", function* () {
    185 					var col1 = yield createDataObject('collection');
    186 					var col2 = yield createDataObject('collection', { parentID: col1.id });
    187 					var item = yield createDataObject('item', { collections: [col2.id] });
    188 					
    189 					var s = new Zotero.Search();
    190 					s.libraryID = item.libraryID;
    191 					s.addCondition('collection', 'is', col1.key);
    192 					s.addCondition('recursive', 'true');
    193 					var matches = yield s.search();
    194 					assert.sameMembers(matches, [item.id]);
    195 				});
    196 			});
    197 			
    198 			describe("fileTypeID", function () {
    199 				it("should search by attachment file type", function* () {
    200 					let s = new Zotero.Search();
    201 					s.libraryID = userLibraryID;
    202 					s.addCondition('fileTypeID', 'is', Zotero.FileTypes.getID('webpage'));
    203 					let matches = yield s.search();
    204 					assert.sameMembers(matches, [fooItem.id, foobarItem.id]);
    205 				});
    206 			});
    207 			
    208 			describe("fulltextContent", function () {
    209 				it("should find text in HTML files", function* () {
    210 					var s = new Zotero.Search();
    211 					s.libraryID = userLibraryID;
    212 					s.addCondition('fulltextContent', 'contains', 'foo bar');
    213 					var matches = yield s.search();
    214 					assert.sameMembers(matches, [foobarItem.id]);
    215 				});
    216 				
    217 				it("should work in subsearch", function* () {
    218 					var s = new Zotero.Search();
    219 					s.libraryID = userLibraryID;
    220 					s.addCondition('fulltextContent', 'contains', 'foo bar');
    221 					
    222 					var s2 = new Zotero.Search();
    223 					s2.setScope(s);
    224 					s2.addCondition('title', 'contains', 'foobar');
    225 					var matches = yield s2.search();
    226 					assert.sameMembers(matches, [foobarItem.id]);
    227 				});
    228 				
    229 				it("should find matching item with joinMode=ANY and non-matching other condition", function* () {
    230 					var s = new Zotero.Search();
    231 					s.libraryID = userLibraryID;
    232 					s.addCondition('joinMode', 'any');
    233 					s.addCondition('fulltextContent', 'contains', 'foo bar');
    234 					s.addCondition('title', 'contains', 'nomatch');
    235 					var matches = yield s.search();
    236 					assert.sameMembers(matches, [foobarItem.id]);
    237 				});
    238 				
    239 				it("should find matching items in regexp mode with joinMode=ANY with matching other condition", function* () {
    240 					var s = new Zotero.Search();
    241 					s.libraryID = userLibraryID;
    242 					s.addCondition('joinMode', 'any');
    243 					s.addCondition('fulltextContent/regexp', 'contains', 'foo.+bar');
    244 					s.addCondition('title', 'is', fooItem.getField('title'));
    245 					var matches = yield s.search();
    246 					assert.sameMembers(matches, [fooItem.id, foobarItem.id]);
    247 				});
    248 				
    249 				it("should find matching item in regexp mode with joinMode=ANY and non-matching other condition", function* () {
    250 					var s = new Zotero.Search();
    251 					s.libraryID = userLibraryID;
    252 					s.addCondition('joinMode', 'any');
    253 					s.addCondition('fulltextContent/regexp', 'contains', 'foo.+bar');
    254 					s.addCondition('title', 'contains', 'nomatch');
    255 					var matches = yield s.search();
    256 					assert.sameMembers(matches, [foobarItem.id]);
    257 				});
    258 				
    259 				it("should find item matching other condition in regexp mode when joinMode=ANY", function* () {
    260 					var s = new Zotero.Search();
    261 					s.libraryID = userLibraryID;
    262 					s.addCondition('joinMode', 'any');
    263 					s.addCondition('fulltextContent/regexp', 'contains', 'nomatch');
    264 					s.addCondition('title', 'is', foobarItem.getField('title'));
    265 					var matches = yield s.search();
    266 					assert.sameMembers(matches, [foobarItem.id]);
    267 				});
    268 				
    269 				it("should find matching item in regexp mode with joinMode=ANY and recursive mode flag", function* () {
    270 					var s = new Zotero.Search();
    271 					s.libraryID = userLibraryID;
    272 					s.addCondition('joinMode', 'any');
    273 					s.addCondition('fulltextContent/regexp', 'contains', 'foo.+bar');
    274 					s.addCondition('recursive', 'true');
    275 					var matches = yield s.search();
    276 					assert.sameMembers(matches, [foobarItem.id]);
    277 				});
    278 			});
    279 			
    280 			describe("fulltextWord", function () {
    281 				it("should return matches with full-text conditions", function* () {
    282 					let s = new Zotero.Search();
    283 					s.libraryID = userLibraryID;
    284 					s.addCondition('fulltextWord', 'contains', 'foo');
    285 					let matches = yield s.search();
    286 					assert.lengthOf(matches, 2);
    287 					assert.sameMembers(matches, [fooItem.id, foobarItem.id]);
    288 				});
    289 		
    290 				it("should not return non-matches with full-text conditions", function* () {
    291 					let s = new Zotero.Search();
    292 					s.libraryID = userLibraryID;
    293 					s.addCondition('fulltextWord', 'contains', 'baz');
    294 					let matches = yield s.search();
    295 					assert.lengthOf(matches, 0);
    296 				});
    297 		
    298 				it("should return matches for full-text conditions in ALL mode", function* () {
    299 					let s = new Zotero.Search();
    300 					s.libraryID = userLibraryID;
    301 					s.addCondition('joinMode', 'all');
    302 					s.addCondition('fulltextWord', 'contains', 'foo');
    303 					s.addCondition('fulltextWord', 'contains', 'bar');
    304 					let matches = yield s.search();
    305 					assert.deepEqual(matches, [foobarItem.id]);
    306 				});
    307 		
    308 				it("should not return non-matches for full-text conditions in ALL mode", function* () {
    309 					let s = new Zotero.Search();
    310 					s.libraryID = userLibraryID;
    311 					s.addCondition('joinMode', 'all');
    312 					s.addCondition('fulltextWord', 'contains', 'mjktkiuewf');
    313 					s.addCondition('fulltextWord', 'contains', 'zijajkvudk');
    314 					let matches = yield s.search();
    315 					assert.lengthOf(matches, 0);
    316 				});
    317 		
    318 				it("should return a match that satisfies only one of two full-text condition in ANY mode", function* () {
    319 					let s = new Zotero.Search();
    320 					s.libraryID = userLibraryID;
    321 					s.addCondition('joinMode', 'any');
    322 					s.addCondition('fulltextWord', 'contains', 'bar');
    323 					s.addCondition('fulltextWord', 'contains', 'baz');
    324 					let matches = yield s.search();
    325 					assert.deepEqual(matches, [foobarItem.id]);
    326 				});
    327 			});
    328 			
    329 			describe("key", function () {
    330 				it("should allow more than max bound parameters", function* () {
    331 					let s = new Zotero.Search();
    332 					let max = Zotero.DB.MAX_BOUND_PARAMETERS + 100;
    333 					for (let i = 0; i < max; i++) {
    334 						s.addCondition('key', 'is', Zotero.DataObjectUtilities.generateKey());
    335 					}
    336 					yield s.search();
    337 				});
    338 			});
    339 			
    340 			describe("savedSearch", function () {
    341 				it("should return items in the saved search", function* () {
    342 					var search = yield createDataObject('search');
    343 					var itemTitle = search.getConditions()[0].value;
    344 					var item = yield createDataObject('item', { title: itemTitle })
    345 					
    346 					var s = new Zotero.Search;
    347 					s.libraryID = Zotero.Libraries.userLibraryID;
    348 					s.addCondition('savedSearch', 'is', search.key);
    349 					var matches = yield s.search();
    350 					assert.deepEqual(matches, [item.id]);
    351 				});
    352 				
    353 				it("should return items not in the saved search for isNot operator", function* () {
    354 					var search = yield createDataObject('search');
    355 					var itemTitle = search.getConditions()[0].value;
    356 					var item = yield createDataObject('item', { title: itemTitle })
    357 					
    358 					var s = new Zotero.Search;
    359 					s.libraryID = Zotero.Libraries.userLibraryID;
    360 					s.addCondition('savedSearch', 'isNot', search.key);
    361 					var matches = yield s.search();
    362 					assert.notInclude(matches, item.id);
    363 				});
    364 			});
    365 			
    366 			describe("unfiled", function () {
    367 				it("shouldn't include items in My Publications", function* () {
    368 					var item1 = yield createDataObject('item');
    369 					var item2 = yield createDataObject('item', { inPublications: true });
    370 					
    371 					var s = new Zotero.Search;
    372 					s.libraryID = Zotero.Libraries.userLibraryID;
    373 					s.addCondition('unfiled', 'true');
    374 					var matches = yield s.search();
    375 					assert.include(matches, item1.id);
    376 					assert.notInclude(matches, item2.id);
    377 				});
    378 			});
    379 		});
    380 	});
    381 	
    382 	describe("#toJSON()", function () {
    383 		it("should output all data", function* () {
    384 			let s = new Zotero.Search();
    385 			s.name = "Test";
    386 			s.addCondition('joinMode', 'any');
    387 			s.addCondition('fulltextContent/regexp', 'contains', 's.+');
    388 			let json = s.toJSON();
    389 			assert.equal(json.name, "Test");
    390 			
    391 			assert.lengthOf(json.conditions, 2);
    392 			
    393 			assert.equal(json.conditions[0].condition, 'joinMode');
    394 			assert.equal(json.conditions[0].operator, 'any');
    395 			// TODO: Change to 'is' + 'any'?
    396 			assert.strictEqual(json.conditions[0].value, '');
    397 			assert.notProperty(json.conditions[0], 'id');
    398 			assert.notProperty(json.conditions[0], 'required');
    399 			assert.notProperty(json.conditions[0], 'mode');
    400 			
    401 			assert.equal(json.conditions[1].condition, 'fulltextContent/regexp');
    402 			assert.equal(json.conditions[1].operator, 'contains');
    403 			assert.equal(json.conditions[1].value, 's.+');
    404 			assert.notProperty(json.conditions[1], 'mode');
    405 		});
    406 	});
    407 	
    408 	describe("#fromJSON()", function () {
    409 		it("should update all data", function* () {
    410 			let s = new Zotero.Search();
    411 			s.name = "Test";
    412 			s.addCondition('joinMode', 'any');
    413 			s.addCondition('title', 'isNot', 'foo');
    414 			let json = s.toJSON();
    415 			json.name = "Test 2";
    416 			json.conditions = [
    417 				{
    418 					condition: 'title',
    419 					operator: 'contains',
    420 					value: 'foo'
    421 				},
    422 				{
    423 					condition: 'year',
    424 					operator: 'is',
    425 					value: '2016'
    426 				}
    427 			];
    428 			s.fromJSON(json);
    429 			assert.equal(s.name, "Test 2");
    430 			var conditions = s.getConditions();
    431 			assert.lengthOf(Object.keys(conditions), 2);
    432 			assert.equal(conditions["0"].condition, 'title');
    433 			assert.equal(conditions["0"].operator, 'contains');
    434 			assert.equal(conditions["0"].value, 'foo');
    435 			assert.equal(conditions["1"].condition, 'year');
    436 			assert.equal(conditions["1"].operator, 'is');
    437 			assert.equal(conditions["1"].value, '2016');
    438 		});
    439 	});
    440 });