Remove retraction flag from items that no longer match
This commit is contained in:
parent
a6d7b623ac
commit
50a4308514
2 changed files with 128 additions and 5 deletions
|
@ -498,10 +498,11 @@ Zotero.Retractions = {
|
|||
// TODO: Diff list and remove existing retractions that are missing
|
||||
|
||||
let possibleMatches = await this._downloadPossibleMatches([...prefixesToSend]);
|
||||
await this._addPossibleMatches(possibleMatches);
|
||||
await this._addPossibleMatches(possibleMatches, true);
|
||||
}
|
||||
else {
|
||||
Zotero.debug("No possible retractions");
|
||||
await this._addPossibleMatches([], true);
|
||||
}
|
||||
|
||||
await this._saveCacheFile(list, etag, doiPrefixLength, pmidPrefixLength);
|
||||
|
@ -530,12 +531,16 @@ Zotero.Retractions = {
|
|||
},
|
||||
|
||||
/**
|
||||
* @param {Object[]} - Results from API search
|
||||
* @param {Object[]} possibleMatches - Results from API search
|
||||
* @param {Boolean} [removeExisting = false] - Remove retracted flag from all items that don't
|
||||
* match the results. This should only be true if possibleMatches includes all possible
|
||||
* matches in the database.
|
||||
* @return {Number[]} - Array of added item ids
|
||||
*/
|
||||
_addPossibleMatches: async function (possibleMatches) {
|
||||
_addPossibleMatches: async function (possibleMatches, removeExisting) {
|
||||
// Look in the key mappings for local items that match and add them as retractions
|
||||
var addedItemIDs = new Set();
|
||||
var allItemIDs = new Set();
|
||||
for (let row of possibleMatches) {
|
||||
if (row.doi) {
|
||||
let ids = this._keyItems[this.TYPE_DOI].get(row.doi);
|
||||
|
@ -544,6 +549,7 @@ Zotero.Retractions = {
|
|||
if (!this._retractedItems.has(id)) {
|
||||
addedItemIDs.add(id);
|
||||
}
|
||||
allItemIDs.add(id);
|
||||
await this._addEntry(id, row);
|
||||
}
|
||||
}
|
||||
|
@ -555,14 +561,31 @@ Zotero.Retractions = {
|
|||
if (!this._retractedItems.has(id)) {
|
||||
addedItemIDs.add(id);
|
||||
}
|
||||
allItemIDs.add(id);
|
||||
await this._addEntry(id, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.debug(`Found ${addedItemIDs.size} retracted `
|
||||
+ Zotero.Utilities.pluralize(addedItemIDs.size, 'item'));
|
||||
// Remove existing retracted items that no longer match
|
||||
var removed = 0;
|
||||
if (removeExisting) {
|
||||
for (let itemID of this._retractedItems) {
|
||||
if (!allItemIDs.has(itemID)) {
|
||||
let item = await Zotero.Items.getAsync(itemID);
|
||||
await this._removeEntry(itemID, item.libraryID);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var msg = `Found ${addedItemIDs.size} retracted `
|
||||
+ Zotero.Utilities.pluralize(addedItemIDs.size, 'item');
|
||||
if (removed) {
|
||||
msg += " and removed " + removed;
|
||||
}
|
||||
Zotero.debug(msg);
|
||||
addedItemIDs = [...addedItemIDs];
|
||||
if (addedItemIDs.length) {
|
||||
this._showAlert(addedItemIDs); // async
|
||||
|
|
|
@ -74,6 +74,106 @@ describe("Retractions", function() {
|
|||
}
|
||||
|
||||
|
||||
describe("#updateFromServer()", function () {
|
||||
var server;
|
||||
var baseURL;
|
||||
|
||||
before(function () {
|
||||
Zotero.HTTP.mock = sinon.FakeXMLHttpRequest;
|
||||
baseURL = ZOTERO_CONFIG.API_URL + 'retractions/';
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
server = sinon.fakeServer.create();
|
||||
server.autoRespond = true;
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
Zotero.HTTP.mock = null;
|
||||
// Restore the real list from the server. We could just mock it as part of the suite.
|
||||
await Zotero.Retractions.updateFromServer();
|
||||
});
|
||||
|
||||
/*it("shouldn't show banner or virtual collection for already flagged items on list update", async function () {
|
||||
await Zotero.Retractions.updateFromServer();
|
||||
});*/
|
||||
|
||||
it("should remove retraction flag from items that no longer match prefix list", async function () {
|
||||
var doi = '10.1234/abcde';
|
||||
var hash = Zotero.Utilities.Internal.sha1(doi);
|
||||
var prefix = hash.substr(0, 5);
|
||||
var lines = [
|
||||
Zotero.Retractions.TYPE_DOI + prefix + ' 12345\n',
|
||||
Zotero.Retractions.TYPE_DOI + 'aaaaa 23456\n'
|
||||
];
|
||||
|
||||
var listCount = 0;
|
||||
var searchCount = 0;
|
||||
server.respond(function (req) {
|
||||
if (req.method == 'GET' && req.url == baseURL + 'list') {
|
||||
listCount++;
|
||||
if (listCount == 1) {
|
||||
req.respond(
|
||||
200,
|
||||
{
|
||||
'Content-Type': 'text/plain',
|
||||
'ETag': 'abcdefg'
|
||||
},
|
||||
lines.join('')
|
||||
);
|
||||
}
|
||||
else if (listCount == 2) {
|
||||
req.respond(
|
||||
200,
|
||||
{
|
||||
'Content-Type': 'text/plain',
|
||||
'ETag': 'bcdefgh'
|
||||
},
|
||||
lines[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (req.method == 'POST' && req.url == baseURL + 'search') {
|
||||
searchCount++;
|
||||
if (searchCount == 1) {
|
||||
req.respond(
|
||||
200,
|
||||
{
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
JSON.stringify([
|
||||
{
|
||||
doi: hash,
|
||||
retractionDOI: '10.1234/bcdef',
|
||||
date: '2019-01-02'
|
||||
}
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await Zotero.Retractions.updateFromServer();
|
||||
|
||||
// Create item with DOI from list
|
||||
var promise = waitForItemEvent('refresh');
|
||||
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
||||
item.setField('DOI', doi);
|
||||
await item.saveTx();
|
||||
await promise;
|
||||
|
||||
assert.isTrue(Zotero.Retractions.isRetracted(item));
|
||||
|
||||
// Make a second request, with the entry removed
|
||||
promise = waitForItemEvent('refresh');
|
||||
await Zotero.Retractions.updateFromServer();
|
||||
await promise;
|
||||
|
||||
assert.isFalse(Zotero.Retractions.isRetracted(item));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("#getRetractionsFromJSON()", function () {
|
||||
it("should identify object with retracted DOI", async function () {
|
||||
var spy = sinon.spy(Zotero.HTTP, 'request');
|
||||
|
|
Loading…
Reference in a new issue