zotero/test/tests/readerTest.js
abaevbog 873beebc0f
close more leftover windows in tests (#5460)
- close hyphenationTest window.
- properly close zoteroPane window in preferences_syncTest.
after() hook inside of the test would not close the window until the
very end of the entire test run. Without this, during
subsequent tests that open their own zoteroPane window, there
are two instances of zoteroPane open at the same time.
- close open tabs in readerTest cleanup, since subsequent
tests expect library tab to be selected.

Followup to https://github.com/zotero/zotero/pull/5444#issuecomment-3141879892
2025-08-02 01:40:21 -04:00

316 lines
10 KiB
JavaScript

"use strict";
describe("Reader", function () {
var win, zp;
before(function* () {
win = yield loadZoteroPane();
zp = win.ZoteroPane;
});
after(function () {
win.Zotero_Tabs.closeAll();
win.close();
});
describe('PDF Reader', function () {
it('should create/update annotations', async function () {
var attachment = await importFileAttachment('test.pdf');
var reader = await Zotero.Reader.open(attachment.itemID);
await reader._initPromise;
reader._internalReader._annotationManager._skipAnnotationSavingDebounce = true;
// Add highlight annotation
let highlightAnnotation = reader._internalReader._annotationManager.addAnnotation(
Components.utils.cloneInto({
type: 'highlight',
color: '#ffd400',
sortIndex: '00000|003305|00000',
position: {
pageIndex: 0,
rects: [[0, 0, 100, 100]]
},
text: 'test'
}, reader._iframeWindow)
);
await waitForItemEvent("add");
// Add underline annotation
let underlineAnnotation = await reader._internalReader._annotationManager.addAnnotation(
Components.utils.cloneInto({
type: 'underline',
color: '#ffd400',
sortIndex: '00000|003305|00000',
position: {
pageIndex: 0,
rects: [[0, 0, 100, 100]]
},
text: 'test'
}, reader._iframeWindow)
);
await waitForItemEvent("add");
// Add note annotation
let noteAnnotation = await reader._internalReader._annotationManager.addAnnotation(
Components.utils.cloneInto({
type: 'note',
color: '#ffd400',
sortIndex: '00000|003305|00000',
comment: 'test',
position: {
pageIndex: 0,
rects: [[0, 0, 100, 100]]
},
text: 'test'
}, reader._iframeWindow)
);
await waitForItemEvent("add");
// Add text annotation
let textAnnotation = await reader._internalReader._annotationManager.addAnnotation(
Components.utils.cloneInto({
type: 'text',
color: '#ffd400',
sortIndex: '00000|003305|00000',
comment: 'test',
position: {
pageIndex: 0,
rects: [[17.70514027630181, 729.1404633368757, 132.24914027630183, 762.1404633368757]],
fontSize: 14,
rotation: 10
},
text: 'test'
}, reader._iframeWindow)
);
await waitForItemEvent("add");
// Add image annotation
let imageAnnotation = await reader._internalReader._annotationManager.addAnnotation(
Components.utils.cloneInto({
type: 'image',
color: '#ffd400',
sortIndex: '00000|003305|00000',
comment: 'test',
position: {
pageIndex: 0,
rects: [[0, 0, 100, 100]]
}
}, reader._iframeWindow)
);
await waitForItemEvent("add");
// Add ink annotation
let inkAnnotation = await reader._internalReader._annotationManager.addAnnotation(
Components.utils.cloneInto({
type: 'ink',
color: '#ffd400',
sortIndex: '00000|003305|00000',
position: {
pageIndex: 0,
paths: [[517.759, 760.229]],
width: 2
},
}, reader._iframeWindow)
);
await waitForItemEvent("add");
// Modify highlight annotation
reader._internalReader._annotationManager.updateAnnotations(
Components.utils.cloneInto([
{
id: highlightAnnotation.id,
text: 'test2'
}
], reader._iframeWindow)
);
await waitForItemEvent("modify");
// Modify underline annotation
await reader._internalReader._annotationManager.updateAnnotations(
Components.utils.cloneInto([
{
id: underlineAnnotation.id,
text: 'test2'
}
], reader._iframeWindow)
);
await waitForItemEvent("modify");
// Modify note annotation
await reader._internalReader._annotationManager.updateAnnotations(
Components.utils.cloneInto([
{
id: noteAnnotation.id,
color: '#aabbcc'
}
], reader._iframeWindow)
);
await waitForItemEvent("modify");
// Modify text annotation
await reader._internalReader._annotationManager.updateAnnotations(
Components.utils.cloneInto([
{
id: textAnnotation.id,
sortIndex: '00000|001491|00283',
position: {
pageIndex: 0,
rects: [[17.70514027630181, 729.1404633368757, 132.24914027630183, 762.1404633368757]],
fontSize: 16,
rotation: 10
},
}
], reader._iframeWindow)
);
await waitForItemEvent("modify");
// Modify image annotation
await reader._internalReader._annotationManager.updateAnnotations(
Components.utils.cloneInto([
{
id: imageAnnotation.id,
sortIndex: '00000|001491|00283',
position: {
pageIndex: 0,
rects: [[0, 0, 200, 200]]
}
}
], reader._iframeWindow)
);
await waitForItemEvent("modify");
// Modify ink annotation
await reader._internalReader._annotationManager.updateAnnotations(
Components.utils.cloneInto([
{
id: inkAnnotation.id,
sortIndex: '00000|001491|00283',
position: {
pageIndex: 0,
paths: [[617.759, 560.229]],
width: 2,
unknownField: 'test'
},
}
], reader._iframeWindow)
);
await waitForItemEvent("modify");
var annotations = attachment.getAnnotations();
assert.equal(annotations.length, 6);
assert.equal(annotations.find(x => x.key === highlightAnnotation.id).annotationText, 'test2');
assert.equal(annotations.find(x => x.key === underlineAnnotation.id).annotationText, 'test2');
assert.equal(annotations.find(x => x.key === noteAnnotation.id).annotationColor, '#aabbcc');
assert.equal(JSON.parse(annotations.find(x => x.key === textAnnotation.id).annotationPosition).fontSize, 16);
assert.equal(JSON.parse(annotations.find(x => x.key === imageAnnotation.id).annotationPosition).rects[0][2], 200);
assert.equal(JSON.parse(annotations.find(x => x.key === inkAnnotation.id).annotationPosition).pageIndex, 0);
assert.equal(JSON.parse(annotations.find(x => x.key === inkAnnotation.id).annotationPosition).unknownField, 'test');
reader.close();
});
describe("#importFromEPUB()", function () {
let bookEpubPath; // The EPUB itself
let bookSdrPath; // The KOReader "sidecar" folder
let calibreBookmarksPath; // The calibre_bookmarks.txt file (we'll copy this into META_INF for some tests)
let metadataOpfPath; // The Calibre metadata.opf file
let tempPath;
let tempBookEpubPath;
async function waitForReader(reader) {
await reader._initPromise;
// Shouldn't this just be included in _initPromise?
await reader._internalReader._primaryView.initializedPromise;
}
async function waitForAdds(n) {
while (n > 0) {
n -= (await waitForItemEvent('add')).length;
}
}
before(function () {
bookEpubPath = getTestDataDirectory();
bookEpubPath.append('moby_dick');
bookEpubPath.append('book.epub');
bookEpubPath = bookEpubPath.path;
calibreBookmarksPath = getTestDataDirectory();
calibreBookmarksPath.append('moby_dick');
calibreBookmarksPath.append('calibre_bookmarks.txt');
calibreBookmarksPath = calibreBookmarksPath.path;
metadataOpfPath = getTestDataDirectory();
metadataOpfPath.append('moby_dick');
metadataOpfPath.append('metadata.opf');
metadataOpfPath = metadataOpfPath.path;
bookSdrPath = getTestDataDirectory();
bookSdrPath.append('moby_dick');
bookSdrPath.append('book.sdr');
bookSdrPath = bookSdrPath.path;
});
beforeEach(async function () {
tempPath = await getTempDirectory();
tempBookEpubPath = PathUtils.join(tempPath, 'book.epub');
await IOUtils.copy(bookEpubPath, tempBookEpubPath);
});
it("should import EPUB annotations from KOReader (stored alongside EPUB)", async function () {
await IOUtils.copy(bookSdrPath, PathUtils.join(tempPath, 'book.sdr'), { recursive: true });
let attachment = await Zotero.Attachments.linkFromFile({ file: tempBookEpubPath });
let reader = await Zotero.Reader.open(attachment.id);
await waitForReader(reader);
let donePromise = Promise.all([waitForDialog(), waitForAdds(2)]);
await reader.importFromEPUB();
await donePromise;
assert.equal(attachment.getAnnotations().length, 2);
});
it("should import EPUB annotations from KOReader (stored elsewhere)", async function () {
let attachment = await Zotero.Attachments.linkFromFile({ file: tempBookEpubPath });
let reader = await Zotero.Reader.open(attachment.id);
await waitForReader(reader);
let donePromise = Promise.all([waitForDialog(), waitForAdds(2)]);
// Import annotations from the *original* EPUB (alongside its book.sdr/metadata.epub.lua)
await reader.importFromEPUB(bookEpubPath);
await donePromise;
assert.equal(attachment.getAnnotations().length, 2);
});
it("should import EPUB annotations from Calibre (stored alongside EPUB)", async function () {
await IOUtils.copy(metadataOpfPath, PathUtils.join(tempPath, 'metadata.opf'));
let attachment = await Zotero.Attachments.linkFromFile({ file: tempBookEpubPath });
let reader = await Zotero.Reader.open(attachment.id);
await waitForReader(reader);
let donePromise = Promise.all([waitForDialog(), waitForAdds(2)]);
await reader.importFromEPUB();
await donePromise;
assert.equal(attachment.getAnnotations().length, 2);
});
it("should import EPUB annotations from Calibre (stored within EPUB)", async function () {
let zipWriter = Cc['@mozilla.org/zipwriter;1'].createInstance(Ci.nsIZipWriter);
zipWriter.open(Zotero.File.pathToFile(tempBookEpubPath), 0x04 /* RDWR */);
zipWriter.addEntryFile(
'META-INF/calibre_bookmarks.txt',
Ci.nsIZipWriter.COMPRESSION_DEFAULT,
Zotero.File.pathToFile(calibreBookmarksPath),
false,
);
zipWriter.close();
let attachment = await Zotero.Attachments.linkFromFile({ file: tempBookEpubPath });
let reader = await Zotero.Reader.open(attachment.id);
await waitForReader(reader);
let donePromise = Promise.all([waitForDialog(), waitForAdds(2)]);
await reader.importFromEPUB();
await donePromise;
assert.equal(attachment.getAnnotations().length, 2);
});
});
});
});