describe("Zotero.Feeds", function () { after(function* () { yield clearFeeds(); }); describe("#restoreFromJSON", function() { var json = {}; var expiredFeedURL, existingFeedURL; before(function() { sinon.stub(Zotero.Feed.prototype, 'updateFeed').resolves(); }); after(function() { Zotero.Feed.prototype.updateFeed.restore(); }); beforeEach(function* () { yield clearFeeds(); for (let i = 0; i < 2; i++) { let url = "http://" + Zotero.Utilities.randomString(10, 'abcdefgh') + ".com/feed.rss"; json[url] = { url, name: Zotero.Utilities.randomString(), refreshInterval: 5, cleanupAfter: 3, markedAsRead: [] }; if (i == 0) { existingFeedURL = url; yield createFeed({url}); } } expiredFeedURL = (yield createFeed()).url; }); it("restores correctly when merge is true", function* () { let feeds = Zotero.Feeds.getAll(); assert.equal(feeds.length, 2); yield Zotero.Feeds.restoreFromJSON(json, true); feeds = Zotero.Feeds.getAll(); for (let url in json) { let feed = Zotero.Feeds.getByURL(url); assert.ok(feed, "new feed created"); } let expiredFeed = Zotero.Feeds.getByURL(expiredFeedURL); assert.ok(expiredFeed, "does not remove feeds not in JSON"); let existingFeed = Zotero.Feeds.getByURL(existingFeedURL); assert.ok(existingFeed, "does not remove feeds in database and JSON"); }); it("restores correctly when merge is false", function* () { let feeds = Zotero.Feeds.getAll(); assert.equal(feeds.length, 2); yield Zotero.Feeds.restoreFromJSON(json); feeds = Zotero.Feeds.getAll(); for (let url in json) { let feed = Zotero.Feeds.getByURL(url); assert.ok(feed, "new feed created"); } let expiredFeed = Zotero.Feeds.getByURL(expiredFeedURL); assert.notOk(expiredFeed, "removes feeds not in JSON"); let existingFeed = Zotero.Feeds.getByURL(existingFeedURL); assert.ok(existingFeed, "does not remove feeds in database and JSON"); }); }); describe("#haveFeeds()", function() { it("should return false for a DB without feeds", function* () { yield clearFeeds(); assert.isFalse(Zotero.Feeds.haveFeeds(), 'no feeds in empty DB'); let group = yield createGroup(); assert.isFalse(Zotero.Feeds.haveFeeds(), 'no feeds in DB with groups'); }); it("should return true for a DB containing feeds", function* () { let feed = yield createFeed(); assert.isTrue(Zotero.Feeds.haveFeeds()); }); }); describe("#getAll()", function() { it("should return an empty array for a DB without feeds", function* () { yield clearFeeds(); let feeds = Zotero.Feeds.getAll(); assert.lengthOf(feeds, 0, 'no feeds in an empty DB'); let group = yield createGroup(); feeds = Zotero.Feeds.getAll(); assert.lengthOf(feeds, 0, 'no feeds in DB with group libraries'); }); it("should return an array of feeds", function* () { yield clearFeeds(); let feed1 = yield createFeed(); let feed2 = yield createFeed(); let feeds = Zotero.Feeds.getAll(); assert.lengthOf(feeds, 2); assert.sameMembers(feeds, [feed1, feed2]); }); }); describe('#getByURL', function() { it("should return a feed by url", function* () { let url = 'http://' + Zotero.Utilities.randomString(10, 'abcdefg') + '.com/feed.rss'; yield createFeed({url}); let feed = Zotero.Feeds.getByURL(url); assert.ok(feed); assert.equal(feed.url, url); }); it("should return undefined if feed does not exist", function* () { var feed; assert.doesNotThrow(function() { feed = Zotero.Feeds.getByURL('doesnotexist'); }); assert.isUndefined(feed); }); }); describe('#updateFeeds', function() { var freshFeed, recentFeed, oldFeed; var _updateFeed; before(function* () { yield clearFeeds(); sinon.stub(Zotero.Feeds, 'scheduleNextFeedCheck'); _updateFeed = sinon.stub(Zotero.Feed.prototype, '_updateFeed').resolves(); let url = getTestDataUrl("feed.rss"); freshFeed = yield createFeed({refreshInterval: 2}); freshFeed._feedUrl = url; freshFeed.lastCheck = null; yield freshFeed.saveTx(); recentFeed = yield createFeed({refreshInterval: 2}); recentFeed._feedUrl = url; recentFeed.lastCheck = Zotero.Date.dateToSQL(new Date(), true); yield recentFeed.saveTx(); oldFeed = yield createFeed({refreshInterval: 2}); oldFeed._feedUrl = url; oldFeed.lastCheck = Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60*60*6), true); yield oldFeed.saveTx(); yield Zotero.Feeds.updateFeeds(); assert.isTrue(_updateFeed.called); }); after(function() { Zotero.Feeds.scheduleNextFeedCheck.restore(); _updateFeed.restore(); }); it('should update feeds that have never been updated', function() { for (var feed of _updateFeed.thisValues) { if (feed.id == freshFeed.id) { break; } } assert.isTrue(feed._updateFeed.called); }); it('should update feeds that need updating since last check', function() { for (var feed of _updateFeed.thisValues) { if (feed.id == oldFeed.id) { break; } } assert.isTrue(feed._updateFeed.called); }); it("should not update feeds that don't need updating", function() { for (var feed of _updateFeed.thisValues) { if (feed.id != recentFeed.id) { break; } // should never reach assert.ok(null, "does not update feed that did not need updating") } }); }); describe('#scheduleNextFeedCheck()', function() { it('schedules next feed check', function* () { sinon.spy(Zotero.Feeds, 'scheduleNextFeedCheck'); sinon.spy(Zotero.Promise, 'delay'); yield clearFeeds(); let feed = yield createFeed({refreshInterval: 1}); feed._set('_feedLastCheck', Zotero.Date.dateToSQL(new Date(), true)); yield feed.saveTx(); yield Zotero.Feeds.scheduleNextFeedCheck(); // Allow a propagation delay of 5000ms assert.isTrue(Zotero.Promise.delay.args[0][0] - 1000*60*60 <= 5000); Zotero.Feeds.scheduleNextFeedCheck.restore(); Zotero.Promise.delay.restore(); }); }) })