2015-04-26 21:42:29 +00:00
|
|
|
describe("Zotero.Attachments", function() {
|
|
|
|
var win;
|
|
|
|
|
2015-06-02 00:03:40 +00:00
|
|
|
before(function* () {
|
2015-04-26 21:42:29 +00:00
|
|
|
// Hidden browser, which requires a browser window, needed for charset detection
|
|
|
|
// (until we figure out a better way)
|
2015-06-02 00:03:40 +00:00
|
|
|
win = yield loadBrowserWindow();
|
2015-04-26 21:42:29 +00:00
|
|
|
});
|
|
|
|
after(function () {
|
|
|
|
if (win) {
|
|
|
|
win.close();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("#importFromFile()", function () {
|
|
|
|
it("should create a child attachment from a text file", function* () {
|
|
|
|
// Create test file
|
|
|
|
var contents = "Test";
|
|
|
|
var tmpFile = Zotero.getTempDirectory();
|
|
|
|
tmpFile.append('test.txt');
|
|
|
|
yield Zotero.File.putContentsAsync(tmpFile, contents);
|
|
|
|
|
|
|
|
// Create parent item
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var parentItemID = yield item.saveTx();
|
2015-04-26 21:42:29 +00:00
|
|
|
|
|
|
|
// Create attachment and compare content
|
2015-05-29 09:31:54 +00:00
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
2015-05-23 08:25:47 +00:00
|
|
|
file: tmpFile,
|
|
|
|
parentItemID: parentItemID
|
|
|
|
});
|
2015-04-26 21:42:29 +00:00
|
|
|
var storedFile = item.getFile();
|
|
|
|
assert.equal((yield Zotero.File.getContentsAsync(storedFile)), contents);
|
|
|
|
|
|
|
|
// Clean up
|
2015-05-29 09:31:54 +00:00
|
|
|
yield Zotero.Items.erase(item.id);
|
2015-04-26 21:42:29 +00:00
|
|
|
});
|
|
|
|
|
2015-05-23 08:25:47 +00:00
|
|
|
it("should create a top-level attachment from a PNG file", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var contents = yield Zotero.File.getBinaryContentsAsync(file);
|
|
|
|
|
|
|
|
// Create attachment and compare content
|
2015-05-29 09:31:54 +00:00
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
2015-05-23 08:25:47 +00:00
|
|
|
file: file
|
|
|
|
});
|
|
|
|
var storedFile = item.getFile();
|
|
|
|
assert.equal((yield Zotero.File.getBinaryContentsAsync(storedFile)), contents);
|
|
|
|
|
|
|
|
// Clean up
|
2015-05-29 09:31:54 +00:00
|
|
|
yield Zotero.Items.erase(item.id);
|
2015-05-23 08:25:47 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should create a top-level attachment from a PNG file in a collection", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var contents = yield Zotero.File.getBinaryContentsAsync(file);
|
|
|
|
|
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
|
|
|
|
// Create attachment and compare content
|
2015-05-29 09:31:54 +00:00
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
2015-05-23 08:25:47 +00:00
|
|
|
file: file,
|
|
|
|
collections: [collection.id]
|
|
|
|
});
|
|
|
|
var storedFile = item.getFile();
|
|
|
|
assert.equal((yield Zotero.File.getBinaryContentsAsync(storedFile)), contents);
|
|
|
|
|
|
|
|
// Clean up
|
2015-05-29 09:31:54 +00:00
|
|
|
yield Zotero.Items.erase(item.id);
|
2015-05-23 08:25:47 +00:00
|
|
|
});
|
|
|
|
|
2015-04-26 21:42:29 +00:00
|
|
|
it("should create a child attachment from a PNG file", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var contents = yield Zotero.File.getBinaryContentsAsync(file);
|
|
|
|
|
|
|
|
// Create parent item
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var parentItemID = yield item.saveTx();
|
2015-04-26 21:42:29 +00:00
|
|
|
|
|
|
|
// Create attachment and compare content
|
2015-05-29 09:31:54 +00:00
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
2015-05-23 08:25:47 +00:00
|
|
|
file: file,
|
|
|
|
parentItemID: parentItemID
|
|
|
|
});
|
2015-04-26 21:42:29 +00:00
|
|
|
var storedFile = item.getFile();
|
|
|
|
assert.equal((yield Zotero.File.getBinaryContentsAsync(storedFile)), contents);
|
|
|
|
|
|
|
|
// Clean up
|
2015-05-29 09:31:54 +00:00
|
|
|
yield Zotero.Items.erase(item.id);
|
2015-04-26 21:42:29 +00:00
|
|
|
});
|
|
|
|
})
|
2015-05-29 05:07:23 +00:00
|
|
|
|
2016-03-22 04:40:59 +00:00
|
|
|
describe("#linkFromFile()", function () {
|
2015-05-29 05:07:23 +00:00
|
|
|
it("should link to a file in My Library", function* () {
|
|
|
|
var item = yield createDataObject('item');
|
|
|
|
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var attachment = yield Zotero.Attachments.linkFromFile({
|
|
|
|
file: file,
|
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getFilePath(), file.path);
|
|
|
|
})
|
|
|
|
|
|
|
|
it.skip("should throw an error for a non-user library", function* () {
|
|
|
|
// Should create a group library for use by all tests
|
|
|
|
})
|
|
|
|
})
|
2015-08-09 08:52:14 +00:00
|
|
|
|
2018-06-30 07:11:13 +00:00
|
|
|
|
|
|
|
describe("#linkFromFileWithRelativePath()", function () {
|
|
|
|
afterEach(function () {
|
|
|
|
Zotero.Prefs.clear('baseAttachmentPath');
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should link to a file using a relative path with no base directory set", async function () {
|
|
|
|
Zotero.Prefs.clear('baseAttachmentPath');
|
|
|
|
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
var spy = sinon.spy(Zotero.Fulltext, 'indexPDF');
|
|
|
|
var relPath = 'a/b/test.pdf';
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.linkFromFileWithRelativePath({
|
|
|
|
path: relPath,
|
|
|
|
title: 'test.pdf',
|
|
|
|
parentItemID: item.id,
|
|
|
|
contentType: 'application/pdf'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.ok(spy.notCalled);
|
|
|
|
spy.restore();
|
|
|
|
assert.equal(
|
|
|
|
attachment.attachmentPath,
|
|
|
|
Zotero.Attachments.BASE_PATH_PLACEHOLDER + relPath
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it("should link to a file using a relative path within the base directory", async function () {
|
|
|
|
var baseDir = await getTempDirectory();
|
|
|
|
Zotero.Prefs.set('baseAttachmentPath', baseDir);
|
|
|
|
Zotero.Prefs.set('saveRelativeAttachmentPath', true);
|
|
|
|
|
|
|
|
var subDir = OS.Path.join(baseDir, 'foo');
|
|
|
|
await OS.File.makeDir(subDir);
|
|
|
|
|
|
|
|
var file = OS.Path.join(subDir, 'test.pdf');
|
|
|
|
await OS.File.copy(OS.Path.join(getTestDataDirectory().path, 'test.pdf'), file);
|
|
|
|
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
var spy = sinon.spy(Zotero.Fulltext, 'indexPDF');
|
|
|
|
var relPath = 'foo/test.pdf';
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.linkFromFileWithRelativePath({
|
|
|
|
path: relPath,
|
|
|
|
title: 'test.pdf',
|
|
|
|
parentItemID: item.id,
|
|
|
|
contentType: 'application/pdf'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.ok(spy.called);
|
|
|
|
spy.restore();
|
|
|
|
assert.equal(
|
|
|
|
attachment.attachmentPath,
|
|
|
|
Zotero.Attachments.BASE_PATH_PLACEHOLDER + relPath
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.ok(await attachment.fileExists());
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it("should link to a nonexistent file using a relative path within the base directory", async function () {
|
|
|
|
var baseDir = await getTempDirectory();
|
|
|
|
Zotero.Prefs.set('baseAttachmentPath', baseDir);
|
|
|
|
Zotero.Prefs.set('saveRelativeAttachmentPath', true);
|
|
|
|
|
|
|
|
var subDir = OS.Path.join(baseDir, 'foo');
|
|
|
|
await OS.File.makeDir(subDir);
|
|
|
|
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
var spy = sinon.spy(Zotero.Fulltext, 'indexPDF');
|
|
|
|
var relPath = 'foo/test.pdf';
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.linkFromFileWithRelativePath({
|
|
|
|
path: relPath,
|
|
|
|
title: 'test.pdf',
|
|
|
|
parentItemID: item.id,
|
|
|
|
contentType: 'application/pdf'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.ok(spy.notCalled);
|
|
|
|
spy.restore();
|
|
|
|
assert.equal(
|
|
|
|
attachment.attachmentPath,
|
|
|
|
Zotero.Attachments.BASE_PATH_PLACEHOLDER + relPath
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.isFalse(await attachment.fileExists());
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it("should reject absolute paths", async function () {
|
|
|
|
try {
|
|
|
|
await Zotero.Attachments.linkFromFileWithRelativePath({
|
|
|
|
path: '/a/b/test.pdf',
|
|
|
|
title: 'test.pdf',
|
|
|
|
contentType: 'application/pdf'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.fail();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2016-03-22 04:40:59 +00:00
|
|
|
describe("#importSnapshotFromFile()", function () {
|
|
|
|
it("should import an HTML file", function* () {
|
|
|
|
var item = yield createDataObject('item');
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.html');
|
|
|
|
var attachment = yield Zotero.Attachments.importSnapshotFromFile({
|
|
|
|
title: 'Snapshot',
|
|
|
|
url: 'http://example.com',
|
|
|
|
file,
|
|
|
|
parentItemID: item.id,
|
|
|
|
contentType: 'text/html',
|
|
|
|
charset: 'utf-8'
|
|
|
|
});
|
|
|
|
|
|
|
|
var matches = yield Zotero.Fulltext.findTextInItems([attachment.id], 'test');
|
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should detect charset for an HTML file", function* () {
|
|
|
|
var item = yield createDataObject('item');
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.html');
|
|
|
|
var attachment = yield Zotero.Attachments.importSnapshotFromFile({
|
|
|
|
title: 'Snapshot',
|
|
|
|
url: 'http://example.com',
|
|
|
|
file,
|
|
|
|
parentItemID: item.id,
|
|
|
|
contentType: 'text/html'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.attachmentCharset, 'utf-8');
|
|
|
|
|
|
|
|
var matches = yield Zotero.Fulltext.findTextInItems([attachment.id], 'test');
|
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
|
|
|
});
|
2018-06-19 00:17:37 +00:00
|
|
|
|
|
|
|
// This isn't particularly the behavior we want, but it documents the expected behavior
|
|
|
|
it("shouldn't index JavaScript-created text in an HTML file when the charset isn't known in advance", async function () {
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test-js.html');
|
|
|
|
var attachment = await Zotero.Attachments.importSnapshotFromFile({
|
|
|
|
title: 'Snapshot',
|
|
|
|
url: 'http://example.com',
|
|
|
|
file,
|
|
|
|
parentItemID: item.id,
|
|
|
|
contentType: 'text/html'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.attachmentCharset, 'utf-8');
|
|
|
|
|
|
|
|
var matches = await Zotero.Fulltext.findTextInItems([attachment.id], 'test');
|
|
|
|
assert.lengthOf(matches, 0);
|
|
|
|
});
|
2016-03-22 04:40:59 +00:00
|
|
|
});
|
|
|
|
|
2016-02-11 07:54:52 +00:00
|
|
|
describe("#linkFromDocument", function () {
|
|
|
|
it("should add a link attachment for the current webpage", function* () {
|
|
|
|
var item = yield createDataObject('item');
|
|
|
|
|
|
|
|
var uri = OS.Path.join(getTestDataDirectory().path, "snapshot", "index.html");
|
|
|
|
var deferred = Zotero.Promise.defer();
|
|
|
|
win.addEventListener('pageshow', () => deferred.resolve());
|
|
|
|
win.loadURI(uri);
|
|
|
|
yield deferred.promise;
|
|
|
|
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var attachment = yield Zotero.Attachments.linkFromDocument({
|
|
|
|
document: win.content.document,
|
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getField('url'), "file://" + uri);
|
|
|
|
|
|
|
|
// Check indexing
|
2016-04-09 22:34:54 +00:00
|
|
|
var matches = yield Zotero.Fulltext.findTextInItems([attachment.id], 'share your research');
|
2016-02-11 07:54:52 +00:00
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2016-05-31 22:03:40 +00:00
|
|
|
describe("#importFromDocument()", function () {
|
|
|
|
it("should save a document with embedded files", function* () {
|
|
|
|
var item = yield createDataObject('item');
|
|
|
|
|
|
|
|
var uri = OS.Path.join(getTestDataDirectory().path, "snapshot", "index.html");
|
|
|
|
var deferred = Zotero.Promise.defer();
|
|
|
|
win.addEventListener('pageshow', () => deferred.resolve());
|
|
|
|
win.loadURI(uri);
|
|
|
|
yield deferred.promise;
|
|
|
|
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var attachment = yield Zotero.Attachments.importFromDocument({
|
|
|
|
document: win.content.document,
|
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getField('url'), "file://" + uri);
|
|
|
|
|
|
|
|
// Check indexing
|
|
|
|
var matches = yield Zotero.Fulltext.findTextInItems([attachment.id], 'share your research');
|
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
|
|
|
|
|
|
|
// Check for embedded files
|
|
|
|
var storageDir = Zotero.Attachments.getStorageDirectory(attachment).path;
|
|
|
|
var file = yield attachment.getFilePathAsync();
|
|
|
|
assert.equal(OS.Path.basename(file), 'index.html');
|
2016-06-02 20:37:26 +00:00
|
|
|
assert.isTrue(yield OS.File.exists(OS.Path.join(storageDir, 'img.gif')));
|
2016-05-31 22:03:40 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
describe("PDF Retrieval", function () {
|
2018-08-07 08:08:47 +00:00
|
|
|
var doiPrefix = 'https://doi.org/';
|
|
|
|
var doi1 = '10.1111/abcd';
|
|
|
|
var doi2 = '10.2222/bcde';
|
|
|
|
var doi3 = '10.3333/cdef';
|
|
|
|
var doi4 = '10.4444/defg';
|
2018-09-06 20:38:28 +00:00
|
|
|
var doi5 = '10.5555/efgh';
|
2018-09-21 08:20:37 +00:00
|
|
|
var doi6 = '10.6666/fghi';
|
2018-08-07 08:08:47 +00:00
|
|
|
var pageURL1 = 'http://website/article1';
|
|
|
|
var pageURL2 = 'http://website/article2';
|
|
|
|
var pageURL3 = 'http://website/article3';
|
|
|
|
var pageURL4 = 'http://website/article4';
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
var pageURL5 = `http://website/${doi4}`;
|
|
|
|
var pageURL6 = `http://website/${doi4}/json`;
|
2018-09-06 20:38:28 +00:00
|
|
|
var pageURL7 = doiPrefix + doi5;
|
2018-09-21 08:20:37 +00:00
|
|
|
var pageURL8 = 'http://website2/article8';
|
|
|
|
var pageURL9 = 'http://website/article9';
|
2018-11-26 07:35:51 +00:00
|
|
|
var pageURL10 = 'http://website/refresh';
|
2018-08-07 08:08:47 +00:00
|
|
|
|
|
|
|
Components.utils.import("resource://zotero-unit/httpd.js");
|
|
|
|
var httpd;
|
|
|
|
var port = 16213;
|
|
|
|
var baseURL = `http://localhost:${port}/`;
|
2018-09-06 20:38:28 +00:00
|
|
|
var pdfPath = OS.Path.join(getTestDataDirectory().path, 'test.pdf');
|
2018-08-07 08:08:47 +00:00
|
|
|
var pdfURL = `${baseURL}article1/pdf`;
|
|
|
|
var pdfSize;
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
var requestStub;
|
2018-09-21 08:20:37 +00:00
|
|
|
var requestStubCallTimes = [];
|
|
|
|
var return429 = true;
|
2018-08-07 08:08:47 +00:00
|
|
|
|
2018-09-06 20:38:28 +00:00
|
|
|
function makeGetResponseHeader(headers) {
|
|
|
|
return function (header) {
|
|
|
|
if (headers[header] !== undefined) {
|
|
|
|
return headers[header];
|
|
|
|
}
|
2018-09-21 08:20:37 +00:00
|
|
|
throw new Error(`Unimplemented header '${header}'`);
|
2018-09-06 20:38:28 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
function getHTMLPage(includePDF) {
|
|
|
|
return `<html>
|
|
|
|
<head>
|
|
|
|
<title>Page Title</title>
|
|
|
|
<link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" />
|
|
|
|
<meta name="citation_title" content="Title"/>
|
|
|
|
<meta name="${includePDF ? 'citation_pdf_url' : 'ignore'}" content="${pdfURL}"/>
|
|
|
|
</head>
|
|
|
|
<body>Body</body>
|
|
|
|
</html>`;
|
|
|
|
}
|
|
|
|
|
2018-09-06 20:38:28 +00:00
|
|
|
function makeHTMLResponseFromType(html, responseType, responseURL) {
|
|
|
|
var response;
|
|
|
|
if (responseType == 'document') {
|
|
|
|
let parser = new DOMParser();
|
|
|
|
let doc = parser.parseFromString(html, 'text/html');
|
|
|
|
doc = Zotero.HTTP.wrapDocument(doc, responseURL);
|
|
|
|
response = doc;
|
|
|
|
}
|
|
|
|
else if (responseType == 'blob') {
|
|
|
|
let blob = new Blob([html], {type: 'text/html'});
|
|
|
|
response = blob;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw new Error("Request not mocked");
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
status: 200,
|
|
|
|
response,
|
|
|
|
responseURL,
|
|
|
|
getResponseHeader: makeGetResponseHeader({
|
|
|
|
'Content-Type': 'text/html'
|
|
|
|
})
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-08-07 08:08:47 +00:00
|
|
|
before(async function () {
|
2018-09-06 20:38:28 +00:00
|
|
|
var pdfBlob = await File.createFromFileName(pdfPath);
|
|
|
|
|
2018-08-07 08:08:47 +00:00
|
|
|
var origFunc = Zotero.HTTP.request.bind(Zotero.HTTP);
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
requestStub = sinon.stub(Zotero.HTTP, 'request');
|
|
|
|
requestStub.callsFake(function (method, url, options) {
|
2018-09-06 20:38:28 +00:00
|
|
|
Zotero.debug("Intercepting " + method + " " + url);
|
2018-09-21 08:20:37 +00:00
|
|
|
requestStubCallTimes.push(new Date());
|
2018-09-06 20:38:28 +00:00
|
|
|
|
2018-08-07 08:08:47 +00:00
|
|
|
// Page responses
|
|
|
|
var routes = [
|
|
|
|
// DOI 1 redirects to page 1, which contains a PDF
|
|
|
|
[doiPrefix + doi1, pageURL1, true],
|
2018-09-21 08:20:37 +00:00
|
|
|
[pageURL1, pageURL1, true],
|
2018-08-07 08:08:47 +00:00
|
|
|
// DOI 2 redirects to page 2, which doesn't contain a PDF, but DOI 2 has an
|
|
|
|
// OA entry for the PDF URL
|
|
|
|
[doiPrefix + doi2, pageURL2, false],
|
2018-09-21 08:20:37 +00:00
|
|
|
[pageURL2, pageURL2, false],
|
2018-08-07 08:08:47 +00:00
|
|
|
// DOI 3 redirects to page 2, which doesn't contain a PDF, but DOI 3 contains
|
|
|
|
// an OA entry for page 3, which contains a PDF)
|
|
|
|
[doiPrefix + doi3, pageURL2, false],
|
|
|
|
[pageURL3, pageURL3, true],
|
|
|
|
// DOI 4 redirects to page 4, which doesn't contain a PDF
|
2018-09-06 20:38:28 +00:00
|
|
|
[doiPrefix + doi4, pageURL4, false],
|
2018-09-21 08:20:37 +00:00
|
|
|
[pageURL4, pageURL4, false],
|
|
|
|
// DOI 6 redirects to page 8, which is on a different domain and has a PDF
|
|
|
|
[doiPrefix + doi6, pageURL8, true],
|
|
|
|
[pageURL8, pageURL8, true],
|
2018-08-07 08:08:47 +00:00
|
|
|
];
|
|
|
|
for (let route of routes) {
|
|
|
|
let [expectedURL, responseURL, includePDF] = route;
|
|
|
|
|
|
|
|
if (url != expectedURL) continue;
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
// Return explicit 302 if not following redirects
|
|
|
|
if (expectedURL != responseURL && options.followRedirects === false) {
|
|
|
|
return {
|
|
|
|
status: 302,
|
|
|
|
getResponseHeader: makeGetResponseHeader({
|
|
|
|
Location: responseURL
|
|
|
|
})
|
|
|
|
};
|
|
|
|
}
|
2018-09-06 20:38:28 +00:00
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
let html = getHTMLPage(includePDF);
|
2018-09-06 20:38:28 +00:00
|
|
|
return makeHTMLResponseFromType(html, options.responseType, responseURL);
|
2018-08-07 08:08:47 +00:00
|
|
|
}
|
|
|
|
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
// HTML page with PDF download link
|
|
|
|
if (url == pageURL5) {
|
2018-09-06 20:38:28 +00:00
|
|
|
let html = `<html>
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
<head>
|
|
|
|
<title>Page Title</title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<a id="pdf-link" href="${pdfURL}">Download PDF</a>
|
|
|
|
</body>
|
|
|
|
</html>`;
|
2018-09-06 20:38:28 +00:00
|
|
|
|
|
|
|
return makeHTMLResponseFromType(html, options.responseType, pageURL5);
|
|
|
|
}
|
|
|
|
|
|
|
|
// JSON response with PDF download links
|
|
|
|
if (url == pageURL6) {
|
|
|
|
let response = {
|
|
|
|
oa_locations: [
|
|
|
|
{
|
|
|
|
url_for_landing_page: pageURL1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
url_for_pdf: pdfURL
|
|
|
|
}
|
|
|
|
]
|
|
|
|
};
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
return {
|
|
|
|
status: 200,
|
2018-09-06 20:38:28 +00:00
|
|
|
response,
|
|
|
|
responseURL: pageURL6,
|
|
|
|
getResponseHeader: makeGetResponseHeader({
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
})
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-09-06 20:38:28 +00:00
|
|
|
// DOI that redirects directly to a PDF
|
|
|
|
if (url == pageURL7) {
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
return {
|
|
|
|
status: 200,
|
2018-09-06 20:38:28 +00:00
|
|
|
response: pdfBlob,
|
|
|
|
responseURL: pdfURL,
|
|
|
|
getResponseHeader: makeGetResponseHeader({
|
|
|
|
'Content-Type': 'application/pdf'
|
|
|
|
})
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
// Returns a 429 every other call
|
|
|
|
if (url.startsWith(pageURL9)) {
|
|
|
|
if (return429) {
|
|
|
|
return429 = false;
|
|
|
|
throw new Zotero.HTTP.UnexpectedStatusException(
|
|
|
|
{
|
|
|
|
status: 429,
|
|
|
|
response: '',
|
|
|
|
responseURL: pageURL9,
|
|
|
|
getResponseHeader: makeGetResponseHeader({
|
|
|
|
'Content-Type': 'text/plain',
|
|
|
|
'Retry-After': '2',
|
|
|
|
})
|
|
|
|
},
|
|
|
|
pageURL9,
|
|
|
|
'Failing with 429'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return429 = true;
|
|
|
|
let html = getHTMLPage(true);
|
|
|
|
return makeHTMLResponseFromType(html, options.responseType, pageURL9);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-26 07:35:51 +00:00
|
|
|
if (url == pageURL10) {
|
|
|
|
let html = `<html><head><meta http-equiv=\"refresh\" content=\"2;url=${pageURL1}\"/></head><body></body></html>`;
|
|
|
|
return makeHTMLResponseFromType(html, options.responseType, pageURL10);
|
|
|
|
}
|
|
|
|
|
2018-08-07 08:08:47 +00:00
|
|
|
// OA PDF lookup
|
|
|
|
if (url.startsWith(ZOTERO_CONFIG.SERVICES_URL)) {
|
|
|
|
let json = JSON.parse(options.body);
|
|
|
|
let response = [];
|
|
|
|
if (json.doi == doi2) {
|
|
|
|
response.push({
|
|
|
|
url: pdfURL,
|
|
|
|
version: 'submittedVersion'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else if (json.doi == doi3) {
|
|
|
|
response.push({
|
|
|
|
pageURL: pageURL3,
|
|
|
|
version: 'submittedVersion'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
status: 200,
|
2018-09-06 20:38:28 +00:00
|
|
|
response,
|
|
|
|
getResponseHeader: makeGetResponseHeader({
|
|
|
|
'Content-Type': 'application/pdf'
|
|
|
|
})
|
2018-08-07 08:08:47 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
return origFunc(...arguments);
|
|
|
|
});
|
|
|
|
|
2018-09-06 20:38:28 +00:00
|
|
|
pdfSize = await OS.File.stat(pdfPath).size;
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
|
|
|
|
Zotero.Prefs.clear('findPDFs.resolvers');
|
2018-08-07 08:08:47 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(async function () {
|
|
|
|
httpd = new HttpServer();
|
|
|
|
httpd.start(port);
|
|
|
|
httpd.registerFile(
|
|
|
|
pdfURL.substr(baseURL.length - 1),
|
|
|
|
Zotero.File.pathToFile(OS.Path.join(getTestDataDirectory().path, 'test.pdf'))
|
|
|
|
);
|
2018-09-21 08:20:37 +00:00
|
|
|
|
|
|
|
requestStubCallTimes = [];
|
2018-08-07 08:08:47 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(async function () {
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
requestStub.resetHistory();
|
2018-08-07 08:08:47 +00:00
|
|
|
await new Promise((resolve) => {
|
|
|
|
httpd.stop(() => resolve());
|
|
|
|
});
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
Zotero.Prefs.clear('findPDFs.resolvers');
|
2018-10-06 05:38:32 +00:00
|
|
|
|
|
|
|
// Close progress dialog after each run
|
|
|
|
var queue = Zotero.ProgressQueues.get('findPDF');
|
|
|
|
if (queue) {
|
|
|
|
queue.getDialog().close();
|
|
|
|
}
|
2018-08-07 08:08:47 +00:00
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
after(() => {
|
|
|
|
Zotero.HTTP.request.restore();
|
|
|
|
});
|
|
|
|
|
2018-09-06 20:38:28 +00:00
|
|
|
it("should add a PDF from a resolved DOI webpage", async function () {
|
2018-08-07 08:08:47 +00:00
|
|
|
var doi = doi1;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
2018-09-06 20:38:28 +00:00
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.isTrue(requestStub.calledTwice);
|
|
|
|
assert.isTrue(requestStub.getCall(0).calledWith('GET', 'https://doi.org/' + doi));
|
2018-09-06 20:38:28 +00:00
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should add a PDF from a DOI that resolves directly to the file", async function () {
|
|
|
|
var doi = doi5;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
2018-08-07 08:08:47 +00:00
|
|
|
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
assert.isTrue(requestStub.calledOnce);
|
|
|
|
assert.isTrue(requestStub.calledWith('GET', 'https://doi.org/' + doi));
|
2018-08-07 08:08:47 +00:00
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
2018-08-30 19:13:04 +00:00
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should add a PDF from a resolved DOI from the Extra field", async function () {
|
|
|
|
var doi = doi1;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('extra', 'DOI: ' + doi);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.isTrue(requestStub.calledTwice);
|
|
|
|
assert.isTrue(requestStub.getCall(0).calledWith('GET', 'https://doi.org/' + doi));
|
2018-08-30 19:13:04 +00:00
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
2018-08-07 08:08:47 +00:00
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should add a PDF from a URL", async function () {
|
|
|
|
var url = pageURL1;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('url', url);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
assert.isTrue(requestStub.calledOnce);
|
|
|
|
assert.isTrue(requestStub.calledWith('GET', url));
|
2018-08-07 08:08:47 +00:00
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should add an OA PDF from a direct URL", async function () {
|
|
|
|
var doi = doi2;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.isTrue(requestStub.calledThrice);
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
var call1 = requestStub.getCall(0);
|
2018-08-07 08:08:47 +00:00
|
|
|
assert.isTrue(call1.calledWith('GET', 'https://doi.org/' + doi));
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
var call2 = requestStub.getCall(1);
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.isTrue(call2.calledWith('GET', pageURL2));
|
|
|
|
var call3 = requestStub.getCall(2);
|
|
|
|
assert.isTrue(call3.calledWith('POST', ZOTERO_CONFIG.SERVICES_URL + 'oa/search'));
|
2018-08-07 08:08:47 +00:00
|
|
|
|
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should add an OA PDF from a page URL", async function () {
|
|
|
|
var doi = doi3;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.equal(requestStub.callCount, 4);
|
2018-08-07 08:08:47 +00:00
|
|
|
// Check the DOI (and get nothing)
|
2018-09-21 08:20:37 +00:00
|
|
|
var call = requestStub.getCall(0);
|
|
|
|
assert.isTrue(call.calledWith('GET', 'https://doi.org/' + doi));
|
|
|
|
call = requestStub.getCall(1);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL2));
|
2018-08-07 08:08:47 +00:00
|
|
|
// Check the OA resolver and get page 3
|
2018-09-21 08:20:37 +00:00
|
|
|
call = requestStub.getCall(2);
|
|
|
|
assert.isTrue(call.calledWith('POST', ZOTERO_CONFIG.SERVICES_URL + 'oa/search'));
|
2018-08-07 08:08:47 +00:00
|
|
|
// Check page 3 and find the download URL
|
2018-09-21 08:20:37 +00:00
|
|
|
call = requestStub.getCall(3);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL3));
|
2018-08-07 08:08:47 +00:00
|
|
|
|
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
2020-02-03 04:34:57 +00:00
|
|
|
it("shouldn't try the URL-field URL again if it was already checked as the redirected DOI URL", async function () {
|
2018-08-07 08:08:47 +00:00
|
|
|
var doi = doi4;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
item.setField('url', pageURL4);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.equal(requestStub.callCount, 3);
|
|
|
|
var call = requestStub.getCall(0);
|
|
|
|
assert.isTrue(call.calledWith('GET', 'https://doi.org/' + doi));
|
|
|
|
call = requestStub.getCall(1);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL4));
|
|
|
|
call = requestStub.getCall(2);
|
|
|
|
assert.isTrue(call.calledWith('POST', ZOTERO_CONFIG.SERVICES_URL + 'oa/search'));
|
2018-08-07 08:08:47 +00:00
|
|
|
|
|
|
|
assert.isFalse(attachment);
|
|
|
|
});
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
it("should wait between requests to the same domain", async function () {
|
|
|
|
var url1 = pageURL1;
|
|
|
|
var item1 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item1.setField('title', 'Test');
|
|
|
|
item1.setField('url', url1);
|
|
|
|
await item1.saveTx();
|
|
|
|
|
|
|
|
var url2 = pageURL3;
|
|
|
|
var item2 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item2.setField('title', 'Test');
|
|
|
|
item2.setField('url', url2);
|
|
|
|
await item2.saveTx();
|
|
|
|
|
|
|
|
var attachments = await Zotero.Attachments.addAvailablePDFs([item1, item2]);
|
|
|
|
|
|
|
|
assert.isTrue(requestStub.calledTwice);
|
2019-01-29 12:35:39 +00:00
|
|
|
assert.isAbove(requestStubCallTimes[1] - requestStubCallTimes[0], 998);
|
2018-10-06 05:38:32 +00:00
|
|
|
// Make sure both items have attachments
|
|
|
|
assert.equal(item1.numAttachments(), 1);
|
|
|
|
assert.equal(item2.numAttachments(), 1);
|
2018-09-21 08:20:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should wait between requests that resolve to the same domain", async function () {
|
|
|
|
// DOI URL resolves to 'website' domain with PDF
|
|
|
|
var url1 = doiPrefix + doi1;
|
|
|
|
var item1 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item1.setField('title', 'Test');
|
|
|
|
item1.setField('url', url1);
|
|
|
|
await item1.saveTx();
|
|
|
|
|
|
|
|
// DOI URL resolves to 'website' domain without PDF
|
|
|
|
var url2 = doiPrefix + doi4;
|
|
|
|
var item2 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item2.setField('title', 'Test');
|
|
|
|
item2.setField('url', url2);
|
|
|
|
await item2.saveTx();
|
|
|
|
|
|
|
|
// DOI URL resolves to 'website2' domain without PDF
|
|
|
|
var url3 = doiPrefix + doi6;
|
|
|
|
var item3 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item3.setField('title', 'Test');
|
|
|
|
item3.setField('url', url3);
|
|
|
|
await item3.saveTx();
|
|
|
|
|
|
|
|
var attachments = await Zotero.Attachments.addAvailablePDFs([item1, item2, item3]);
|
|
|
|
|
|
|
|
assert.equal(requestStub.callCount, 6);
|
|
|
|
assert.equal(requestStub.getCall(0).args[1], doiPrefix + doi1);
|
|
|
|
assert.equal(requestStub.getCall(1).args[1], pageURL1);
|
|
|
|
assert.equal(requestStub.getCall(2).args[1], doiPrefix + doi4);
|
|
|
|
// Should skip ahead to the next DOI
|
|
|
|
assert.equal(requestStub.getCall(3).args[1], doiPrefix + doi6);
|
|
|
|
// which is on a new domain
|
|
|
|
assert.equal(requestStub.getCall(4).args[1], pageURL8);
|
|
|
|
// and then return to make 'website' request for DOI 4
|
|
|
|
assert.equal(requestStub.getCall(5).args[1], pageURL4);
|
|
|
|
|
|
|
|
// 'website' requests should be a second apart
|
2018-10-09 23:14:59 +00:00
|
|
|
assert.isAbove(requestStubCallTimes[5] - requestStubCallTimes[1], 999);
|
2018-09-21 08:20:37 +00:00
|
|
|
|
2018-10-06 05:38:32 +00:00
|
|
|
assert.equal(item1.numAttachments(), 1);
|
|
|
|
assert.equal(item2.numAttachments(), 0);
|
|
|
|
assert.equal(item3.numAttachments(), 1);
|
2018-09-21 08:20:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should wait between requests to the same domain after a 429", async function () {
|
|
|
|
var url1 = pageURL9;
|
|
|
|
var item1 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item1.setField('title', 'Test');
|
|
|
|
item1.setField('url', url1);
|
|
|
|
await item1.saveTx();
|
|
|
|
|
|
|
|
var url2 = pageURL3;
|
|
|
|
var item2 = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item2.setField('title', 'Test');
|
|
|
|
item2.setField('url', url2);
|
|
|
|
await item2.saveTx();
|
|
|
|
|
|
|
|
var attachments = await Zotero.Attachments.addAvailablePDFs([item1, item2]);
|
|
|
|
|
|
|
|
assert.isTrue(requestStub.calledThrice);
|
|
|
|
assert.equal(requestStub.getCall(0).args[1], pageURL9);
|
|
|
|
assert.equal(requestStub.getCall(1).args[1], pageURL9);
|
|
|
|
assert.equal(requestStub.getCall(2).args[1], pageURL3);
|
2018-10-09 23:14:59 +00:00
|
|
|
assert.isAbove(requestStubCallTimes[1] - requestStubCallTimes[0], 1999);
|
2018-10-06 05:38:32 +00:00
|
|
|
// Make sure both items have attachments
|
|
|
|
assert.equal(item1.numAttachments(), 1);
|
|
|
|
assert.equal(item2.numAttachments(), 1);
|
2018-09-21 08:20:37 +00:00
|
|
|
});
|
|
|
|
|
2018-11-26 07:35:51 +00:00
|
|
|
it("should follow a meta redirect", async function () {
|
|
|
|
var url = pageURL10;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('url', url);
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
|
|
|
assert.isTrue(requestStub.calledTwice);
|
|
|
|
assert.equal(requestStub.getCall(0).args[1], pageURL10)
|
|
|
|
assert.equal(requestStub.getCall(1).args[1], pageURL1)
|
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
it("should handle a custom resolver in HTML mode", async function () {
|
|
|
|
var doi = doi4;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
|
|
|
|
var resolvers = [{
|
|
|
|
name: 'Custom',
|
|
|
|
method: 'get',
|
|
|
|
url: 'http://website/{doi}',
|
|
|
|
mode: 'html',
|
|
|
|
selector: '#pdf-link',
|
|
|
|
attribute: 'href'
|
|
|
|
}];
|
|
|
|
Zotero.Prefs.set('findPDFs.resolvers', JSON.stringify(resolvers));
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.equal(requestStub.callCount, 4);
|
|
|
|
var call = requestStub.getCall(0);
|
|
|
|
assert.isTrue(call.calledWith('GET', 'https://doi.org/' + doi));
|
|
|
|
var call = requestStub.getCall(1);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL4));
|
|
|
|
call = requestStub.getCall(2);
|
|
|
|
assert.isTrue(call.calledWith('POST', ZOTERO_CONFIG.SERVICES_URL + 'oa/search'));
|
|
|
|
call = requestStub.getCall(3);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL5));
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
|
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should handle a custom resolver in JSON mode with URL strings", async function () {
|
|
|
|
var doi = doi4;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
|
|
|
|
var resolvers = [{
|
|
|
|
name: 'Custom',
|
|
|
|
method: 'get',
|
|
|
|
url: 'http://website/{doi}/json',
|
|
|
|
mode: 'json',
|
|
|
|
selector: '.oa_locations.url_for_pdf'
|
|
|
|
}];
|
|
|
|
Zotero.Prefs.set('findPDFs.resolvers', JSON.stringify(resolvers));
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.equal(requestStub.callCount, 4);
|
|
|
|
var call = requestStub.getCall(0);
|
|
|
|
assert.isTrue(call.calledWith('GET', 'https://doi.org/' + doi));
|
|
|
|
call = requestStub.getCall(1);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL4));
|
|
|
|
call = requestStub.getCall(2);
|
|
|
|
assert.isTrue(call.calledWith('POST', ZOTERO_CONFIG.SERVICES_URL + 'oa/search'));
|
|
|
|
call = requestStub.getCall(3);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL6));
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
|
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should handle a custom resolver in JSON mode with mapped properties", async function () {
|
|
|
|
var doi = doi4;
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('title', 'Test');
|
|
|
|
item.setField('DOI', doi);
|
|
|
|
await item.saveTx();
|
|
|
|
|
|
|
|
var resolvers = [{
|
|
|
|
name: 'Custom',
|
|
|
|
method: 'get',
|
|
|
|
url: 'http://website/{doi}/json',
|
|
|
|
mode: 'json',
|
|
|
|
selector: '.oa_locations',
|
|
|
|
mappings: {
|
|
|
|
url: 'url_for_pdf',
|
|
|
|
pageURL: 'url_for_landing_page',
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
Zotero.Prefs.set('findPDFs.resolvers', JSON.stringify(resolvers));
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
2018-09-21 08:20:37 +00:00
|
|
|
assert.equal(requestStub.callCount, 5);
|
|
|
|
var call = requestStub.getCall(0);
|
|
|
|
assert.isTrue(call.calledWith('GET', 'https://doi.org/' + doi));
|
|
|
|
call = requestStub.getCall(1);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL4));
|
|
|
|
call = requestStub.getCall(2);
|
|
|
|
assert.isTrue(call.calledWith('POST', ZOTERO_CONFIG.SERVICES_URL + 'oa/search'));
|
|
|
|
call = requestStub.getCall(3);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL6));
|
|
|
|
call = requestStub.getCall(4);
|
|
|
|
assert.isTrue(call.calledWith('GET', pageURL1));
|
Automatically download open-access PDFs when saving via the connector
If there's no translated PDF or the translated PDF fails and the item
has a DOI, check Zotero's Unpaywall mirror for possible sources and try
to download one of those.
Unlike with "Add Item by Identifier" and "Find Available PDF" in the
item context menu, this does not try the DOI/URL page, since it would
result in more data leakage and most of the time you'd be saving from
the DOI page already. We could consider offering it as an option, but
for it to be useful, you'd have to have an institutional subscription,
be on-campus or connected via VPN (for now), and be saving from
somewhere other than the main page.
A new connector endpoint, sessionProgress, takes the place of
attachmentProgress. Unlike attachmentProgress, sessionProgress can show
new attachments that have been added to the save, and with a little more
work should also be able to show when a parent item has been recognized
for a directly saved PDF.
This also adds support for custom PDF resolvers, available to all PDF
retrieval methods. I'll document those separately.
Closes #1542
2018-08-15 07:34:28 +00:00
|
|
|
|
|
|
|
assert.ok(attachment);
|
|
|
|
var json = attachment.toJSON();
|
|
|
|
assert.equal(json.url, pdfURL);
|
|
|
|
assert.equal(json.contentType, 'application/pdf');
|
|
|
|
assert.equal(json.filename, 'Test.pdf');
|
|
|
|
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
|
|
|
|
});
|
2018-08-07 08:08:47 +00:00
|
|
|
});
|
|
|
|
|
2020-06-02 19:31:12 +00:00
|
|
|
describe("#getFileBaseNameFromItem()", function () {
|
|
|
|
it("should strip HTML tags from title", async function () {
|
|
|
|
var item = createUnsavedDataObject('item', { title: 'Foo <i>Bar</i> Foo<br><br/><br />Bar' });
|
|
|
|
var str = Zotero.Attachments.getFileBaseNameFromItem(item);
|
|
|
|
assert.equal(str, 'Foo Bar Foo Bar');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-05-09 06:30:00 +00:00
|
|
|
describe("#getBaseDirectoryRelativePath()", function () {
|
2017-08-18 14:04:22 +00:00
|
|
|
it("should handle base directory at Windows drive root", function () {
|
|
|
|
Zotero.Prefs.set('baseAttachmentPath', "C:\\");
|
|
|
|
var path = Zotero.Attachments.getBaseDirectoryRelativePath("C:\\file.txt");
|
|
|
|
assert.equal(path, Zotero.Attachments.BASE_PATH_PLACEHOLDER + "file.txt");
|
|
|
|
});
|
|
|
|
|
2016-05-09 06:30:00 +00:00
|
|
|
it("should convert backslashes to forward slashes", function () {
|
|
|
|
Zotero.Prefs.set('baseAttachmentPath', "C:\\foo\\bar");
|
|
|
|
var path = Zotero.Attachments.getBaseDirectoryRelativePath("C:\\foo\\bar\\test\\file.txt");
|
|
|
|
assert.equal(path, Zotero.Attachments.BASE_PATH_PLACEHOLDER + "test/file.txt");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-08-09 08:52:14 +00:00
|
|
|
describe("#getTotalFileSize", function () {
|
|
|
|
it("should return the size for a single-file attachment", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
|
|
|
|
// Create attachment and compare content
|
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
|
|
|
file: file
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal((yield Zotero.Attachments.getTotalFileSize(item)), file.fileSize);
|
|
|
|
})
|
|
|
|
})
|
2015-08-10 05:55:55 +00:00
|
|
|
|
|
|
|
describe("#hasMultipleFiles and #getNumFiles()", function () {
|
|
|
|
it("should return false and 1 for a single file", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
|
|
|
|
// Create attachment and compare content
|
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
|
|
|
file: file
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.isFalse(yield Zotero.Attachments.hasMultipleFiles(item));
|
|
|
|
assert.equal((yield Zotero.Attachments.getNumFiles(item)), 1);
|
|
|
|
})
|
|
|
|
|
|
|
|
it("should return false and 1 for single HTML file with hidden file", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.html');
|
|
|
|
|
|
|
|
// Create attachment and compare content
|
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
|
|
|
file: file
|
|
|
|
});
|
|
|
|
var path = OS.Path.join(OS.Path.dirname(item.getFilePath()), '.zotero-ft-cache');
|
|
|
|
yield Zotero.File.putContentsAsync(path, "");
|
|
|
|
|
|
|
|
assert.isFalse(yield Zotero.Attachments.hasMultipleFiles(item));
|
|
|
|
assert.equal((yield Zotero.Attachments.getNumFiles(item)), 1);
|
|
|
|
})
|
|
|
|
|
|
|
|
it("should return true and 2 for multiple files", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.html');
|
|
|
|
|
|
|
|
// Create attachment and compare content
|
|
|
|
var item = yield Zotero.Attachments.importFromFile({
|
|
|
|
file: file
|
|
|
|
});
|
|
|
|
var path = OS.Path.join(OS.Path.dirname(item.getFilePath()), 'test.png');
|
|
|
|
yield Zotero.File.putContentsAsync(path, "");
|
|
|
|
|
|
|
|
assert.isTrue(yield Zotero.Attachments.hasMultipleFiles(item));
|
|
|
|
assert.equal((yield Zotero.Attachments.getNumFiles(item)), 2);
|
|
|
|
})
|
2016-12-12 08:26:35 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe("#createDirectoryForItem()", function () {
|
|
|
|
it("should create missing directory", function* () {
|
|
|
|
var item = yield importFileAttachment('test.png');
|
|
|
|
var path = OS.Path.dirname(item.getFilePath());
|
|
|
|
yield OS.File.removeDir(path);
|
|
|
|
yield Zotero.Attachments.createDirectoryForItem(item);
|
|
|
|
assert.isTrue(yield OS.File.exists(path));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should delete all existing files", function* () {
|
|
|
|
var item = yield importFileAttachment('test.html');
|
|
|
|
var path = OS.Path.dirname(item.getFilePath());
|
|
|
|
var files = ['a', 'b', 'c', 'd'];
|
|
|
|
for (let file of files) {
|
|
|
|
yield Zotero.File.putContentsAsync(OS.Path.join(path, file), file);
|
|
|
|
}
|
|
|
|
yield Zotero.Attachments.createDirectoryForItem(item);
|
|
|
|
assert.isTrue(yield Zotero.File.directoryIsEmpty(path));
|
|
|
|
assert.isTrue(yield OS.File.exists(path));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should handle empty directory", function* () {
|
|
|
|
var item = yield importFileAttachment('test.png');
|
|
|
|
var file = item.getFilePath();
|
|
|
|
var dir = OS.Path.dirname(item.getFilePath());
|
|
|
|
yield OS.File.remove(file);
|
|
|
|
yield Zotero.Attachments.createDirectoryForItem(item);
|
|
|
|
assert.isTrue(yield OS.File.exists(dir));
|
|
|
|
});
|
|
|
|
});
|
2019-08-18 20:22:39 +00:00
|
|
|
|
|
|
|
describe("#convertLinkedFileToStoredFile()", function () {
|
|
|
|
it("should copy a linked file to a stored file", async function () {
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
var relatedItem = await createDataObject('item');
|
|
|
|
|
|
|
|
var originalFile = OS.Path.join(getTestDataDirectory().path, 'test.pdf');
|
|
|
|
var attachment = await Zotero.Attachments.linkFromFile({
|
|
|
|
file: originalFile,
|
|
|
|
title: 'Title',
|
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
attachment.setNote('Note');
|
|
|
|
attachment.setTags([{ tag: 'Tag' }]);
|
|
|
|
attachment.addRelatedItem(relatedItem);
|
|
|
|
await attachment.saveTx();
|
|
|
|
relatedItem.addRelatedItem(attachment);
|
|
|
|
await relatedItem.saveTx();
|
|
|
|
// Make sure we're indexed
|
|
|
|
await Zotero.Fulltext.indexItems([attachment.id]);
|
|
|
|
|
|
|
|
var newAttachment = await Zotero.Attachments.convertLinkedFileToStoredFile(attachment);
|
|
|
|
|
|
|
|
assert.isFalse(Zotero.Items.exists(attachment.id));
|
|
|
|
assert.isTrue(await OS.File.exists(originalFile));
|
|
|
|
assert.equal(newAttachment.attachmentLinkMode, Zotero.Attachments.LINK_MODE_IMPORTED_FILE);
|
|
|
|
assert.equal(newAttachment.attachmentContentType, 'application/pdf');
|
|
|
|
assert.isTrue(await newAttachment.fileExists());
|
|
|
|
assert.equal(newAttachment.getField('title'), 'Title');
|
|
|
|
assert.equal(newAttachment.getNote(), 'Note');
|
|
|
|
assert.sameDeepMembers(newAttachment.getTags(), [{ tag: 'Tag' }]);
|
|
|
|
assert.sameMembers(newAttachment.relatedItems, [relatedItem.key]);
|
|
|
|
assert.sameMembers(relatedItem.relatedItems, [newAttachment.key]);
|
|
|
|
assert.isTrue(await OS.File.exists(Zotero.Fulltext.getItemCacheFile(newAttachment).path));
|
|
|
|
assert.equal(
|
|
|
|
await Zotero.Fulltext.getIndexedState(newAttachment),
|
|
|
|
Zotero.Fulltext.INDEX_STATE_INDEXED
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it("should move a linked file to a stored file with `move: true`", async function () {
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
|
|
|
|
var originalFile = OS.Path.join(Zotero.getTempDirectory().path, 'test.png');
|
|
|
|
await OS.File.copy(
|
|
|
|
OS.Path.join(getTestDataDirectory().path, 'test.png'),
|
|
|
|
originalFile
|
|
|
|
);
|
|
|
|
var attachment = await Zotero.Attachments.linkFromFile({
|
|
|
|
file: originalFile,
|
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
var newAttachment = await Zotero.Attachments.convertLinkedFileToStoredFile(
|
|
|
|
attachment,
|
|
|
|
{
|
|
|
|
move: true
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.isFalse(Zotero.Items.exists(attachment.id));
|
|
|
|
assert.isFalse(await OS.File.exists(originalFile));
|
|
|
|
assert.equal(newAttachment.attachmentLinkMode, Zotero.Attachments.LINK_MODE_IMPORTED_FILE);
|
|
|
|
assert.isTrue(await newAttachment.fileExists());
|
|
|
|
});
|
|
|
|
});
|
2015-04-26 21:42:29 +00:00
|
|
|
})
|