tagSelectorTest.js (12803B)
1 "use strict"; 2 3 describe("Tag Selector", function () { 4 var win, doc, collectionsView, tagSelector; 5 6 var clearTagColors = Zotero.Promise.coroutine(function* (libraryID) { 7 var tagColors = Zotero.Tags.getColors(libraryID); 8 for (let name of tagColors.keys()) { 9 yield Zotero.Tags.setColor(libraryID, name, false); 10 } 11 }); 12 13 function getColoredTags() { 14 var tagsBox = tagSelector.id('tags-box'); 15 var elems = tagsBox.getElementsByTagName('button'); 16 var names = []; 17 for (let i = 0; i < elems.length; i++) { 18 if (elems[i].style.order < 0) { 19 names.push(elems[i].textContent); 20 } 21 } 22 return names; 23 } 24 25 function getRegularTags() { 26 var tagsBox = tagSelector.id('tags-box'); 27 var elems = tagsBox.getElementsByTagName('button'); 28 var names = []; 29 for (let i = 0; i < elems.length; i++) { 30 if (elems[i].style.order >= 0 && elems[i].style.display != 'none') { 31 names.push(elems[i].textContent); 32 } 33 } 34 return names; 35 } 36 37 38 before(function* () { 39 win = yield loadZoteroPane(); 40 doc = win.document; 41 collectionsView = win.ZoteroPane.collectionsView; 42 tagSelector = doc.getElementById('zotero-tag-selector'); 43 44 // Wait for things to settle 45 yield Zotero.Promise.delay(100); 46 }); 47 48 beforeEach(function* () { 49 var libraryID = Zotero.Libraries.userLibraryID; 50 yield clearTagColors(libraryID); 51 // Default "Display All Tags in This Library" off 52 tagSelector.filterToScope = true; 53 tagSelector.setSearch(''); 54 yield tagSelector.refresh(true); 55 }) 56 57 after(function () { 58 win.close(); 59 }); 60 61 describe("#setSearch()", function () { 62 it("should filter to tags matching the search", function* () { 63 var collection = yield createDataObject('collection'); 64 var item = createUnsavedDataObject('item', { collections: [collection.id] }); 65 item.setTags(['a', 'b', 'c']); 66 var promise = waitForTagSelector(win); 67 yield item.saveTx(); 68 yield promise; 69 70 var tagsSearch = doc.getElementById('tags-search'); 71 tagsSearch.value = 'a'; 72 tagsSearch.doCommand(); 73 74 var tags = getRegularTags(); 75 assert.sameMembers(tags, ['a']); 76 77 tagsSearch.value = ''; 78 tagsSearch.doCommand(); 79 yield item.eraseTx(); 80 }); 81 }); 82 83 describe("#refresh()", function () { 84 it("should remove tags not on matching items on tag click", function* () { 85 var collection = yield createDataObject('collection'); 86 var item1 = createUnsavedDataObject('item', { collections: [collection.id] }); 87 item1.setTags([ 88 { 89 tag: "A" 90 } 91 ]); 92 var item2 = createUnsavedDataObject('item', { collections: [collection.id] }); 93 item2.setTags([ 94 { 95 tag: "A" 96 }, 97 { 98 tag: "B" 99 } 100 ]); 101 var item3 = createUnsavedDataObject('item', { collections: [collection.id] }); 102 item3.setTags([ 103 { 104 tag: "C" 105 } 106 ]); 107 var promise = waitForTagSelector(win); 108 yield Zotero.DB.executeTransaction(function* () { 109 yield item1.save(); 110 yield item2.save(); 111 yield item3.save(); 112 }); 113 yield promise; 114 115 var buttons = tagSelector.id('tags-box').getElementsByTagName('button'); 116 var spy = sinon.spy(win.ZoteroPane, "updateTagFilter"); 117 buttons[0].click(); 118 119 yield spy.returnValues[0]; 120 121 spy.restore(); 122 123 var tags = getRegularTags(); 124 assert.sameMembers(tags, ['A', 'B']); 125 }); 126 }); 127 128 129 describe("#filterToScope", function () { 130 it("should show all tags in library when false", function* () { 131 tagSelector.filterToScope = false; 132 133 var collection = yield createDataObject('collection'); 134 var item1 = createUnsavedDataObject('item'); 135 item1.setTags([ 136 { 137 tag: "A" 138 } 139 ]); 140 var item2 = createUnsavedDataObject('item', { collections: [collection.id] }); 141 item2.setTags([ 142 { 143 tag: "B" 144 } 145 ]); 146 var item3 = createUnsavedDataObject('item', { collections: [collection.id] }); 147 item3.setTags([ 148 { 149 tag: "C" 150 } 151 ]); 152 var promise = waitForTagSelector(win); 153 yield Zotero.DB.executeTransaction(function* () { 154 yield item1.save(); 155 yield item2.save(); 156 yield item3.save(); 157 }); 158 yield promise; 159 160 var tags = getRegularTags(); 161 assert.sameMembers(tags, ['A', 'B', 'C']); 162 }); 163 }); 164 165 166 describe("#notify()", function () { 167 it("should add a tag when added to an item in the library root", function* () { 168 var promise, tagSelector; 169 170 if (collectionsView.selection.currentIndex != 0) { 171 promise = waitForTagSelector(win); 172 yield collectionsView.selectLibrary(); 173 yield promise; 174 } 175 176 // Add item with tag to library root 177 var item = createUnsavedDataObject('item'); 178 item.setTags([ 179 { 180 tag: 'A' 181 }, 182 { 183 tag: 'B', 184 type: 1 185 } 186 ]); 187 promise = waitForTagSelector(win); 188 yield item.saveTx(); 189 yield promise; 190 191 // Tag selector should have at least one tag 192 assert.isAbove(getRegularTags().length, 1); 193 }); 194 195 it("should add a tag when an item is added in a collection", function* () { 196 var promise, tagSelector; 197 198 // Add collection 199 promise = waitForTagSelector(win); 200 var collection = yield createDataObject('collection'); 201 yield promise; 202 203 // Tag selector should be empty in new collection 204 assert.equal(getRegularTags().length, 0); 205 206 // Add item with tag to collection 207 var item = createUnsavedDataObject('item'); 208 item.setTags([ 209 { 210 tag: 'C' 211 } 212 ]); 213 item.setCollections([collection.id]); 214 promise = waitForTagSelector(win) 215 yield item.saveTx(); 216 yield promise; 217 218 // Tag selector should show the new item's tag 219 assert.equal(getRegularTags().length, 1); 220 }) 221 222 it("should add a tag when an item is added to a collection", function* () { 223 var promise, tagSelector; 224 225 // Add collection 226 promise = waitForTagSelector(win); 227 var collection = yield createDataObject('collection'); 228 yield promise; 229 230 // Tag selector should be empty in new collection 231 assert.equal(getRegularTags().length, 0); 232 233 // Add item with tag to library root 234 var item = createUnsavedDataObject('item'); 235 item.setTags([ 236 { 237 tag: 'C' 238 } 239 ]); 240 promise = waitForTagSelector(win) 241 yield item.saveTx(); 242 yield promise; 243 244 // Tag selector should still be empty in collection 245 assert.equal(getRegularTags().length, 0); 246 247 item.setCollections([collection.id]); 248 promise = waitForTagSelector(win); 249 yield item.saveTx(); 250 yield promise; 251 252 // Tag selector should show the new item's tag 253 assert.equal(getRegularTags().length, 1); 254 }) 255 256 it("should show a colored tag at the top of the list even when linked to no items", function* () { 257 var libraryID = Zotero.Libraries.userLibraryID; 258 259 var tagElems = tagSelector.id('tags-box').getElementsByTagName('button'); 260 var count = tagElems.length; 261 262 yield Zotero.Tags.setColor(libraryID, "Top", '#AAAAAA'); 263 264 assert.equal(tagElems.length, count + 1); 265 }); 266 267 it("shouldn't re-insert a new tag that matches an existing color", function* () { 268 var libraryID = Zotero.Libraries.userLibraryID; 269 270 /*// Remove all tags in library 271 var tags = yield Zotero.Tags.getAll(libraryID); 272 tags.forEach(function (tag) { 273 var tagID = Zotero.Tags.getID(tag); 274 yield Zotero.Tags.removeFromLibrary(libraryID, tagID); 275 });*/ 276 277 // Add B and A as colored tags without any items 278 yield Zotero.Tags.setColor(libraryID, "B", '#990000'); 279 yield Zotero.Tags.setColor(libraryID, "A", '#CC9933'); 280 281 // Add A to an item to make it a real tag 282 var item = createUnsavedDataObject('item'); 283 item.setTags([ 284 { 285 tag: "A" 286 } 287 ]); 288 var promise = waitForTagSelector(win); 289 yield item.saveTx(); 290 yield promise; 291 292 var tagElems = tagSelector.id('tags-box').getElementsByTagName('button'); 293 294 // Make sure the colored tags are still in the right position 295 var tags = new Map(); 296 for (let i = 0; i < tagElems.length; i++) { 297 tags.set(tagElems[i].textContent, tagElems[i].style.order); 298 } 299 assert.isBelow(parseInt(tags.get("B")), 0); 300 assert.isBelow(parseInt(tags.get("B")), parseInt(tags.get("A"))); 301 }) 302 303 it("should remove a tag when an item is removed from a collection", function* () { 304 // Add collection 305 var promise = waitForTagSelector(win); 306 var collection = yield createDataObject('collection'); 307 yield promise; 308 309 // Add item with tag to collection 310 var item = createUnsavedDataObject('item'); 311 item.setTags([ 312 { 313 tag: 'A' 314 } 315 ]); 316 item.setCollections([collection.id]); 317 promise = waitForTagSelector(win); 318 yield item.saveTx(); 319 yield promise; 320 321 // Tag selector should show the new item's tag 322 assert.equal(getRegularTags().length, 1); 323 324 item.setCollections(); 325 promise = waitForTagSelector(win); 326 yield item.saveTx(); 327 yield promise; 328 329 // Tag selector shouldn't show the removed item's tag 330 assert.equal(getRegularTags().length, 0); 331 }) 332 333 it("should remove a tag when an item in a collection is moved to the trash", function* () { 334 // Add collection 335 var promise = waitForTagSelector(win); 336 var collection = yield createDataObject('collection'); 337 yield promise; 338 339 // Add item with tag to collection 340 var item = createUnsavedDataObject('item'); 341 item.setTags([ 342 { 343 tag: 'A' 344 } 345 ]); 346 item.setCollections([collection.id]); 347 promise = waitForTagSelector(win) 348 yield item.saveTx(); 349 yield promise; 350 351 // Tag selector should show the new item's tag 352 assert.equal(getRegularTags().length, 1); 353 354 // Move item to trash 355 item.deleted = true; 356 promise = waitForTagSelector(win); 357 yield item.saveTx(); 358 yield promise; 359 360 // Tag selector shouldn't show the deleted item's tag 361 assert.equal(getRegularTags().length, 0); 362 }) 363 364 it("should remove a tag when a tag is deleted for a library", function* () { 365 yield selectLibrary(win); 366 367 var item = createUnsavedDataObject('item'); 368 item.setTags([ 369 { 370 tag: 'A' 371 } 372 ]); 373 var promise = waitForTagSelector(win); 374 yield item.saveTx(); 375 yield promise; 376 377 // Tag selector should show the new item's tag 378 assert.include(getRegularTags(), "A"); 379 380 // Remove tag from library 381 promise = waitForTagSelector(win); 382 var dialogPromise = waitForDialog(); 383 yield tagSelector.deleteTag("A"); 384 yield promise; 385 386 // Tag selector shouldn't show the deleted item's tag 387 assert.notInclude(getRegularTags(), "A"); 388 }) 389 }) 390 391 describe("#rename()", function () { 392 it("should rename a tag and update the tag selector", function* () { 393 yield selectLibrary(win); 394 395 var tag = Zotero.Utilities.randomString(); 396 var newTag = Zotero.Utilities.randomString(); 397 var item = createUnsavedDataObject('item'); 398 item.setTags([ 399 { 400 tag: tag 401 } 402 ]); 403 var promise = waitForTagSelector(win); 404 yield item.saveTx(); 405 yield promise; 406 407 promise = waitForTagSelector(win); 408 var promptPromise = waitForWindow("chrome://global/content/commonDialog.xul", function (dialog) { 409 dialog.document.getElementById('loginTextbox').value = newTag; 410 dialog.document.documentElement.acceptDialog(); 411 }) 412 yield tagSelector.rename(tag); 413 yield promise; 414 415 var tags = getRegularTags(); 416 assert.include(tags, newTag); 417 }); 418 419 it("should rename a non-matching colored tag and update the tag selector", function* () { 420 yield selectLibrary(win); 421 422 var oldTag = Zotero.Utilities.randomString(); 423 var newTag = Zotero.Utilities.randomString(); 424 425 var libraryID = Zotero.Libraries.userLibraryID; 426 var promise = waitForTagSelector(win); 427 yield Zotero.Tags.setColor(libraryID, oldTag, "#F3F3F3"); 428 yield promise; 429 430 promise = waitForTagSelector(win); 431 var promptPromise = waitForWindow("chrome://global/content/commonDialog.xul", function (dialog) { 432 dialog.document.getElementById('loginTextbox').value = newTag; 433 dialog.document.documentElement.acceptDialog(); 434 }) 435 yield tagSelector.rename(oldTag); 436 yield promise; 437 438 var tags = getColoredTags(); 439 assert.notInclude(tags, oldTag); 440 assert.include(tags, newTag); 441 }); 442 }) 443 444 describe("#_openColorPickerWindow()", function () { 445 it("should assign a color to a tag", function* () { 446 yield selectLibrary(win); 447 var tag = "b " + Zotero.Utilities.randomString(); 448 var item = createUnsavedDataObject('item'); 449 item.setTags([ 450 { 451 tag: "a" 452 }, 453 { 454 tag: tag 455 } 456 ]); 457 var promise = waitForTagSelector(win); 458 yield item.saveTx(); 459 yield promise; 460 461 462 assert.include(getRegularTags(), "a"); 463 464 var dialogPromise = waitForDialog(false, undefined, 'chrome://zotero/content/tagColorChooser.xul'); 465 var tagSelectorPromise = waitForTagSelector(win); 466 yield tagSelector._openColorPickerWindow(tag); 467 yield dialogPromise; 468 yield tagSelectorPromise; 469 470 assert.include(getColoredTags(), tag); 471 assert.notInclude(getRegularTags(), tag); 472 }) 473 }); 474 })