2015-04-26 21:42:29 +00:00
|
|
|
describe("Zotero.Attachments", function() {
|
2023-04-14 15:37:07 +00:00
|
|
|
var HiddenBrowser;
|
|
|
|
var browser;
|
2015-04-26 21:42:29 +00:00
|
|
|
|
2023-04-14 15:37:07 +00:00
|
|
|
before(function () {
|
|
|
|
HiddenBrowser = ChromeUtils.import("chrome://zotero/content/HiddenBrowser.jsm").HiddenBrowser;
|
2015-04-26 21:42:29 +00:00
|
|
|
});
|
2023-04-14 15:37:07 +00:00
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
if (browser) {
|
|
|
|
HiddenBrowser.destroy(browser);
|
|
|
|
browser = null;
|
2015-04-26 21:42:29 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
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
|
|
|
|
2022-06-17 08:57:34 +00:00
|
|
|
it("should index JavaScript-created text in an HTML file", async function () {
|
2018-06-19 00:17:37 +00:00
|
|
|
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');
|
2022-06-17 08:57:34 +00:00
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
2018-06-19 00:17:37 +00:00
|
|
|
});
|
2016-03-22 04:40:59 +00:00
|
|
|
});
|
|
|
|
|
2021-12-02 09:27:33 +00:00
|
|
|
|
|
|
|
describe("#importFromURL()", function () {
|
|
|
|
it("should download a PDF from a JS redirect page", async function () {
|
|
|
|
this.timeout(65e3);
|
|
|
|
|
|
|
|
var item = await Zotero.Attachments.importFromURL({
|
|
|
|
libraryID: Zotero.Libraries.userLibraryID,
|
|
|
|
url: 'https://zotero-static.s3.amazonaws.com/test-pdf-redirect.html',
|
|
|
|
contentType: 'application/pdf'
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.isTrue(item.isPDFAttachment());
|
|
|
|
var sample = await Zotero.File.getContentsAsync(item.getFilePath(), null, 1000);
|
|
|
|
assert.equal(Zotero.MIME.sniffForMIMEType(sample), 'application/pdf');
|
|
|
|
|
|
|
|
// Clean up
|
|
|
|
await Zotero.Items.erase(item.id);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
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");
|
2023-04-14 15:37:07 +00:00
|
|
|
browser = yield HiddenBrowser.create(uri);
|
2016-02-11 07:54:52 +00:00
|
|
|
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
var attachment = yield Zotero.Attachments.linkFromDocument({
|
2023-04-14 15:37:07 +00:00
|
|
|
document: yield HiddenBrowser.getDocument(browser),
|
2016-02-11 07:54:52 +00:00
|
|
|
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 () {
|
2020-07-17 22:14:10 +00:00
|
|
|
Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
|
|
|
Components.utils.import("resource://zotero-unit/httpd.js");
|
2020-10-12 23:53:48 +00:00
|
|
|
var testServerPath, httpd, prefix;
|
2020-07-17 22:14:10 +00:00
|
|
|
var testServerPort = 16213;
|
|
|
|
|
|
|
|
before(async function () {
|
|
|
|
this.timeout(20000);
|
|
|
|
Zotero.Prefs.set("httpServer.enabled", true);
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(function () {
|
2020-10-12 23:53:48 +00:00
|
|
|
prefix = Zotero.Utilities.randomString();
|
2020-07-17 22:14:10 +00:00
|
|
|
// Alternate ports to prevent exceptions not catchable in JS
|
2020-10-12 23:53:48 +00:00
|
|
|
// Use random prefix because httpd does not actually stop between tests
|
|
|
|
testServerPath = 'http://127.0.0.1:' + testServerPort + '/' + prefix;
|
2020-07-17 22:14:10 +00:00
|
|
|
httpd = new HttpServer();
|
|
|
|
httpd.start(testServerPort);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(async function () {
|
|
|
|
var defer = new Zotero.Promise.defer();
|
|
|
|
httpd.stop(() => defer.resolve());
|
|
|
|
await defer.promise;
|
|
|
|
});
|
|
|
|
|
2020-10-23 23:39:07 +00:00
|
|
|
it("should save a document with embedded files", async function () {
|
|
|
|
var item = await createDataObject('item');
|
2020-07-17 22:14:10 +00:00
|
|
|
|
|
|
|
var uri = OS.Path.join(getTestDataDirectory().path, "snapshot");
|
2020-10-12 23:53:48 +00:00
|
|
|
httpd.registerDirectory("/" + prefix + "/", new FileUtils.File(uri));
|
2016-05-31 22:03:40 +00:00
|
|
|
|
2023-04-14 15:37:07 +00:00
|
|
|
browser = await HiddenBrowser.create(testServerPath + "/index.html");
|
2020-10-23 23:39:07 +00:00
|
|
|
var attachment = await Zotero.Attachments.importFromDocument({
|
2023-04-14 15:37:07 +00:00
|
|
|
browser,
|
2016-05-31 22:03:40 +00:00
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
2020-07-17 22:14:10 +00:00
|
|
|
assert.equal(attachment.getField('url'), testServerPath + "/index.html");
|
2016-05-31 22:03:40 +00:00
|
|
|
|
|
|
|
// Check indexing
|
2020-10-23 23:39:07 +00:00
|
|
|
var matches = await Zotero.Fulltext.findTextInItems([attachment.id], 'share your research');
|
2016-05-31 22:03:40 +00:00
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
|
|
|
|
|
|
|
var storageDir = Zotero.Attachments.getStorageDirectory(attachment).path;
|
2020-10-23 23:39:07 +00:00
|
|
|
var file = await attachment.getFilePathAsync();
|
2016-05-31 22:03:40 +00:00
|
|
|
assert.equal(OS.Path.basename(file), 'index.html');
|
2020-07-17 22:14:10 +00:00
|
|
|
|
|
|
|
// Check attachment html file contents
|
|
|
|
let path = OS.Path.join(storageDir, 'index.html');
|
2020-10-23 23:39:07 +00:00
|
|
|
assert.isTrue(await OS.File.exists(path));
|
|
|
|
let contents = await Zotero.File.getContentsAsync(path);
|
2021-01-18 08:52:00 +00:00
|
|
|
assert.include(contents, "><!--\n Page saved with SingleFile");
|
2020-10-23 23:39:07 +00:00
|
|
|
|
|
|
|
// Check attachment base64 contents
|
2020-07-17 22:14:10 +00:00
|
|
|
let expectedPath = getTestDataDirectory();
|
|
|
|
expectedPath.append('snapshot');
|
|
|
|
expectedPath.append('img.gif');
|
2020-10-23 23:39:07 +00:00
|
|
|
let needle = await Zotero.File.getBinaryContentsAsync(expectedPath);
|
|
|
|
needle = '<img src=data:image/gif;base64,' + btoa(needle) + '>';
|
|
|
|
assert.include(contents, needle);
|
2020-07-17 22:14:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should save a document with embedded files restricted by CORS", async function () {
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
|
|
|
|
var url = "file://" + OS.Path.join(getTestDataDirectory().path, "snapshot", "img.gif");
|
|
|
|
httpd.registerPathHandler(
|
2020-10-12 23:53:48 +00:00
|
|
|
'/' + prefix + '/index.html',
|
2020-07-17 22:14:10 +00:00
|
|
|
{
|
|
|
|
handle: function (request, response) {
|
|
|
|
response.setStatusLine(null, 200, "OK");
|
|
|
|
response.write(`<html><head><title>Test</title></head><body><img src="${url}"/>`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-04-14 15:37:07 +00:00
|
|
|
browser = await HiddenBrowser.create(testServerPath + "/index.html");
|
2020-07-17 22:14:10 +00:00
|
|
|
var attachment = await Zotero.Attachments.importFromDocument({
|
2023-04-14 15:37:07 +00:00
|
|
|
browser,
|
2020-07-17 22:14:10 +00:00
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getField('url'), testServerPath + "/index.html");
|
|
|
|
|
|
|
|
// Check for embedded files
|
|
|
|
var storageDir = Zotero.Attachments.getStorageDirectory(attachment).path;
|
|
|
|
var file = await attachment.getFilePathAsync();
|
|
|
|
assert.equal(OS.Path.basename(file), 'index.html');
|
|
|
|
|
|
|
|
// Check attachment html file contents
|
|
|
|
let path = OS.Path.join(storageDir, 'index.html');
|
|
|
|
assert.isTrue(await OS.File.exists(path));
|
|
|
|
let contents = await Zotero.File.getContentsAsync(path);
|
2021-01-18 08:52:00 +00:00
|
|
|
assert.include(contents, "><!--\n Page saved with SingleFile");
|
2020-07-17 22:14:10 +00:00
|
|
|
|
2020-10-23 23:39:07 +00:00
|
|
|
// Check attachment base64 contents
|
2020-07-17 22:14:10 +00:00
|
|
|
let expectedPath = getTestDataDirectory();
|
|
|
|
expectedPath.append('snapshot');
|
|
|
|
expectedPath.append('img.gif');
|
2020-10-23 23:39:07 +00:00
|
|
|
// This is broken because the browser will not load the image due to CORS and
|
|
|
|
// then SingleFile detects that it is an empty image and replaces it without
|
|
|
|
// trying to load the file. I don't really know of a good way around this for
|
|
|
|
// the moment so I am leaving this assertion commented out, but without the
|
|
|
|
// test is much less useful.
|
|
|
|
// let needle = await Zotero.File.getBinaryContentsAsync(expectedPath);
|
|
|
|
// needle = '<img src=data:image/gif;base64,' + btoa(needle) + '>';
|
2020-10-27 21:58:44 +00:00
|
|
|
// assert.include(contents, needle);
|
2020-07-17 22:14:10 +00:00
|
|
|
});
|
2020-09-28 17:43:32 +00:00
|
|
|
|
|
|
|
it("should save a document with embedded files that throw errors", async function () {
|
|
|
|
var item = await createDataObject('item');
|
|
|
|
|
|
|
|
var url = "file://" + OS.Path.join(getTestDataDirectory().path, "snapshot", "foobar.gif");
|
|
|
|
httpd.registerPathHandler(
|
2020-10-12 23:53:48 +00:00
|
|
|
'/' + prefix + '/index.html',
|
2020-09-28 17:43:32 +00:00
|
|
|
{
|
|
|
|
handle: function (request, response) {
|
|
|
|
response.setStatusLine(null, 200, "OK");
|
|
|
|
response.write(`<html><head><title>Test</title></head><body><img src="${url}"/>`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-04-14 15:37:07 +00:00
|
|
|
browser = await HiddenBrowser.create(testServerPath + "/index.html");
|
2020-09-28 17:43:32 +00:00
|
|
|
var attachment = await Zotero.Attachments.importFromDocument({
|
2023-04-14 15:37:07 +00:00
|
|
|
browser,
|
2020-09-28 17:43:32 +00:00
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getField('url'), testServerPath + "/index.html");
|
|
|
|
|
|
|
|
// Check for embedded files
|
|
|
|
var storageDir = Zotero.Attachments.getStorageDirectory(attachment).path;
|
|
|
|
var file = await attachment.getFilePathAsync();
|
|
|
|
assert.equal(OS.Path.basename(file), 'index.html');
|
|
|
|
assert.isFalse(await OS.File.exists(OS.Path.join(storageDir, 'images', '1.gif')));
|
|
|
|
|
|
|
|
// Check attachment html file contents
|
|
|
|
let path = OS.Path.join(storageDir, 'index.html');
|
|
|
|
assert.isTrue(await OS.File.exists(path));
|
|
|
|
let contents = await Zotero.File.getContentsAsync(path);
|
2021-01-18 08:52:00 +00:00
|
|
|
assert.include(contents, "><!--\n Page saved with SingleFile");
|
2020-10-27 21:58:44 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should save a document but not save the iframe", async function () {
|
|
|
|
let item = await createDataObject('item');
|
|
|
|
|
|
|
|
let content = `<html><head><title>Test</title></head><body><iframe src="${testServerPath + "/iframe.html"}"/>`;
|
|
|
|
httpd.registerPathHandler(
|
|
|
|
'/' + prefix + '/index.html',
|
|
|
|
{
|
|
|
|
handle: function (request, response) {
|
|
|
|
response.setStatusLine(null, 200, "OK");
|
|
|
|
response.write(content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
let url = "file://" + OS.Path.join(getTestDataDirectory().path, "snapshot", "img.gif");
|
|
|
|
httpd.registerPathHandler(
|
|
|
|
'/' + prefix + '/iframe.html',
|
|
|
|
{
|
|
|
|
handle: function (request, response) {
|
|
|
|
response.setStatusLine(null, 200, "OK");
|
|
|
|
response.write(`<html><head><title>Test</title></head><body><img src="${url}"/>`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-04-14 15:37:07 +00:00
|
|
|
browser = await HiddenBrowser.create(testServerPath + "/index.html");
|
2020-10-27 21:58:44 +00:00
|
|
|
let attachment = await Zotero.Attachments.importFromDocument({
|
2023-04-14 15:37:07 +00:00
|
|
|
browser,
|
2020-10-27 21:58:44 +00:00
|
|
|
parentItemID: item.id
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getField('url'), testServerPath + "/index.html");
|
|
|
|
|
|
|
|
// Check for embedded files
|
|
|
|
var storageDir = Zotero.Attachments.getStorageDirectory(attachment).path;
|
|
|
|
var file = await attachment.getFilePathAsync();
|
|
|
|
assert.equal(OS.Path.basename(file), 'index.html');
|
|
|
|
assert.isFalse(await OS.File.exists(OS.Path.join(storageDir, 'images', '1.gif')));
|
|
|
|
|
|
|
|
// Check attachment html file contents
|
|
|
|
let path = OS.Path.join(storageDir, 'index.html');
|
|
|
|
assert.isTrue(await OS.File.exists(path));
|
|
|
|
let contents = await Zotero.File.getContentsAsync(path);
|
|
|
|
assert.include(contents, "><!--\n Page saved with SingleFile");
|
|
|
|
assert.notInclude(contents, "<img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\">'></iframe>");
|
2020-09-28 17:43:32 +00:00
|
|
|
});
|
2020-07-17 22:14:10 +00:00
|
|
|
});
|
|
|
|
|
2020-10-23 23:39:07 +00:00
|
|
|
describe("#importFromSnapshotContent()", function () {
|
|
|
|
it("should save simple HTML content", async function () {
|
2020-07-17 22:14:10 +00:00
|
|
|
let item = await createDataObject('item');
|
|
|
|
|
|
|
|
let content = getTestDataDirectory();
|
|
|
|
content.append('snapshot');
|
|
|
|
content.append('index.html');
|
|
|
|
|
2020-10-23 23:39:07 +00:00
|
|
|
let snapshotContent = await Zotero.File.getContentsAsync(content);
|
2020-07-17 22:14:10 +00:00
|
|
|
|
2020-10-23 23:39:07 +00:00
|
|
|
let attachment = await Zotero.Attachments.importFromSnapshotContent({
|
2020-07-17 22:14:10 +00:00
|
|
|
parentItemID: item.id,
|
|
|
|
url: "https://example.com/test.html",
|
|
|
|
title: "Testing Title",
|
2020-10-23 23:39:07 +00:00
|
|
|
snapshotContent
|
2020-07-17 22:14:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(attachment.getField('url'), "https://example.com/test.html");
|
|
|
|
|
|
|
|
// Check indexing
|
|
|
|
let matches = await Zotero.Fulltext.findTextInItems([attachment.id], 'share your research');
|
|
|
|
assert.lengthOf(matches, 1);
|
|
|
|
assert.propertyVal(matches[0], 'id', attachment.id);
|
|
|
|
|
|
|
|
// Check for embedded files
|
|
|
|
let storageDir = Zotero.Attachments.getStorageDirectory(attachment).path;
|
|
|
|
let file = await attachment.getFilePathAsync();
|
|
|
|
assert.equal(OS.Path.basename(file), 'test.html');
|
|
|
|
|
|
|
|
// Check attachment html file contents
|
|
|
|
let path = OS.Path.join(storageDir, 'test.html');
|
|
|
|
assert.isTrue(await OS.File.exists(path));
|
|
|
|
let contents = await Zotero.File.getContentsAsync(path);
|
|
|
|
let expectedContents = await Zotero.File.getContentsAsync(file);
|
|
|
|
assert.equal(contents, expectedContents);
|
2016-05-31 22:03:40 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-11-16 23:34:38 +00:00
|
|
|
describe("Find Available PDF", 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],
|
2022-10-30 08:44:31 +00:00
|
|
|
|
|
|
|
// Redirect loop
|
|
|
|
['http://website/redirect_loop1', 'http://website/redirect_loop2', false],
|
|
|
|
['http://website/redirect_loop2', 'http://website/redirect_loop3', false],
|
|
|
|
['http://website/redirect_loop3', 'http://website/redirect_loop1', false],
|
|
|
|
|
|
|
|
// Too many total redirects
|
|
|
|
['http://website/too_many_redirects1', 'http://website/too_many_redirects2', false],
|
|
|
|
['http://website/too_many_redirects2', 'http://website/too_many_redirects3', false],
|
|
|
|
['http://website/too_many_redirects3', 'http://website/too_many_redirects4', false],
|
|
|
|
['http://website/too_many_redirects4', 'http://website/too_many_redirects5', false],
|
|
|
|
['http://website/too_many_redirects5', 'http://website/too_many_redirects6', false],
|
|
|
|
['http://website/too_many_redirects6', 'http://website/too_many_redirects7', false],
|
|
|
|
['http://website/too_many_redirects7', 'http://website/too_many_redirects8', false],
|
|
|
|
['http://website/too_many_redirects8', 'http://website/too_many_redirects9', false],
|
|
|
|
['http://website/too_many_redirects9', 'http://website/too_many_redirects10', false],
|
|
|
|
['http://website/too_many_redirects10', 'http://website/too_many_redirects11', false],
|
|
|
|
['http://website/too_many_redirects11', pageURL1, 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({
|
2022-11-16 23:32:42 +00:00
|
|
|
'Content-Type': 'application/json'
|
2018-09-06 20:38:28 +00:00
|
|
|
})
|
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
|
|
|
|
2022-11-16 23:32:17 +00:00
|
|
|
// Generate a page with a relative PDF URL
|
|
|
|
httpd.registerPathHandler(
|
|
|
|
"/" + doi4,
|
|
|
|
{
|
|
|
|
handle: function (request, response) {
|
|
|
|
response.setStatusLine(null, 200, "OK");
|
|
|
|
response.write(`<html>
|
|
|
|
<head>
|
|
|
|
<title>Page Title</title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<a id="pdf-link" href="/article1/pdf">Download PDF</a>
|
|
|
|
</body>
|
|
|
|
</html>`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
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
|
2021-02-09 22:12:25 +00:00
|
|
|
assert.isAbove(requestStubCallTimes[5] - requestStubCallTimes[1], 995);
|
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);
|
|
|
|
});
|
|
|
|
|
2022-10-30 08:44:31 +00:00
|
|
|
it("should stop after too many redirects to the same URL", async function () {
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('url', 'http://website/redirect_loop1');
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
assert.isFalse(attachment);
|
|
|
|
assert.equal(requestStub.callCount, 7);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should stop after too many total redirects for a given page URL", async function () {
|
|
|
|
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
|
|
|
|
item.setField('url', 'http://website/too_many_redirects1');
|
|
|
|
await item.saveTx();
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
assert.isFalse(attachment);
|
|
|
|
assert.equal(requestStub.callCount, 10);
|
|
|
|
});
|
|
|
|
|
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);
|
|
|
|
});
|
|
|
|
|
2022-11-16 23:32:17 +00:00
|
|
|
it("should handle a custom resolver with a relative PDF path 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',
|
|
|
|
// Registered with httpd.js in beforeEach()
|
|
|
|
url: baseURL + "{doi}",
|
|
|
|
mode: 'html',
|
|
|
|
selector: '#pdf-link',
|
|
|
|
attribute: 'href'
|
|
|
|
}];
|
|
|
|
Zotero.Prefs.set('findPDFs.resolvers', JSON.stringify(resolvers));
|
|
|
|
|
|
|
|
var attachment = await Zotero.Attachments.addAvailablePDF(item);
|
|
|
|
|
|
|
|
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'));
|
|
|
|
var call = requestStub.getCall(3);
|
|
|
|
assert.isTrue(call.calledWith('GET', baseURL + doi4));
|
|
|
|
|
|
|
|
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 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');
|
2020-08-25 18:22:23 +00:00
|
|
|
assert.equal(newAttachment.note, 'Note');
|
2019-08-18 20:22:39 +00:00
|
|
|
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
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2021-03-12 11:26:59 +00:00
|
|
|
it("should move annotations to 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
|
|
|
|
});
|
|
|
|
var annotation1 = await createAnnotation('highlight', attachment);
|
|
|
|
var annotation2 = await createAnnotation('note', attachment);
|
|
|
|
|
|
|
|
var newAttachment = await Zotero.Attachments.convertLinkedFileToStoredFile(attachment);
|
|
|
|
|
|
|
|
assert.isFalse(Zotero.Items.exists(attachment.id));
|
|
|
|
assert.isTrue(Zotero.Items.exists(annotation1.id));
|
|
|
|
assert.isTrue(Zotero.Items.exists(annotation2.id));
|
|
|
|
|
|
|
|
var annotations = newAttachment.getAnnotations();
|
|
|
|
assert.lengthOf(annotations, 2);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2019-08-18 20:22:39 +00:00
|
|
|
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
|
|
|
})
|