413 lines
12 KiB
JavaScript
413 lines
12 KiB
JavaScript
describe("Item pane", function () {
|
|
var win, doc, itemsView;
|
|
|
|
before(function* () {
|
|
win = yield loadZoteroPane();
|
|
doc = win.document;
|
|
itemsView = win.ZoteroPane.itemsView;
|
|
});
|
|
after(function () {
|
|
win.close();
|
|
});
|
|
|
|
describe("Info pane", function () {
|
|
it("should refresh on item update", function* () {
|
|
var item = new Zotero.Item('book');
|
|
var id = yield item.saveTx();
|
|
|
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
|
var label = itemBox.shadowRoot.querySelectorAll('[fieldname="title"]')[1];
|
|
assert.equal(label.textContent, '');
|
|
|
|
item.setField('title', 'Test');
|
|
yield item.saveTx();
|
|
|
|
label = itemBox.shadowRoot.querySelectorAll('[fieldname="title"]')[1];
|
|
assert.equal(label.textContent, 'Test');
|
|
|
|
yield Zotero.Items.erase(id);
|
|
})
|
|
|
|
|
|
it("should swap creator names", async function () {
|
|
var item = new Zotero.Item('book');
|
|
item.setCreators([
|
|
{
|
|
firstName: "First",
|
|
lastName: "Last",
|
|
creatorType: "author"
|
|
}
|
|
]);
|
|
await item.saveTx();
|
|
|
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
|
var label = itemBox.shadowRoot.querySelector('[fieldname="creator-0-lastName"]')
|
|
var parent = label.parentNode;
|
|
assert.property(parent, 'oncontextmenu');
|
|
assert.isFunction(label.parentNode.oncontextmenu);
|
|
|
|
var menupopup = itemBox.shadowRoot.getElementById('zotero-creator-transform-menu');
|
|
// Fake a right-click
|
|
doc.popupNode = parent;
|
|
menupopup.openPopup(
|
|
parent, "after_start", 0, 0, true, false, new MouseEvent('click', { button: 2 })
|
|
);
|
|
var menuitem = menupopup.getElementsByTagName('menuitem')[0];
|
|
menuitem.click();
|
|
await waitForItemEvent('modify');
|
|
|
|
var creator = item.getCreators()[0];
|
|
assert.propertyVal(creator, 'firstName', 'Last');
|
|
assert.propertyVal(creator, 'lastName', 'First');
|
|
});
|
|
|
|
|
|
it("shouldn't show Swap Names menu for single-field mode", function* () {
|
|
var item = new Zotero.Item('book');
|
|
item.setCreators([
|
|
{
|
|
name: "Name",
|
|
creatorType: "author"
|
|
}
|
|
]);
|
|
yield item.saveTx();
|
|
|
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
|
var label = itemBox.shadowRoot.querySelector('[fieldname="creator-0-lastName"]');
|
|
assert.isNull(label.parentNode.oncontextmenu, null);
|
|
});
|
|
|
|
|
|
// Note: This issue applies to all context menus in the item box (text transform, name swap),
|
|
// though the others aren't tested. This might go away with the XUL->HTML transition.
|
|
it.skip("should save open field after changing creator type", function* () {
|
|
var item = new Zotero.Item('book');
|
|
item.setCreators([
|
|
{
|
|
firstName: "First",
|
|
lastName: "Last",
|
|
creatorType: "author"
|
|
}
|
|
]);
|
|
var id = yield item.saveTx();
|
|
|
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
|
var label = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'place')[1];
|
|
label.click();
|
|
var textbox = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'place')[1];
|
|
textbox.value = "Place";
|
|
|
|
var menuLabel = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'creator-0-typeID')[0];
|
|
menuLabel.click();
|
|
var menupopup = itemBox._creatorTypeMenu;
|
|
var menuItems = menupopup.getElementsByTagName('menuitem');
|
|
menuItems[1].click();
|
|
yield waitForItemEvent('modify');
|
|
|
|
assert.equal(item.getField('place'), 'Place');
|
|
assert.equal(Zotero.CreatorTypes.getName(item.getCreators()[0].creatorTypeID), 'contributor');
|
|
|
|
// Wait for no-op saveTx()
|
|
yield Zotero.Promise.delay(1);
|
|
});
|
|
|
|
it("should accept 'now' for Accessed", async function () {
|
|
var item = await createDataObject('item');
|
|
|
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
|
var box = itemBox.shadowRoot;
|
|
var label = box.querySelector('div[fieldname="accessDate"].zotero-clicky');
|
|
label.click();
|
|
var textbox = box.querySelector('input[fieldname="accessDate"]');
|
|
textbox.value = 'now';
|
|
// Blur events don't necessarily trigger if window doesn't have focus
|
|
itemBox.hideEditor(textbox);
|
|
|
|
await waitForItemEvent('modify');
|
|
|
|
assert.approximately(
|
|
Zotero.Date.sqlToDate(item.getField('accessDate'), true).getTime(),
|
|
Date.now(),
|
|
5000
|
|
);
|
|
});
|
|
|
|
it("should persist fieldMode after hiding a creator name editor", async function () {
|
|
let item = new Zotero.Item('book');
|
|
item.setCreators([
|
|
{
|
|
name: "First Last",
|
|
creatorType: "author",
|
|
fieldMode: 1
|
|
}
|
|
]);
|
|
await item.saveTx();
|
|
|
|
let itemBox = doc.getElementById('zotero-editpane-item-box');
|
|
let box = doc.getAnonymousNodes(itemBox)[0];
|
|
|
|
box.querySelector('label[fieldname="creator-0-lastName"]').click();
|
|
itemBox.hideEditor(box.querySelector('textbox[fieldname="creator-0-lastName"]'));
|
|
|
|
assert.equal(
|
|
box.querySelector('label[fieldname="creator-0-lastName"]').getAttribute('fieldMode'),
|
|
'1'
|
|
);
|
|
});
|
|
})
|
|
|
|
|
|
describe("Notes pane", function () {
|
|
it("should refresh on child note change", function* () {
|
|
var item;
|
|
var note1;
|
|
var note2;
|
|
yield Zotero.DB.executeTransaction(async function () {
|
|
item = createUnsavedDataObject('item');
|
|
await item.save();
|
|
|
|
note1 = new Zotero.Item('note');
|
|
note1.parentID = item.id;
|
|
note1.setNote('A');
|
|
await note1.save();
|
|
|
|
note2 = new Zotero.Item('note');
|
|
note2.parentID = item.id;
|
|
note2.setNote('B');
|
|
await note2.save();
|
|
});
|
|
|
|
var tabs = doc.getElementById('zotero-editpane-tabs');
|
|
var notesTab = doc.getElementById('zotero-editpane-notes-tab');
|
|
var noteRows = doc.getElementById('zotero-editpane-notes');
|
|
var grid = noteRows.shadowRoot.getElementById('grid');
|
|
tabs.selectedItem = notesTab;
|
|
// Wait for note list to update
|
|
do {
|
|
yield Zotero.Promise.delay(1);
|
|
}
|
|
while (grid.querySelectorAll('div.box > label').length !== 2);
|
|
|
|
// Update note text
|
|
note2.setNote('C');
|
|
yield note2.saveTx();
|
|
|
|
// Wait for note list to update
|
|
do {
|
|
yield Zotero.Promise.delay(1);
|
|
}
|
|
while ([...grid.querySelectorAll('div.box > label')].every(label => label.textContent != 'C'));
|
|
});
|
|
|
|
it("should refresh on child note trash", function* () {
|
|
var item;
|
|
var note1;
|
|
var note2;
|
|
yield Zotero.DB.executeTransaction(async function () {
|
|
item = createUnsavedDataObject('item');
|
|
await item.save();
|
|
|
|
note1 = new Zotero.Item('note');
|
|
note1.parentID = item.id;
|
|
note1.setNote('A');
|
|
await note1.save();
|
|
|
|
note2 = new Zotero.Item('note');
|
|
note2.parentID = item.id;
|
|
note2.setNote('B');
|
|
await note2.save();
|
|
});
|
|
|
|
var tabs = doc.getElementById('zotero-editpane-tabs');
|
|
var notesTab = doc.getElementById('zotero-editpane-notes-tab');
|
|
var noteRows = doc.getElementById('zotero-editpane-notes');
|
|
var grid = noteRows.shadowRoot.getElementById('grid');
|
|
tabs.selectedItem = notesTab;
|
|
// Wait for note list to update
|
|
do {
|
|
yield Zotero.Promise.delay(1);
|
|
}
|
|
while (grid.querySelectorAll('div.box > label').length !== 2);
|
|
|
|
// Click "-" in first note
|
|
var promise = waitForDialog();
|
|
grid.querySelector(".zotero-clicky-minus").click();
|
|
yield promise;
|
|
|
|
// Wait for note list to update
|
|
do {
|
|
yield Zotero.Promise.delay(1);
|
|
}
|
|
while (grid.querySelectorAll('div.box > label').length !== 1);
|
|
});
|
|
|
|
it("should refresh on child note delete", function* () {
|
|
var item;
|
|
var note1;
|
|
var note2;
|
|
yield Zotero.DB.executeTransaction(async function () {
|
|
item = createUnsavedDataObject('item');
|
|
await item.save();
|
|
|
|
note1 = new Zotero.Item('note');
|
|
note1.parentID = item.id;
|
|
note1.setNote('A');
|
|
await note1.save();
|
|
|
|
note2 = new Zotero.Item('note');
|
|
note2.parentID = item.id;
|
|
note2.setNote('B');
|
|
await note2.save();
|
|
});
|
|
|
|
var tabs = doc.getElementById('zotero-editpane-tabs');
|
|
var notesTab = doc.getElementById('zotero-editpane-notes-tab');
|
|
var noteRows = doc.getElementById('zotero-editpane-notes');
|
|
var grid = noteRows.shadowRoot.getElementById('grid');
|
|
tabs.selectedItem = notesTab;
|
|
// Wait for note list to update
|
|
do {
|
|
yield Zotero.Promise.delay(1);
|
|
}
|
|
while (grid.querySelectorAll('div.box > label').length !== 2);
|
|
|
|
yield note2.eraseTx();
|
|
|
|
// Wait for note list to update
|
|
do {
|
|
yield Zotero.Promise.delay(1);
|
|
}
|
|
while (grid.querySelectorAll('div.box > label').length !== 1);
|
|
});
|
|
});
|
|
|
|
|
|
describe("Attachment pane", function () {
|
|
it("should refresh on file rename", function* () {
|
|
var file = getTestDataDirectory();
|
|
file.append('test.png');
|
|
var item = yield Zotero.Attachments.importFromFile({
|
|
file: file
|
|
});
|
|
var newName = 'test2.png';
|
|
yield item.renameAttachmentFile(newName);
|
|
|
|
var itemBox = doc.getElementById('zotero-attachment-box');
|
|
var label = itemBox._id('fileName');
|
|
assert.equal(label.value, newName);
|
|
})
|
|
|
|
it("should update on attachment title change", async function () {
|
|
var file = getTestDataDirectory();
|
|
file.append('test.png');
|
|
var item = await Zotero.Attachments.importFromFile({ file });
|
|
var newTitle = 'New Title';
|
|
item.setField('title', newTitle);
|
|
await item.saveTx();
|
|
|
|
var itemBox = doc.getElementById('zotero-attachment-box');
|
|
var label = itemBox._id('title');
|
|
assert.equal(label.textContent, newTitle);
|
|
})
|
|
})
|
|
|
|
|
|
describe("Note editor", function () {
|
|
it("should refresh on note update", function* () {
|
|
var item = new Zotero.Item('note');
|
|
var id = yield item.saveTx();
|
|
|
|
var noteEditor = doc.getElementById('zotero-note-editor');
|
|
|
|
// Wait for the editor
|
|
yield new Zotero.Promise((resolve, reject) => {
|
|
noteEditor.onInit(() => resolve());
|
|
});
|
|
assert.equal(noteEditor._editorInstance._iframeWindow.wrappedJSObject.getDataSync(), null);
|
|
item.setNote('<p>Test</p>');
|
|
yield item.saveTx();
|
|
|
|
// Wait for asynchronous editor update
|
|
do {
|
|
yield Zotero.Promise.delay(10);
|
|
} while (
|
|
!/<div data-schema-version=".*"><p>Test<\/p><\/div>/.test(
|
|
noteEditor._editorInstance._iframeWindow.wrappedJSObject.getDataSync().html.replace(/\n/g, '')
|
|
)
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Feed buttons", function() {
|
|
describe("Mark as Read/Unread", function() {
|
|
it("should update label when state of an item changes", function* () {
|
|
let feed = yield createFeed();
|
|
yield selectLibrary(win, feed.libraryID);
|
|
yield waitForItemsLoad(win);
|
|
|
|
var stub = sinon.stub(win.ZoteroPane, 'startItemReadTimeout');
|
|
var item = yield createDataObject('feedItem', { libraryID: feed.libraryID });
|
|
// Skip timed mark-as-read
|
|
assert.ok(stub.called);
|
|
stub.restore();
|
|
item.isRead = true;
|
|
yield item.saveTx();
|
|
|
|
let button = doc.getElementById('zotero-feed-item-toggleRead-button');
|
|
|
|
assert.equal(button.getAttribute('label'), Zotero.getString('pane.item.markAsUnread'));
|
|
yield item.toggleRead(false);
|
|
assert.equal(button.getAttribute('label'), Zotero.getString('pane.item.markAsRead'));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Duplicates Merge pane", function () {
|
|
// Same as test in itemsTest, but via UI, which makes a copy via toJSON()/fromJSON()
|
|
it("should transfer merge-tracking relations when merging two pairs into one item", async function () {
|
|
var item1 = await createDataObject('item', { title: 'A' });
|
|
var item2 = await createDataObject('item', { title: 'B' });
|
|
var item3 = await createDataObject('item', { title: 'C' });
|
|
var item4 = await createDataObject('item', { title: 'D' });
|
|
|
|
var uris = [item2, item3, item4].map(item => Zotero.URI.getItemURI(item));
|
|
|
|
var p;
|
|
|
|
var zp = win.ZoteroPane;
|
|
await zp.selectItems([item1.id, item2.id]);
|
|
zp.mergeSelectedItems();
|
|
p = waitForItemEvent('modify');
|
|
doc.getElementById('zotero-duplicates-merge-button').click();
|
|
await p;
|
|
|
|
assert.sameMembers(
|
|
item1.getRelations()[Zotero.Relations.replacedItemPredicate],
|
|
[uris[0]]
|
|
);
|
|
|
|
await zp.selectItems([item3.id, item4.id]);
|
|
zp.mergeSelectedItems();
|
|
p = waitForItemEvent('modify');
|
|
doc.getElementById('zotero-duplicates-merge-button').click();
|
|
await p;
|
|
|
|
assert.sameMembers(
|
|
item3.getRelations()[Zotero.Relations.replacedItemPredicate],
|
|
[uris[2]]
|
|
);
|
|
|
|
await zp.selectItems([item1.id, item3.id]);
|
|
zp.mergeSelectedItems();
|
|
p = waitForItemEvent('modify');
|
|
doc.getElementById('zotero-duplicates-merge-button').click();
|
|
await p;
|
|
|
|
// Remaining item should include all other URIs
|
|
assert.sameMembers(
|
|
item1.getRelations()[Zotero.Relations.replacedItemPredicate],
|
|
uris
|
|
);
|
|
});
|
|
});
|
|
})
|