Automatically relink attachments from LABD (#2374)

Fixes #2092
This commit is contained in:
Abe Jellinek 2022-03-01 11:34:46 -08:00
parent ecd0e50ac4
commit 5f9e8f5b7e
7 changed files with 437 additions and 14 deletions

View file

@ -1269,4 +1269,169 @@ describe("ZoteroPane", function() {
assert.isFalse(attachment3.deleted);
});
});
describe("#checkForLinkedFilesToRelink()", function () {
let labdDir;
this.beforeEach(async () => {
labdDir = await getTempDirectory();
Zotero.Prefs.set('baseAttachmentPath', labdDir);
Zotero.Prefs.set('saveRelativeAttachmentPath', true);
});
it("should detect and relink a single attachment", async function () {
let item = await createDataObject('item');
let file = getTestDataDirectory();
file.append('test.pdf');
let outsideStorageDir = await getTempDirectory();
let outsideFile = OS.Path.join(outsideStorageDir, 'test.pdf');
let labdFile = OS.Path.join(labdDir, 'test.pdf');
await OS.File.copy(file.path, outsideFile);
let attachment = await Zotero.Attachments.linkFromFile({
file: outsideFile,
parentItemID: item.id
});
await assert.eventually.isTrue(attachment.fileExists());
await OS.File.move(outsideFile, labdFile);
await assert.eventually.isFalse(attachment.fileExists());
let stub = sinon.stub(zp, 'showLinkedFileFoundAutomaticallyDialog')
.returns('one');
await zp.checkForLinkedFilesToRelink(attachment);
assert.ok(stub.calledOnce);
assert.ok(stub.calledWith(attachment, sinon.match.string, 0));
await assert.eventually.isTrue(attachment.fileExists());
assert.equal(attachment.getFilePath(), labdFile);
assert.equal(attachment.attachmentPath, 'attachments:test.pdf');
stub.restore();
});
it("should detect and relink multiple attachments when user chooses", async function () {
for (let choice of ['one', 'all']) {
let file1 = getTestDataDirectory();
file1.append('test.pdf');
let file2 = getTestDataDirectory();
file2.append('empty.pdf');
let outsideStorageDir = await getTempDirectory();
let outsideFile1 = OS.Path.join(outsideStorageDir, 'test.pdf');
let outsideFile2 = OS.Path.join(outsideStorageDir, 'empty.pdf');
let labdFile1 = OS.Path.join(labdDir, 'test.pdf');
let labdFile2 = OS.Path.join(labdDir, 'empty.pdf');
await OS.File.copy(file1.path, outsideFile1);
await OS.File.copy(file2.path, outsideFile2);
let attachment1 = await Zotero.Attachments.linkFromFile({ file: outsideFile1 });
let attachment2 = await Zotero.Attachments.linkFromFile({ file: outsideFile2 });
await assert.eventually.isTrue(attachment1.fileExists());
await assert.eventually.isTrue(attachment2.fileExists());
await OS.File.move(outsideFile1, labdFile1);
await OS.File.move(outsideFile2, labdFile2);
await assert.eventually.isFalse(attachment1.fileExists());
await assert.eventually.isFalse(attachment2.fileExists());
let stub = sinon.stub(zp, 'showLinkedFileFoundAutomaticallyDialog')
.returns(choice);
await zp.checkForLinkedFilesToRelink(attachment1);
assert.ok(stub.calledOnce);
assert.ok(stub.calledWith(attachment1, sinon.match.string, 1));
await assert.eventually.isTrue(attachment1.fileExists());
await assert.eventually.equal(attachment2.fileExists(), choice === 'all');
assert.equal(attachment1.getFilePath(), labdFile1);
assert.equal(attachment1.attachmentPath, 'attachments:test.pdf');
if (choice === 'all') {
assert.equal(attachment2.getFilePath(), labdFile2);
assert.equal(attachment2.attachmentPath, 'attachments:empty.pdf');
}
else {
assert.equal(attachment2.getFilePath(), outsideFile2);
}
stub.restore();
}
});
it("should use subdirectories of original path", async function () {
let file = getTestDataDirectory();
file.append('test.pdf');
let outsideStorageDir = OS.Path.join(await getTempDirectory(), 'subdir');
await OS.File.makeDir(outsideStorageDir);
let outsideFile = OS.Path.join(outsideStorageDir, 'test.pdf');
let labdSubdir = OS.Path.join(labdDir, 'subdir');
await OS.File.makeDir(labdSubdir);
let labdFile = OS.Path.join(labdSubdir, 'test.pdf');
await OS.File.copy(file.path, outsideFile);
let attachment = await Zotero.Attachments.linkFromFile({ file: outsideFile });
await assert.eventually.isTrue(attachment.fileExists());
await OS.File.move(outsideFile, labdFile);
await assert.eventually.isFalse(attachment.fileExists());
let dialogStub = sinon.stub(zp, 'showLinkedFileFoundAutomaticallyDialog')
.returns('one');
let existsSpy = sinon.spy(OS.File, 'exists');
await zp.checkForLinkedFilesToRelink(attachment);
assert.ok(dialogStub.calledOnce);
assert.ok(dialogStub.calledWith(attachment, sinon.match.string, 0));
assert.ok(existsSpy.calledWith(OS.Path.join(labdSubdir, 'test.pdf')));
assert.notOk(existsSpy.calledWith(OS.Path.join(labdDir, 'test.pdf'))); // Should never get there
await assert.eventually.isTrue(attachment.fileExists());
assert.equal(attachment.getFilePath(), labdFile);
assert.equal(attachment.attachmentPath, 'attachments:subdir/test.pdf');
dialogStub.restore();
existsSpy.restore();
});
it("should handle Windows paths", async function () {
let filenames = [['test.pdf'], ['empty.pdf'], ['search', 'baz.pdf']];
let labdFiles = [];
let attachments = [];
for (let parts of filenames) {
let file = getTestDataDirectory();
parts.forEach(part => file.append(part));
await OS.File.makeDir(OS.Path.join(labdDir, ...parts.slice(0, -1)));
let labdFile = OS.Path.join(labdDir, ...parts);
await OS.File.copy(file.path, labdFile);
labdFiles.push(labdFile);
let attachment = await Zotero.Attachments.linkFromFile({ file });
attachment.attachmentPath = `C:\\test\\${parts.join('\\')}`;
await attachment.saveTx();
attachments.push(attachment);
await assert.eventually.isFalse(attachment.fileExists());
}
let stub = sinon.stub(zp, 'showLinkedFileFoundAutomaticallyDialog')
.returns('all');
await zp.checkForLinkedFilesToRelink(attachments[0]);
assert.ok(stub.calledOnce);
assert.ok(stub.calledWith(attachments[0], sinon.match.string, filenames.length - 1));
for (let i = 0; i < filenames.length; i++) {
let attachment = attachments[i];
await assert.eventually.isTrue(attachment.fileExists());
assert.equal(attachment.getFilePath(), labdFiles[i]);
assert.equal(attachment.attachmentPath, 'attachments:' + OS.Path.join(...filenames[i]));
}
stub.restore();
});
});
})