2015-06-02 04:29:40 +00:00
|
|
|
describe("Zotero.FeedItem", function () {
|
|
|
|
let feed, libraryID;
|
|
|
|
before(function* () {
|
2016-01-13 13:13:29 +00:00
|
|
|
feed = yield createFeed({ name: 'Test ' + Zotero.randomString(), url: 'http://' + Zotero.randomString() + '.com/' });
|
2015-06-02 04:29:40 +00:00
|
|
|
yield feed.saveTx();
|
|
|
|
libraryID = feed.libraryID;
|
|
|
|
});
|
|
|
|
after(function() {
|
2016-01-13 13:13:29 +00:00
|
|
|
return clearFeeds();
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should be an instance of Zotero.Item", function() {
|
|
|
|
assert.instanceOf(new Zotero.FeedItem(), Zotero.Item);
|
|
|
|
});
|
|
|
|
describe("#libraryID", function() {
|
|
|
|
it("should reference a feed", function() {
|
|
|
|
let feedItem = new Zotero.FeedItem();
|
|
|
|
assert.doesNotThrow(function() {feedItem.libraryID = feed.libraryID});
|
|
|
|
assert.throws(function() {feedItem.libraryID = Zotero.Libraries.userLibraryID}, /^libraryID must reference a feed$/);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("#constructor()", function* () {
|
|
|
|
it("should accept required fields as arguments", function* () {
|
|
|
|
let guid = Zotero.randomString();
|
|
|
|
let feedItem = new Zotero.FeedItem();
|
2016-02-11 11:02:38 +00:00
|
|
|
yield assert.isRejected(feedItem.saveTx());
|
2015-06-02 04:29:40 +00:00
|
|
|
|
|
|
|
feedItem = new Zotero.FeedItem('book', { guid });
|
|
|
|
feedItem.libraryID = libraryID;
|
2016-02-11 11:02:38 +00:00
|
|
|
yield assert.isFulfilled(feedItem.saveTx());
|
2015-06-02 04:29:40 +00:00
|
|
|
|
|
|
|
assert.equal(feedItem.itemTypeID, Zotero.ItemTypes.getID('book'));
|
|
|
|
assert.equal(feedItem.guid, guid);
|
|
|
|
assert.equal(feedItem.libraryID, libraryID);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("#isFeedItem", function() {
|
|
|
|
it("should be true", function() {
|
|
|
|
let feedItem = new Zotero.FeedItem();
|
|
|
|
assert.isTrue(feedItem.isFeedItem);
|
|
|
|
});
|
|
|
|
it("should be falsy for regular item", function() {
|
|
|
|
let item = new Zotero.Item();
|
|
|
|
assert.notOk(item.isFeedItem);
|
|
|
|
})
|
|
|
|
});
|
|
|
|
describe("#guid", function() {
|
|
|
|
it("should not be settable to a non-string value", function() {
|
|
|
|
let feedItem = new Zotero.FeedItem();
|
|
|
|
assert.throws(() => feedItem.guid = 1);
|
|
|
|
});
|
|
|
|
it("should be settable to any string", function() {
|
|
|
|
let feedItem = new Zotero.FeedItem();
|
|
|
|
feedItem.guid = 'foo';
|
|
|
|
assert.equal(feedItem.guid, 'foo');
|
|
|
|
});
|
|
|
|
it("should not be possible to change guid after saving item", function* () {
|
|
|
|
let feedItem = yield createDataObject('feedItem', { libraryID });
|
|
|
|
assert.throws(() => feedItem.guid = 'bar');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("#isRead", function() {
|
|
|
|
it("should be false by default", function* () {
|
|
|
|
let feedItem = yield createDataObject('feedItem', { libraryID });
|
|
|
|
assert.isFalse(feedItem.isRead);
|
|
|
|
});
|
|
|
|
it("should be settable and persist after saving", function* () {
|
|
|
|
this.timeout(5000);
|
|
|
|
let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() });
|
|
|
|
feedItem.libraryID = feed.libraryID;
|
|
|
|
assert.isFalse(feedItem.isRead);
|
|
|
|
|
|
|
|
let expectedTimestamp = Date.now();
|
|
|
|
feedItem.isRead = true;
|
|
|
|
assert.isTrue(feedItem.isRead);
|
|
|
|
let readTime = Zotero.Date.sqlToDate(feedItem._feedItemReadTime, true).getTime();
|
|
|
|
assert.closeTo(readTime, expectedTimestamp, 2000, 'sets the read timestamp to current time');
|
|
|
|
|
|
|
|
feedItem.isRead = false;
|
|
|
|
assert.isFalse(feedItem.isRead);
|
|
|
|
assert.notOk(feedItem._feedItemReadTime);
|
|
|
|
|
|
|
|
expectedTimestamp = Date.now();
|
|
|
|
feedItem.isRead = true;
|
|
|
|
yield Zotero.Promise.delay(2001);
|
2016-02-11 11:02:38 +00:00
|
|
|
yield feedItem.saveTx();
|
2015-06-02 04:29:40 +00:00
|
|
|
|
|
|
|
readTime = yield Zotero.DB.valueQueryAsync('SELECT readTime FROM feedItems WHERE itemID=?', feedItem.id);
|
|
|
|
readTime = Zotero.Date.sqlToDate(readTime, true).getTime();
|
|
|
|
assert.closeTo(readTime, expectedTimestamp, 2000, 'read timestamp is correct in the DB');
|
|
|
|
});
|
|
|
|
});
|
2016-01-13 13:13:29 +00:00
|
|
|
describe("#fromJSON()", function() {
|
|
|
|
it("should attempt to parse non ISO-8601 dates", function* () {
|
2016-06-13 10:03:20 +00:00
|
|
|
Zotero.locale = 'en-US';
|
2022-06-22 08:36:56 +00:00
|
|
|
Zotero.Date.init();
|
2016-06-13 10:03:20 +00:00
|
|
|
var data = [
|
|
|
|
{
|
|
|
|
itemType: "journalArticle",
|
|
|
|
date: "2015-06-07 20:56:00" // sql
|
|
|
|
},
|
|
|
|
{
|
|
|
|
itemType: "journalArticle",
|
|
|
|
date: "Mon, 13 Jun 2016 06:25:57 EDT" // HTTP
|
|
|
|
},
|
|
|
|
{
|
|
|
|
itemType: "journalArticle",
|
|
|
|
date: "18-20 June 2015" // parsed by `strToDate`
|
|
|
|
},
|
|
|
|
{
|
|
|
|
itemType: "journalArticle",
|
|
|
|
date: "06/07/2015" // american format also parsed by `strToDate`
|
|
|
|
}
|
|
|
|
];
|
|
|
|
var expectedDates = [
|
|
|
|
'2015-06-07 20:56:00',
|
|
|
|
'2016-06-13 10:25:57',
|
|
|
|
'2015-06-18',
|
|
|
|
'2015-06-07'
|
|
|
|
];
|
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
|
var item = new Zotero.FeedItem;
|
|
|
|
item.fromJSON(data[i]);
|
|
|
|
assert.strictEqual(item.getField('date'), expectedDates[i]);
|
|
|
|
}
|
2016-01-13 13:13:29 +00:00
|
|
|
})
|
|
|
|
});
|
2015-06-02 04:29:40 +00:00
|
|
|
describe("#save()", function() {
|
|
|
|
it("should require feed being set", function* () {
|
|
|
|
let feedItem = new Zotero.FeedItem('book', { guid: Zotero.randomString() });
|
|
|
|
// Defaults to user library ID
|
2017-05-31 15:52:06 +00:00
|
|
|
yield assert.isRejected(feedItem.saveTx(), /^Cannot add /);
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|
|
|
|
it("should require GUID being set", function* () {
|
|
|
|
let feedItem = new Zotero.FeedItem('book');
|
|
|
|
feedItem.libraryID = feed.libraryID;
|
2017-05-31 15:52:06 +00:00
|
|
|
yield assert.isRejected(feedItem.saveTx(), /^GUID must be set before saving FeedItem$/);
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|
|
|
|
it("should require a unique GUID", function* () {
|
|
|
|
let guid = Zotero.randomString();
|
|
|
|
let feedItem1 = yield createDataObject('feedItem', { libraryID, guid });
|
|
|
|
|
|
|
|
let feedItem2 = createUnsavedDataObject('feedItem', { libraryID, guid });
|
2016-02-11 11:02:38 +00:00
|
|
|
yield assert.isRejected(feedItem2.saveTx());
|
2015-06-02 04:29:40 +00:00
|
|
|
|
|
|
|
// But we should be able to save it after deleting the original feed
|
2016-02-11 11:02:38 +00:00
|
|
|
yield feedItem1.eraseTx();
|
|
|
|
yield assert.isFulfilled(feedItem2.saveTx());
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|
|
|
|
it("should require item type being set", function* () {
|
|
|
|
let feedItem = new Zotero.FeedItem(null, { guid: Zotero.randomString() });
|
|
|
|
feedItem.libraryID = feed.libraryID;
|
2017-05-31 15:52:06 +00:00
|
|
|
yield assert.isRejected(feedItem.saveTx(), /^Item type must be set before saving$/);
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|
|
|
|
it("should save feed item", function* () {
|
|
|
|
let guid = Zotero.randomString();
|
|
|
|
let feedItem = createUnsavedDataObject('feedItem', { libraryID, guid });
|
2016-02-11 11:02:38 +00:00
|
|
|
yield assert.isFulfilled(feedItem.saveTx());
|
2015-06-02 04:29:40 +00:00
|
|
|
|
|
|
|
feedItem = yield Zotero.FeedItems.getAsync(feedItem.id);
|
|
|
|
assert.ok(feedItem);
|
|
|
|
assert.equal(feedItem.guid, guid);
|
|
|
|
});
|
|
|
|
it.skip("should support saving feed items with all types and fields", function* () {
|
|
|
|
this.timeout(60000);
|
|
|
|
let allTypesAndFields = loadSampleData('allTypesAndFields'),
|
|
|
|
feedItems = [];
|
|
|
|
for (let type in allTypesAndFields) {
|
|
|
|
let feedItem = new Zotero.FeedItem(null, type, feed.libraryID);
|
|
|
|
feedItem.fromJSON(allTypesAndFields[type]);
|
|
|
|
|
2016-02-11 11:02:38 +00:00
|
|
|
yield feedItem.saveTx();
|
2015-06-02 04:29:40 +00:00
|
|
|
|
|
|
|
feedItems.push(feedItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
let feedItemsJSON = {};
|
|
|
|
for (let i=0; i<feedItems.length; i++) {
|
|
|
|
let feed = feedItems[i];
|
|
|
|
feedItemsJSON[feed.guid] = feed.toJSON();
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.deepEqual(feedItemsJSON, allTypesAndFields);
|
|
|
|
});
|
|
|
|
it("should allow saving after editing data", function* () {
|
|
|
|
let feedItem = yield createDataObject('feedItem', { libraryID });
|
|
|
|
|
|
|
|
feedItem.setField('title', 'bar');
|
2016-02-11 11:02:38 +00:00
|
|
|
yield assert.isFulfilled(feedItem.saveTx());
|
2015-06-02 04:29:40 +00:00
|
|
|
assert.equal(feedItem.getField('title'), 'bar');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("#erase()", function() {
|
|
|
|
it("should erase an existing feed item", function* () {
|
|
|
|
let feedItem = yield createDataObject('feedItem', { libraryID });
|
|
|
|
|
2016-02-11 11:02:38 +00:00
|
|
|
yield feedItem.eraseTx();
|
2015-06-02 04:29:40 +00:00
|
|
|
assert.isFalse(yield Zotero.FeedItems.getAsync(feedItem.id));
|
|
|
|
|
2016-02-11 11:02:38 +00:00
|
|
|
//yield assert.isRejected(feedItem.EraseTx(), "does not allow erasing twice");
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|
|
|
|
});
|
2016-01-13 13:13:29 +00:00
|
|
|
|
|
|
|
describe("#toggleRead()", function() {
|
|
|
|
it('should toggle state', function* () {
|
2016-02-01 14:59:30 +00:00
|
|
|
let item = yield createDataObject('feedItem', { libraryID });
|
2016-01-13 13:13:29 +00:00
|
|
|
item.isRead = false;
|
2016-02-11 11:02:38 +00:00
|
|
|
yield item.saveTx();
|
2016-01-13 13:13:29 +00:00
|
|
|
|
|
|
|
yield item.toggleRead();
|
|
|
|
assert.isTrue(item.isRead, "item is toggled to read state");
|
|
|
|
});
|
|
|
|
it('should save if specified state is different from current', function* (){
|
2016-02-01 14:59:30 +00:00
|
|
|
let item = yield createDataObject('feedItem', { libraryID });
|
2016-01-13 13:13:29 +00:00
|
|
|
item.isRead = false;
|
2016-02-11 11:02:38 +00:00
|
|
|
yield item.saveTx();
|
2016-01-13 13:13:29 +00:00
|
|
|
sinon.spy(item, 'save');
|
|
|
|
|
|
|
|
yield item.toggleRead(true);
|
|
|
|
assert.isTrue(item.save.called, "item was saved on toggle read");
|
|
|
|
|
2019-05-25 11:28:28 +00:00
|
|
|
item.save.resetHistory();
|
2016-01-13 13:13:29 +00:00
|
|
|
|
|
|
|
yield item.toggleRead(true);
|
|
|
|
assert.isFalse(item.save.called, "item was not saved on toggle read to same state");
|
|
|
|
});
|
|
|
|
});
|
2016-02-01 14:59:30 +00:00
|
|
|
|
|
|
|
describe('#translate()', function() {
|
2016-06-11 08:50:04 +00:00
|
|
|
var win;
|
|
|
|
|
2016-02-01 14:59:30 +00:00
|
|
|
before(function* () {
|
2016-08-25 16:37:51 +00:00
|
|
|
// TEMP: Fix for slow translator initialization on Linux/Travis
|
|
|
|
this.timeout(20000);
|
|
|
|
yield Zotero.Translators.init();
|
|
|
|
|
2022-06-19 19:07:41 +00:00
|
|
|
// Needs an open window to be able to create a progress window
|
|
|
|
win = yield loadZoteroWindow();
|
2016-02-01 14:59:30 +00:00
|
|
|
});
|
2016-06-11 08:50:04 +00:00
|
|
|
|
|
|
|
after(function () {
|
|
|
|
win.close()
|
|
|
|
});
|
|
|
|
|
2017-11-30 09:39:34 +00:00
|
|
|
it('should translate and save items', function* () {
|
2016-02-01 14:59:30 +00:00
|
|
|
var feedItem = yield createDataObject('feedItem', {libraryID});
|
2016-02-11 11:02:38 +00:00
|
|
|
var url = getTestDataUrl('metadata/journalArticle-single.html');
|
2016-02-01 14:59:30 +00:00
|
|
|
feedItem.setField('url', url);
|
2016-02-11 11:02:38 +00:00
|
|
|
yield feedItem.saveTx();
|
2016-02-01 14:59:30 +00:00
|
|
|
|
|
|
|
yield feedItem.translate();
|
|
|
|
|
|
|
|
assert.equal(feedItem.getField('title'), 'Scarcity or Abundance? Preserving the Past in a Digital Era');
|
|
|
|
});
|
2017-11-30 09:39:34 +00:00
|
|
|
it('should translate and save items to corresponding library and collection', function* () {
|
2016-02-01 14:59:30 +00:00
|
|
|
let group = yield createGroup();
|
|
|
|
let collection = yield createDataObject('collection', {libraryID: group.libraryID});
|
|
|
|
|
|
|
|
var feedItem = yield createDataObject('feedItem', {libraryID});
|
2016-02-11 11:02:38 +00:00
|
|
|
var url = getTestDataUrl('metadata/journalArticle-single.html');
|
2016-02-01 14:59:30 +00:00
|
|
|
feedItem.setField('url', url);
|
2016-02-11 11:02:38 +00:00
|
|
|
yield feedItem.saveTx();
|
2016-02-01 14:59:30 +00:00
|
|
|
|
|
|
|
yield feedItem.translate(group.libraryID, collection.id);
|
|
|
|
|
|
|
|
let item = collection.getChildItems(false, false)[0];
|
|
|
|
|
|
|
|
assert.equal(item.getField('title'), 'Scarcity or Abundance? Preserving the Past in a Digital Era');
|
|
|
|
});
|
2017-11-30 09:39:34 +00:00
|
|
|
it('should clone the item to corresponding library and collection if no translators available', function* () {
|
|
|
|
let group = yield createGroup();
|
|
|
|
let collection = yield createDataObject('collection', {libraryID: group.libraryID});
|
|
|
|
|
|
|
|
var feedItem = yield createDataObject('feedItem', {libraryID, title: 'test'});
|
|
|
|
var url = getTestDataUrl('test.html');
|
|
|
|
feedItem.setField('url', url);
|
|
|
|
yield feedItem.saveTx();
|
|
|
|
|
|
|
|
yield feedItem.translate(group.libraryID, collection.id);
|
|
|
|
|
|
|
|
let item = collection.getChildItems(false, false)[0];
|
|
|
|
|
|
|
|
assert.equal(item.getField('title'), 'test');
|
|
|
|
});
|
2016-02-01 14:59:30 +00:00
|
|
|
});
|
2015-06-02 04:29:40 +00:00
|
|
|
});
|