Various feeds changes

- Hide notes, tags and related for feed items in itembox
- Add feed support for <enclosure> elements
- Add feed syncing methods for synced settings (additional work is
  needed on the sync architecture to download synced settings from the
  server)
- Change feed item clear policy to be less aggressive
- Adjust for deasyncification
- Disable translate-on-select
- Close adomasven/zotero#7, Remove context menu items from feeds
This commit is contained in:
Adomas Venčkauskas 2016-02-11 11:02:38 +00:00 committed by Dan Stillman
parent 0d4025e9fb
commit 12fc6cfbe8
42 changed files with 894 additions and 379 deletions

View file

@ -385,11 +385,7 @@ function createUnsavedDataObject(objectType, params = {}) {
var createDataObject = Zotero.Promise.coroutine(function* (objectType, params = {}, saveOptions) {
var obj = createUnsavedDataObject(objectType, params);
if (objectType == 'feedItem') {
yield obj.forceSaveTx(saveOptions);
} else {
yield obj.saveTx(saveOptions);
}
yield obj.saveTx(saveOptions);
return obj;
});
@ -453,8 +449,12 @@ function getTestDataDirectory() {
QueryInterface(Components.interfaces.nsIFileURL).file;
}
function getTestDataItemUrl(path) {
return OS.Path.join("resource://zotero-unit-tests/data", path);
function getTestDataUrl(path) {
path = path.split('/');
if (path[0].length == 0) {
path.splice(0, 1);
}
return "resource://zotero-unit-tests/data/" + path.join('/');
}
/**

View file

@ -682,10 +682,10 @@ describe("Zotero.CollectionTreeView", function() {
it('should add a translated feed item recovered from an URL', function* (){
var feed = yield createFeed();
var collection = yield createDataObject('collection', false, { skipSelect: true });
var url = getTestDataItemUrl('metadata/journalArticle-single.html');
var url = getTestDataUrl('metadata/journalArticle-single.html');
var feedItem = yield createDataObject('feedItem', {libraryID: feed.libraryID}, { skipSelect: true });
feedItem.setField('url', url);
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
var translateFn = sinon.spy(feedItem, 'translate');
// Add observer to wait for collection add

View file

@ -18,6 +18,7 @@
<description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's &lt;a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm"&gt;Star City&lt;/a&gt;.</description>
<pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>
<enclosure url="http://www.example.com/example.pdf" type="application/pdf" />
</item>
<item>
<title>The Engine That Does More</title>

View file

@ -23,11 +23,11 @@ describe("Zotero.FeedItem", function () {
it("should accept required fields as arguments", function* () {
let guid = Zotero.randomString();
let feedItem = new Zotero.FeedItem();
yield assert.isRejected(feedItem.forceSaveTx());
yield assert.isRejected(feedItem.saveTx());
feedItem = new Zotero.FeedItem('book', { guid });
feedItem.libraryID = libraryID;
yield assert.isFulfilled(feedItem.forceSaveTx());
yield assert.isFulfilled(feedItem.saveTx());
assert.equal(feedItem.itemTypeID, Zotero.ItemTypes.getID('book'));
assert.equal(feedItem.guid, guid);
@ -83,7 +83,7 @@ describe("Zotero.FeedItem", function () {
expectedTimestamp = Date.now();
feedItem.isRead = true;
yield Zotero.Promise.delay(2001);
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
readTime = yield Zotero.DB.valueQueryAsync('SELECT readTime FROM feedItems WHERE itemID=?', feedItem.id);
readTime = Zotero.Date.sqlToDate(readTime, true).getTime();
@ -107,41 +107,36 @@ describe("Zotero.FeedItem", function () {
})
});
describe("#save()", function() {
it("should require edit check override", function* () {
let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() });
feedItem.libraryID = feed.libraryID;
yield assert.isRejected(feedItem.saveTx(), /^Error: Cannot edit feedItem in read-only library/);
});
it("should require feed being set", function* () {
let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() });
// Defaults to user library ID
yield assert.isRejected(feedItem.forceSaveTx(), /^Error: Cannot add /);
yield assert.isRejected(feedItem.saveTx(), /^Error: Cannot add /);
});
it("should require GUID being set", function* () {
let feedItem = new Zotero.FeedItem('book');
feedItem.libraryID = feed.libraryID;
yield assert.isRejected(feedItem.forceSaveTx(), /^Error: GUID must be set before saving FeedItem$/);
yield assert.isRejected(feedItem.saveTx(), /^Error: GUID must be set before saving FeedItem$/);
});
it("should require a unique GUID", function* () {
let guid = Zotero.randomString();
let feedItem1 = yield createDataObject('feedItem', { libraryID, guid });
let feedItem2 = createUnsavedDataObject('feedItem', { libraryID, guid });
yield assert.isRejected(feedItem2.forceSaveTx());
yield assert.isRejected(feedItem2.saveTx());
// But we should be able to save it after deleting the original feed
yield feedItem1.forceEraseTx();
yield assert.isFulfilled(feedItem2.forceSaveTx());
yield feedItem1.eraseTx();
yield assert.isFulfilled(feedItem2.saveTx());
});
it("should require item type being set", function* () {
let feedItem = new Zotero.FeedItem(null, { guid: Zotero.randomString() });
feedItem.libraryID = feed.libraryID;
yield assert.isRejected(feedItem.forceSaveTx(), /^Error: Item type must be set before saving$/);
yield assert.isRejected(feedItem.saveTx(), /^Error: Item type must be set before saving$/);
});
it("should save feed item", function* () {
let guid = Zotero.randomString();
let feedItem = createUnsavedDataObject('feedItem', { libraryID, guid });
yield assert.isFulfilled(feedItem.forceSaveTx());
yield assert.isFulfilled(feedItem.saveTx());
feedItem = yield Zotero.FeedItems.getAsync(feedItem.id);
assert.ok(feedItem);
@ -155,7 +150,7 @@ describe("Zotero.FeedItem", function () {
let feedItem = new Zotero.FeedItem(null, type, feed.libraryID);
feedItem.fromJSON(allTypesAndFields[type]);
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
feedItems.push(feedItem);
}
@ -172,7 +167,7 @@ describe("Zotero.FeedItem", function () {
let feedItem = yield createDataObject('feedItem', { libraryID });
feedItem.setField('title', 'bar');
yield assert.isFulfilled(feedItem.forceSaveTx());
yield assert.isFulfilled(feedItem.saveTx());
assert.equal(feedItem.getField('title'), 'bar');
});
});
@ -180,15 +175,22 @@ describe("Zotero.FeedItem", function () {
it("should erase an existing feed item", function* () {
let feedItem = yield createDataObject('feedItem', { libraryID });
yield feedItem.forceEraseTx();
yield feedItem.eraseTx();
assert.isFalse(yield Zotero.FeedItems.getAsync(feedItem.id));
//yield assert.isRejected(feedItem.forceEraseTx(), "does not allow erasing twice");
//yield assert.isRejected(feedItem.EraseTx(), "does not allow erasing twice");
});
it("should require edit check override to erase", function* () {
let feedItem = yield createDataObject('feedItem', { libraryID });
it("should remove synced setting if exists", function* () {
let item = yield createDataObject('feedItem', { libraryID });
yield assert.isRejected(feedItem.eraseTx(), /^Error: Cannot edit feedItem in read-only library/);
yield item.toggleRead();
let syncedSettings = feed.getSyncedSettings();
assert.ok(syncedSettings.markedAsRead[item.guid]);
yield item.eraseTx();
syncedSettings = feed.getSyncedSettings();
assert.notOk(syncedSettings.markedAsRead[item.guid]);
});
});
@ -196,7 +198,7 @@ describe("Zotero.FeedItem", function () {
it('should toggle state', function* () {
let item = yield createDataObject('feedItem', { libraryID });
item.isRead = false;
yield item.forceSaveTx();
yield item.saveTx();
yield item.toggleRead();
assert.isTrue(item.isRead, "item is toggled to read state");
@ -204,7 +206,7 @@ describe("Zotero.FeedItem", function () {
it('should save if specified state is different from current', function* (){
let item = yield createDataObject('feedItem', { libraryID });
item.isRead = false;
yield item.forceSaveTx();
yield item.saveTx();
sinon.spy(item, 'save');
yield item.toggleRead(true);
@ -215,6 +217,17 @@ describe("Zotero.FeedItem", function () {
yield item.toggleRead(true);
assert.isFalse(item.save.called, "item was not saved on toggle read to same state");
});
it('should set relevant synced settings', function* () {
let item = yield createDataObject('feedItem', { libraryID });
item.isRead = false;
yield item.saveTx();
yield item.toggleRead();
let feed = Zotero.Feeds.get(item.libraryID);
let syncedSettings = feed.getSyncedSettings();
assert.ok(syncedSettings.markedAsRead[item.guid], "item marked as read stored in synced settings");
});
});
describe('#translate()', function() {
@ -224,9 +237,9 @@ describe("Zotero.FeedItem", function () {
});
it('translates and saves items', function* () {
var feedItem = yield createDataObject('feedItem', {libraryID});
var url = getTestDataItemUrl('metadata/journalArticle-single.html');
var url = getTestDataUrl('metadata/journalArticle-single.html');
feedItem.setField('url', url);
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
yield feedItem.translate();
@ -237,9 +250,9 @@ describe("Zotero.FeedItem", function () {
let collection = yield createDataObject('collection', {libraryID: group.libraryID});
var feedItem = yield createDataObject('feedItem', {libraryID});
var url = getTestDataItemUrl('metadata/journalArticle-single.html');
var url = getTestDataUrl('metadata/journalArticle-single.html');
feedItem.setField('url', url);
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
yield feedItem.translate(group.libraryID, collection.id);

View file

@ -7,6 +7,51 @@ describe("Zotero.FeedItems", function () {
return clearFeeds();
});
describe("#getMarkedAsRead", function() {
var items = [];
var result;
before(function* () {
for (let i = 0; i < 4; i++) {
let f = yield createDataObject('feedItem', {libraryID: feed.libraryID, guid: 'http://www.example.com/' + i});
items.push(f);
}
yield items[0].toggleRead();
yield items[2].toggleRead();
result = yield Zotero.FeedItems.getMarkedAsRead(feed.libraryID);
});
it('should get all marked as read items', function() {
assert.include(result, items[0]);
assert.include(result, items[2]);
});
it('should not include items that were not marked', function() {
assert.notInclude(result, items[1]);
assert.notInclude(result, items[3]);
});
});
describe("#markAsReadByGUID", function() {
var items = [];
var result;
before(function* () {
for (let i = 0; i < 4; i++) {
let f = yield createDataObject('feedItem', {
libraryID: feed.libraryID,
guid: 'http://' + Zotero.Utilities.randomString() + '.com/feed.rss'
});
items.push(f);
}
yield Zotero.FeedItems.markAsReadByGUID([items[0].guid, items[2].guid]);
});
it('should mark as read only specified guids', function() {
assert.isTrue(items[0].isRead);
assert.isTrue(items[2].isRead);
});
it('should leave other items marked unread', function() {
assert.isFalse(items[1].isRead);
assert.isFalse(items[3].isRead);
});
});
describe("#getIDFromGUID()", function() {
it("should return false for non-existent GUID", function* () {
let id = yield Zotero.FeedItems.getIDFromGUID(Zotero.randomString());
@ -14,7 +59,7 @@ describe("Zotero.FeedItems", function () {
});
it("should return feed item id from GUID", function* () {
let feedItem = yield createDataObject('feedItem', { libraryID: feed.libraryID });
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
let id2 = yield Zotero.FeedItems.getIDFromGUID(feedItem.guid);
assert.equal(id2, feedItem.id);
@ -24,7 +69,7 @@ describe("Zotero.FeedItems", function () {
it("should return feed item from GUID", function* () {
let guid = Zotero.randomString();
let feedItem = yield createDataObject('feedItem', { guid, libraryID: feed.libraryID });
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
let feedItem2 = yield Zotero.FeedItems.getAsyncByGUID(guid);
assert.equal(feedItem2.id, feedItem.id);
@ -48,7 +93,7 @@ describe("Zotero.FeedItems", function () {
for (let i = 0; i < 10; i++) {
let item = yield createDataObject('feedItem', { guid: Zotero.randomString(), libraryID: feed.id });
item.isRead = true;
yield item.forceSaveTx();
yield item.saveTx();
items.push(item);
}
ids = Array.map(items, (i) => i.id);
@ -66,7 +111,7 @@ describe("Zotero.FeedItems", function () {
it('should toggle all items read if at least one unread', function* () {
items[0].isRead = false;
yield items[0].forceSaveTx();
yield items[0].saveTx();
yield Zotero.FeedItems.toggleReadByID(ids);
@ -85,7 +130,7 @@ describe("Zotero.FeedItems", function () {
it('should toggle all items unread if unread state specified', function* () {
items[0].isRead = false;
yield items[0].forceSaveTx();
yield items[0].saveTx();
yield Zotero.FeedItems.toggleReadByID(ids, false);
@ -93,5 +138,15 @@ describe("Zotero.FeedItems", function () {
assert.isFalse(save.thisValues[i].isRead, "#toggleRead called with true");
}
});
it('should set relevant sync settings', function* () {
items[0].isRead = false;
yield items[0].saveTx();
yield Zotero.FeedItems.toggleReadByID(ids);
let syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
let markedAsRead = Object.keys(syncedFeeds[feed.url].markedAsRead);
assert.deepEqual(markedAsRead, Object.keys(items).map((k) => items[k].guid));
});
});
});

View file

@ -2,9 +2,9 @@
describe("Zotero.FeedReader", function () {
var htmlUrl = getTestDataItemUrl("test.html");
var htmlUrl = getTestDataUrl("test.html");
var feedUrl = getTestDataItemUrl("feed.rss");
var feedUrl = getTestDataUrl("feed.rss");
var feedInfo = {
title: 'Liftoff News',
subtitle: 'Liftoff to Space Exploration.',
@ -18,7 +18,7 @@ describe("Zotero.FeedReader", function () {
language: 'en-us'
};
var detailedFeedUrl = getTestDataItemUrl("feedDetailed.rss");
var detailedFeedUrl = getTestDataUrl("feedDetailed.rss");
var detailedFeedInfo = {
title: 'Feed',
subtitle: 'Feed Description',
@ -106,20 +106,15 @@ describe("Zotero.FeedReader", function () {
});
it('should parse items correctly for a sparse feed', function* () {
let expected = {
guid: 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573',
let expected = { guid: 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573',
title: 'Star City',
abstractNote: 'How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia\'s Star City.',
url: 'http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp',
creators: [{
firstName: '',
lastName: 'editor@example.com',
creatorType: 'author',
fieldMode: 1
}],
creators: [{ firstName: '', lastName: 'editor@example.com', creatorType: 'author', fieldMode: 1 }],
date: 'Tue, 03 Jun 2003 09:39:21 GMT',
language: 'en-us',
itemType: 'journalArticle'
itemType: 'journalArticle',
enclosedItems: [{ url: 'http://www.example.com/example.pdf', contentType: 'application/pdf' }]
};
let fr = new Zotero.FeedReader(feedUrl);
@ -149,7 +144,8 @@ describe("Zotero.FeedReader", function () {
publisher: 'Publisher',
rights: '©2016 Published by Publisher',
language: 'en',
itemType: 'journalArticle'
itemType: 'journalArticle',
enclosedItems: []
};
let fr = new Zotero.FeedReader(detailedFeedUrl);

View file

@ -42,12 +42,11 @@ describe("Zotero.Feed", function() {
yield feed.saveTx();
assert.isFalse(feed.editable);
});
it("should not allow adding items without editCheck override", function* () {
it("should allow adding items without editCheck override", function* () {
let feed = yield createFeed();
let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() });
feedItem.libraryID = feed.libraryID;
yield assert.isRejected(feedItem.saveTx(), /^Error: Cannot edit feedItem in read-only library/);
yield assert.isFulfilled(feedItem.saveTx({ skipEditCheck: true }));
yield assert.isFulfilled(feedItem.saveTx());
});
});
@ -135,6 +134,31 @@ describe("Zotero.Feed", function() {
assert.equal(feed.name, 'bar');
assert.equal(dbVal, feed.name);
});
it("should add a new synced setting after creation", function* () {
let url = 'http://' + Zotero.Utilities.randomString(10, 'abcde') + '.com/feed.rss';
let syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.notOk(syncedFeeds[url]);
yield createFeed({url});
syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.ok(syncedFeeds[url]);
});
it("should remove previous feed and add a new one if url changed", function* () {
let feed = yield createFeed();
let syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.ok(syncedFeeds[feed.url]);
let oldUrl = feed.url;
feed.url = 'http://' + Zotero.Utilities.randomString(10, 'abcde') + '.com/feed.rss';
yield feed.saveTx();
syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.notOk(syncedFeeds[oldUrl]);
assert.ok(syncedFeeds[feed.url]);
});
});
describe("#erase()", function() {
it("should erase a saved feed", function* () {
@ -160,10 +184,59 @@ describe("Zotero.Feed", function() {
assert.notOk(yield Zotero.FeedItems.getAsync(feedItem.id));
});
it("should remove synced settings", function* () {
let url = 'http://' + Zotero.Utilities.randomString(10, 'abcde') + '.com/feed.rss';
let feed = yield createFeed({url});
let syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.ok(syncedFeeds[feed.url]);
yield feed.eraseTx();
syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.notOk(syncedFeeds[url]);
});
});
describe("#getSyncedSettings", function() {
it("should return correct synced settings for the feed", function* () {
let url = 'http://' + Zotero.Utilities.randomString(10, 'abcde') + '.com/feed.rss';
let syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.notOk(syncedFeeds[url]);
let feed = yield createFeed({url});
syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.ok(syncedFeeds[url]);
let syncedData = feed.getSyncedSettings();
assert.deepEqual(syncedData, syncedFeeds[url]);
});
});
describe("#storeSyncedSettings", function() {
it("should store updated settings for the feed", function* () {
let guid = Zotero.Utilities.randomString();
let feed = yield createFeed();
let syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.notOk(syncedFeeds[feed.url].markedAsRead[guid]);
let syncedData = feed.getSyncedSettings();
syncedData.markedAsRead[guid] = true;
yield feed.setSyncedSettings(syncedData);
yield feed.storeSyncedSettings();
syncedFeeds = Zotero.SyncedSettings.get(Zotero.Libraries.userLibraryID, 'feeds');
assert.isTrue(syncedFeeds[feed.url].markedAsRead[guid]);
});
});
describe("#clearExpiredItems()", function() {
var feed, expiredFeedItem, readFeedItem, feedItem, feedItemIDs;
var feed, expiredFeedItem, readFeedItem, feedItem, readStillInFeed, feedItemIDs;
before(function* (){
feed = yield createFeed({cleanupAfter: 1});
@ -173,11 +246,18 @@ describe("Zotero.Feed", function() {
expiredFeedItem.isRead = true;
expiredFeedItem._feedItemReadTime = Zotero.Date.dateToSQL(
new Date(Date.now() - 2 * 24*60*60*1000), true);
yield expiredFeedItem.forceSaveTx();
yield expiredFeedItem.saveTx();
readStillInFeed = yield createDataObject('feedItem', { libraryID: feed.libraryID });
// Read 2 days ago
readStillInFeed.isRead = true;
readStillInFeed._feedItemReadTime = Zotero.Date.dateToSQL(
new Date(Date.now() - 2 * 24*60*60*1000), true);
yield readStillInFeed.saveTx();
readFeedItem = yield createDataObject('feedItem', { libraryID: feed.libraryID });
readFeedItem.isRead = true;
yield readFeedItem.forceSaveTx();
yield readFeedItem.saveTx();
feedItem = yield createDataObject('feedItem', { libraryID: feed.libraryID });
@ -186,8 +266,9 @@ describe("Zotero.Feed", function() {
assert.include(feedItemIDs, feedItem.id, "feed contains unread feed item");
assert.include(feedItemIDs, readFeedItem.id, "feed contains read feed item");
assert.include(feedItemIDs, expiredFeedItem.id, "feed contains expired feed item");
assert.include(feedItemIDs, readStillInFeed.id, "feed contains expired but still in rss feed item");
yield feed.clearExpiredItems();
yield feed.clearExpiredItems(new Set([readStillInFeed.id]));
feedItemIDs = yield Zotero.FeedItems.getAll(feed.libraryID).map((row) => row.id);
});
@ -198,7 +279,11 @@ describe("Zotero.Feed", function() {
it('should not clear read items that have not expired yet', function() {
assert.include(feedItemIDs, readFeedItem.id, "feed still contains new feed item");
})
});
it('should not clear read items that are still in rss', function() {
assert.include(feedItemIDs, readStillInFeed.id, "feed still contains read still in rss feed item");
});
it('should not clear unread items', function() {
assert.include(feedItemIDs, feedItem.id, "feed still contains new feed item");
@ -207,8 +292,8 @@ describe("Zotero.Feed", function() {
describe('#updateFeed()', function() {
var feed;
var feedUrl = getTestDataItemUrl("feed.rss");
var modifiedFeedUrl = getTestDataItemUrl("feedModified.rss");
var feedUrl = getTestDataUrl("feed.rss");
var modifiedFeedUrl = getTestDataUrl("feedModified.rss");
beforeEach(function* (){
feed = yield createFeed();
@ -232,11 +317,12 @@ describe("Zotero.Feed", function() {
});
it('should add new feed items', function* () {
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
let feedItems = yield Zotero.FeedItems.getAll(feed.id, true);
assert.equal(feedItems.length, 3);
});
it('should set lastCheck, lastUpdated and lastGUID values', function* () {
it('should set lastCheck and lastUpdated values', function* () {
yield clearFeeds();
let feed = yield createFeed();
feed._feedUrl = feedUrl;
@ -245,15 +331,14 @@ describe("Zotero.Feed", function() {
yield feed.updateFeed();
assert.ok(feed.lastCheck >= Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60), true));
assert.ok(feed.lastUpdate >= Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60), true));
assert.equal(feed.lastGUID, 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:'+feed.id);
assert.isTrue(feed.lastCheck > Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60), true), 'feed.lastCheck updated');
assert.isTrue(feed.lastUpdate > Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60), true), 'feed.lastUpdate updated');
});
it('should update modified items and set unread', function* () {
let feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
let feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573");
feedItem.isRead = true;
yield feedItem.forceSaveTx();
feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
yield feedItem.saveTx();
feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573");
assert.isTrue(feedItem.isRead);
let oldDateModified = feedItem.getField('date');
@ -261,7 +346,7 @@ describe("Zotero.Feed", function() {
feed._feedUrl = modifiedFeedUrl;
yield feed.updateFeed();
feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573");
assert.notEqual(oldDateModified, feedItem.getField('date'));
assert.isFalse(feedItem.isRead)
@ -272,7 +357,7 @@ describe("Zotero.Feed", function() {
feed._feedUrl = modifiedFeedUrl;
yield feed.updateFeed();
assert.equal(save.thisValues[0].guid, "http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
assert.equal(save.thisValues[0].guid, "http://liftoff.msfc.nasa.gov/2003/06/03.html#item573");
save.restore();
});
it('should update unread count', function* () {
@ -281,7 +366,7 @@ describe("Zotero.Feed", function() {
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
for (let feedItem of feedItems) {
feedItem.isRead = true;
yield feedItem.forceSaveTx();
yield feedItem.saveTx();
}
feed._feedUrl = modifiedFeedUrl;
@ -289,20 +374,11 @@ describe("Zotero.Feed", function() {
assert.equal(feed.unreadCount, 2);
});
it('should not re-add deleted items, but add new ones', function* () {
let feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/05/20.html#item570:"+feed.id);
yield feedItem.forceEraseTx();
it('should add a link to enclosed pdfs from <enclosure/> elements', function* () {
let feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573");
let pdf = yield Zotero.Items.getAsync(feedItem.getAttachments()[0]);
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
for (let feedItem of feedItems) {
feedItem.isRead = true;
yield feedItem.forceSaveTx();
}
feed._feedUrl = modifiedFeedUrl;
yield feed.updateFeed();
assert.equal(feed.unreadCount, 2);
assert.equal(pdf.getField('url'), "http://www.example.com/example.pdf");
});
});
@ -311,11 +387,6 @@ describe("Zotero.Feed", function() {
before(function* () {
feed = yield createFeed();
})
it("should not allow adding regular items", function* () {
let item = new Zotero.Item('book');
item.libraryID = feed.libraryID;
yield assert.isRejected(item.saveTx({ skipEditCheck: true }), /^Error: Cannot add /);
});
it("should not allow adding collections", function* () {
let collection = new Zotero.Collection({ name: 'test', libraryID: feed.libraryID });
yield assert.isRejected(collection.saveTx({ skipEditCheck: true }), /^Error: Cannot add /);
@ -327,7 +398,7 @@ describe("Zotero.Feed", function() {
it("should allow adding feed item", function* () {
let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() });
feedItem.libraryID = feed.libraryID;
yield assert.isFulfilled(feedItem.forceSaveTx());
yield assert.isFulfilled(feedItem.saveTx());
});
});
})

View file

@ -3,6 +3,77 @@ 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* () {
@ -40,6 +111,23 @@ describe("Zotero.Feeds", function () {
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;
@ -49,7 +137,7 @@ describe("Zotero.Feeds", function () {
sinon.stub(Zotero.Feeds, 'scheduleNextFeedCheck');
_updateFeed = sinon.stub(Zotero.Feed.prototype, '_updateFeed').resolves();
let url = getTestDataItemUrl("feed.rss");
let url = getTestDataUrl("feed.rss");
freshFeed = yield createFeed({refreshInterval: 2});
freshFeed._feedUrl = url;
@ -97,7 +185,7 @@ describe("Zotero.Feeds", function () {
break;
}
// should never reach
assert.isOk(null, "does not update feed that did not need updating")
assert.ok(null, "does not update feed that did not need updating")
}
});
});

View file

@ -131,7 +131,7 @@ describe("Zotero.Items", function () {
let feedItem = new Zotero.FeedItem('journalArticle', { guid: Zotero.randomString() });
feedItem.libraryID = feed.libraryID;
let id = yield feedItem.forceSaveTx();
let id = yield feedItem.saveTx();
feedItem = yield Zotero.Items.getAsync(id);