feedItemTest.js (9987B)
1 describe("Zotero.FeedItem", function () { 2 let feed, libraryID; 3 before(function* () { 4 feed = yield createFeed({ name: 'Test ' + Zotero.randomString(), url: 'http://' + Zotero.randomString() + '.com/' }); 5 yield feed.saveTx(); 6 libraryID = feed.libraryID; 7 }); 8 after(function() { 9 return clearFeeds(); 10 }); 11 12 it("should be an instance of Zotero.Item", function() { 13 assert.instanceOf(new Zotero.FeedItem(), Zotero.Item); 14 }); 15 describe("#libraryID", function() { 16 it("should reference a feed", function() { 17 let feedItem = new Zotero.FeedItem(); 18 assert.doesNotThrow(function() {feedItem.libraryID = feed.libraryID}); 19 assert.throws(function() {feedItem.libraryID = Zotero.Libraries.userLibraryID}, /^libraryID must reference a feed$/); 20 }); 21 }); 22 describe("#constructor()", function* () { 23 it("should accept required fields as arguments", function* () { 24 let guid = Zotero.randomString(); 25 let feedItem = new Zotero.FeedItem(); 26 yield assert.isRejected(feedItem.saveTx()); 27 28 feedItem = new Zotero.FeedItem('book', { guid }); 29 feedItem.libraryID = libraryID; 30 yield assert.isFulfilled(feedItem.saveTx()); 31 32 assert.equal(feedItem.itemTypeID, Zotero.ItemTypes.getID('book')); 33 assert.equal(feedItem.guid, guid); 34 assert.equal(feedItem.libraryID, libraryID); 35 }); 36 }); 37 describe("#isFeedItem", function() { 38 it("should be true", function() { 39 let feedItem = new Zotero.FeedItem(); 40 assert.isTrue(feedItem.isFeedItem); 41 }); 42 it("should be falsy for regular item", function() { 43 let item = new Zotero.Item(); 44 assert.notOk(item.isFeedItem); 45 }) 46 }); 47 describe("#guid", function() { 48 it("should not be settable to a non-string value", function() { 49 let feedItem = new Zotero.FeedItem(); 50 assert.throws(() => feedItem.guid = 1); 51 }); 52 it("should be settable to any string", function() { 53 let feedItem = new Zotero.FeedItem(); 54 feedItem.guid = 'foo'; 55 assert.equal(feedItem.guid, 'foo'); 56 }); 57 it("should not be possible to change guid after saving item", function* () { 58 let feedItem = yield createDataObject('feedItem', { libraryID }); 59 assert.throws(() => feedItem.guid = 'bar'); 60 }); 61 }); 62 describe("#isRead", function() { 63 it("should be false by default", function* () { 64 let feedItem = yield createDataObject('feedItem', { libraryID }); 65 assert.isFalse(feedItem.isRead); 66 }); 67 it("should be settable and persist after saving", function* () { 68 this.timeout(5000); 69 let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() }); 70 feedItem.libraryID = feed.libraryID; 71 assert.isFalse(feedItem.isRead); 72 73 let expectedTimestamp = Date.now(); 74 feedItem.isRead = true; 75 assert.isTrue(feedItem.isRead); 76 let readTime = Zotero.Date.sqlToDate(feedItem._feedItemReadTime, true).getTime(); 77 assert.closeTo(readTime, expectedTimestamp, 2000, 'sets the read timestamp to current time'); 78 79 feedItem.isRead = false; 80 assert.isFalse(feedItem.isRead); 81 assert.notOk(feedItem._feedItemReadTime); 82 83 expectedTimestamp = Date.now(); 84 feedItem.isRead = true; 85 yield Zotero.Promise.delay(2001); 86 yield feedItem.saveTx(); 87 88 readTime = yield Zotero.DB.valueQueryAsync('SELECT readTime FROM feedItems WHERE itemID=?', feedItem.id); 89 readTime = Zotero.Date.sqlToDate(readTime, true).getTime(); 90 assert.closeTo(readTime, expectedTimestamp, 2000, 'read timestamp is correct in the DB'); 91 }); 92 }); 93 describe("#fromJSON()", function() { 94 it("should attempt to parse non ISO-8601 dates", function* () { 95 Zotero.locale = 'en-US'; 96 var data = [ 97 { 98 itemType: "journalArticle", 99 date: "2015-06-07 20:56:00" // sql 100 }, 101 { 102 itemType: "journalArticle", 103 date: "Mon, 13 Jun 2016 06:25:57 EDT" // HTTP 104 }, 105 { 106 itemType: "journalArticle", 107 date: "18-20 June 2015" // parsed by `strToDate` 108 }, 109 { 110 itemType: "journalArticle", 111 date: "06/07/2015" // american format also parsed by `strToDate` 112 } 113 ]; 114 var expectedDates = [ 115 '2015-06-07 20:56:00', 116 '2016-06-13 10:25:57', 117 '2015-06-18', 118 '2015-06-07' 119 ]; 120 for (let i = 0; i < data.length; i++) { 121 var item = new Zotero.FeedItem; 122 item.fromJSON(data[i]); 123 assert.strictEqual(item.getField('date'), expectedDates[i]); 124 } 125 }) 126 }); 127 describe("#save()", function() { 128 it("should require feed being set", function* () { 129 let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() }); 130 // Defaults to user library ID 131 yield assert.isRejected(feedItem.saveTx(), /^Cannot add /); 132 }); 133 it("should require GUID being set", function* () { 134 let feedItem = new Zotero.FeedItem('book'); 135 feedItem.libraryID = feed.libraryID; 136 yield assert.isRejected(feedItem.saveTx(), /^GUID must be set before saving FeedItem$/); 137 }); 138 it("should require a unique GUID", function* () { 139 let guid = Zotero.randomString(); 140 let feedItem1 = yield createDataObject('feedItem', { libraryID, guid }); 141 142 let feedItem2 = createUnsavedDataObject('feedItem', { libraryID, guid }); 143 yield assert.isRejected(feedItem2.saveTx()); 144 145 // But we should be able to save it after deleting the original feed 146 yield feedItem1.eraseTx(); 147 yield assert.isFulfilled(feedItem2.saveTx()); 148 }); 149 it("should require item type being set", function* () { 150 let feedItem = new Zotero.FeedItem(null, { guid: Zotero.randomString() }); 151 feedItem.libraryID = feed.libraryID; 152 yield assert.isRejected(feedItem.saveTx(), /^Item type must be set before saving$/); 153 }); 154 it("should save feed item", function* () { 155 let guid = Zotero.randomString(); 156 let feedItem = createUnsavedDataObject('feedItem', { libraryID, guid }); 157 yield assert.isFulfilled(feedItem.saveTx()); 158 159 feedItem = yield Zotero.FeedItems.getAsync(feedItem.id); 160 assert.ok(feedItem); 161 assert.equal(feedItem.guid, guid); 162 }); 163 it.skip("should support saving feed items with all types and fields", function* () { 164 this.timeout(60000); 165 let allTypesAndFields = loadSampleData('allTypesAndFields'), 166 feedItems = []; 167 for (let type in allTypesAndFields) { 168 let feedItem = new Zotero.FeedItem(null, type, feed.libraryID); 169 feedItem.fromJSON(allTypesAndFields[type]); 170 171 yield feedItem.saveTx(); 172 173 feedItems.push(feedItem); 174 } 175 176 let feedItemsJSON = {}; 177 for (let i=0; i<feedItems.length; i++) { 178 let feed = feedItems[i]; 179 feedItemsJSON[feed.guid] = feed.toJSON(); 180 } 181 182 assert.deepEqual(feedItemsJSON, allTypesAndFields); 183 }); 184 it("should allow saving after editing data", function* () { 185 let feedItem = yield createDataObject('feedItem', { libraryID }); 186 187 feedItem.setField('title', 'bar'); 188 yield assert.isFulfilled(feedItem.saveTx()); 189 assert.equal(feedItem.getField('title'), 'bar'); 190 }); 191 }); 192 describe("#erase()", function() { 193 it("should erase an existing feed item", function* () { 194 let feedItem = yield createDataObject('feedItem', { libraryID }); 195 196 yield feedItem.eraseTx(); 197 assert.isFalse(yield Zotero.FeedItems.getAsync(feedItem.id)); 198 199 //yield assert.isRejected(feedItem.EraseTx(), "does not allow erasing twice"); 200 }); 201 }); 202 203 describe("#toggleRead()", function() { 204 it('should toggle state', function* () { 205 let item = yield createDataObject('feedItem', { libraryID }); 206 item.isRead = false; 207 yield item.saveTx(); 208 209 yield item.toggleRead(); 210 assert.isTrue(item.isRead, "item is toggled to read state"); 211 }); 212 it('should save if specified state is different from current', function* (){ 213 let item = yield createDataObject('feedItem', { libraryID }); 214 item.isRead = false; 215 yield item.saveTx(); 216 sinon.spy(item, 'save'); 217 218 yield item.toggleRead(true); 219 assert.isTrue(item.save.called, "item was saved on toggle read"); 220 221 item.save.reset(); 222 223 yield item.toggleRead(true); 224 assert.isFalse(item.save.called, "item was not saved on toggle read to same state"); 225 }); 226 }); 227 228 describe('#translate()', function() { 229 var win; 230 231 before(function* () { 232 // TEMP: Fix for slow translator initialization on Linux/Travis 233 this.timeout(20000); 234 yield Zotero.Translators.init(); 235 236 // Needs an open window to be able to create a hidden window for translation 237 win = yield loadBrowserWindow(); 238 }); 239 240 after(function () { 241 win.close() 242 }); 243 244 it('should translate and save items', function* () { 245 var feedItem = yield createDataObject('feedItem', {libraryID}); 246 var url = getTestDataUrl('metadata/journalArticle-single.html'); 247 feedItem.setField('url', url); 248 yield feedItem.saveTx(); 249 250 yield feedItem.translate(); 251 252 assert.equal(feedItem.getField('title'), 'Scarcity or Abundance? Preserving the Past in a Digital Era'); 253 }); 254 it('should translate and save items to corresponding library and collection', function* () { 255 let group = yield createGroup(); 256 let collection = yield createDataObject('collection', {libraryID: group.libraryID}); 257 258 var feedItem = yield createDataObject('feedItem', {libraryID}); 259 var url = getTestDataUrl('metadata/journalArticle-single.html'); 260 feedItem.setField('url', url); 261 yield feedItem.saveTx(); 262 263 yield feedItem.translate(group.libraryID, collection.id); 264 265 let item = collection.getChildItems(false, false)[0]; 266 267 assert.equal(item.getField('title'), 'Scarcity or Abundance? Preserving the Past in a Digital Era'); 268 }); 269 it('should clone the item to corresponding library and collection if no translators available', function* () { 270 let group = yield createGroup(); 271 let collection = yield createDataObject('collection', {libraryID: group.libraryID}); 272 273 var feedItem = yield createDataObject('feedItem', {libraryID, title: 'test'}); 274 var url = getTestDataUrl('test.html'); 275 feedItem.setField('url', url); 276 yield feedItem.saveTx(); 277 278 yield feedItem.translate(group.libraryID, collection.id); 279 280 let item = collection.getChildItems(false, false)[0]; 281 282 assert.equal(item.getField('title'), 'test'); 283 }); 284 }); 285 });