2015-09-29 08:09:15 +00:00
|
|
|
"use strict";
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
describe("Zotero.ItemTreeView", function() {
|
2016-03-14 02:59:19 +00:00
|
|
|
var win, zp, cv, itemsView, existingItemID;
|
2015-04-30 21:06:38 +00:00
|
|
|
|
|
|
|
// Load Zotero pane and select library
|
|
|
|
before(function* () {
|
|
|
|
win = yield loadZoteroPane();
|
2015-06-09 05:29:06 +00:00
|
|
|
zp = win.ZoteroPane;
|
2016-03-14 02:59:19 +00:00
|
|
|
cv = zp.collectionsView;
|
2015-04-30 21:06:38 +00:00
|
|
|
|
2016-05-05 06:14:54 +00:00
|
|
|
var item = yield createDataObject('item', { setTitle: true });
|
|
|
|
existingItemID = item.id;
|
2015-04-30 21:06:38 +00:00
|
|
|
});
|
2015-06-09 05:29:06 +00:00
|
|
|
beforeEach(function* () {
|
2016-03-14 02:59:19 +00:00
|
|
|
yield selectLibrary(win);
|
2015-06-09 05:29:06 +00:00
|
|
|
itemsView = zp.itemsView;
|
|
|
|
})
|
2015-04-30 21:06:38 +00:00
|
|
|
after(function () {
|
2015-05-04 06:00:52 +00:00
|
|
|
win.close();
|
2015-04-30 21:06:38 +00:00
|
|
|
});
|
|
|
|
|
2016-03-14 02:59:19 +00:00
|
|
|
it("shouldn't show items in trash in library root", function* () {
|
2015-11-01 08:36:23 +00:00
|
|
|
var item = yield createDataObject('item', { title: "foo" });
|
|
|
|
var itemID = item.id;
|
|
|
|
item.deleted = true;
|
|
|
|
yield item.saveTx();
|
2016-03-14 02:59:19 +00:00
|
|
|
assert.isFalse(itemsView.getRowIndexByID(itemID));
|
2015-11-01 08:36:23 +00:00
|
|
|
})
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
describe("#selectItem()", function () {
|
|
|
|
/**
|
|
|
|
* Make sure that selectItem() doesn't hang if the pane's item-select handler is never
|
|
|
|
* triggered due to the item already being selected
|
|
|
|
*/
|
|
|
|
it("should return if item is already selected", function* () {
|
|
|
|
yield itemsView.selectItem(existingItemID);
|
2015-05-05 06:40:01 +00:00
|
|
|
var selected = itemsView.getSelectedItems(true);
|
2015-04-30 21:06:38 +00:00
|
|
|
assert.lengthOf(selected, 1);
|
2015-05-05 06:40:01 +00:00
|
|
|
assert.equal(selected[0], existingItemID);
|
2015-04-30 21:06:38 +00:00
|
|
|
yield itemsView.selectItem(existingItemID);
|
2015-05-05 06:40:01 +00:00
|
|
|
selected = itemsView.getSelectedItems(true);
|
2015-04-30 21:06:38 +00:00
|
|
|
assert.lengthOf(selected, 1);
|
2015-05-05 06:40:01 +00:00
|
|
|
assert.equal(selected[0], existingItemID);
|
2015-04-30 21:06:38 +00:00
|
|
|
});
|
|
|
|
})
|
|
|
|
|
2016-03-11 09:50:55 +00:00
|
|
|
describe("#getCellText()", function () {
|
|
|
|
it("should return new value after edit", function* () {
|
|
|
|
var str = Zotero.Utilities.randomString();
|
|
|
|
var item = yield createDataObject('item', { title: str });
|
|
|
|
var row = itemsView.getRowIndexByID(item.id);
|
|
|
|
assert.equal(itemsView.getCellText(row, { id: 'zotero-items-column-title' }), str);
|
|
|
|
yield modifyDataObject(item);
|
|
|
|
assert.notEqual(itemsView.getCellText(row, { id: 'zotero-items-column-title' }), str);
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
describe("#notify()", function () {
|
2015-05-07 19:05:37 +00:00
|
|
|
beforeEach(function () {
|
|
|
|
sinon.spy(win.ZoteroPane, "itemSelected");
|
|
|
|
})
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
win.ZoteroPane.itemSelected.restore();
|
|
|
|
})
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
it("should select a new item", function* () {
|
|
|
|
itemsView.selection.clearSelection();
|
|
|
|
assert.lengthOf(itemsView.getSelectedItems(), 0);
|
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
assert.equal(win.ZoteroPane.itemSelected.callCount, 1);
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Create item
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var id = yield item.saveTx();
|
2015-04-30 21:06:38 +00:00
|
|
|
|
|
|
|
// New item should be selected
|
|
|
|
var selected = itemsView.getSelectedItems();
|
|
|
|
assert.lengthOf(selected, 1);
|
|
|
|
assert.equal(selected[0].id, id);
|
2015-05-07 19:05:37 +00:00
|
|
|
|
|
|
|
// Item should have been selected once
|
|
|
|
assert.equal(win.ZoteroPane.itemSelected.callCount, 2);
|
|
|
|
assert.ok(win.ZoteroPane.itemSelected.returnValues[1].value());
|
2015-04-30 21:06:38 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("shouldn't select a new item if skipNotifier is passed", function* () {
|
|
|
|
// Select existing item
|
|
|
|
yield itemsView.selectItem(existingItemID);
|
2015-05-05 06:40:01 +00:00
|
|
|
var selected = itemsView.getSelectedItems(true);
|
2015-04-30 21:06:38 +00:00
|
|
|
assert.lengthOf(selected, 1);
|
2015-05-05 06:40:01 +00:00
|
|
|
assert.equal(selected[0], existingItemID);
|
2015-04-30 21:06:38 +00:00
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// Reset call count on spy
|
|
|
|
win.ZoteroPane.itemSelected.reset();
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Create item with skipNotifier flag
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var id = yield item.saveTx({
|
2015-04-30 21:06:38 +00:00
|
|
|
skipNotifier: true
|
|
|
|
});
|
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// No select events should have occurred
|
|
|
|
assert.equal(win.ZoteroPane.itemSelected.callCount, 0);
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Existing item should still be selected
|
2015-05-05 06:40:01 +00:00
|
|
|
selected = itemsView.getSelectedItems(true);
|
2015-04-30 21:06:38 +00:00
|
|
|
assert.lengthOf(selected, 1);
|
2015-05-05 06:40:01 +00:00
|
|
|
assert.equal(selected[0], existingItemID);
|
2015-04-30 21:06:38 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("shouldn't select a new item if skipSelect is passed", function* () {
|
|
|
|
// Select existing item
|
|
|
|
yield itemsView.selectItem(existingItemID);
|
2015-05-05 06:40:01 +00:00
|
|
|
var selected = itemsView.getSelectedItems(true);
|
2015-04-30 21:06:38 +00:00
|
|
|
assert.lengthOf(selected, 1);
|
2015-05-05 06:40:01 +00:00
|
|
|
assert.equal(selected[0], existingItemID);
|
2015-04-30 21:06:38 +00:00
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// Reset call count on spy
|
|
|
|
win.ZoteroPane.itemSelected.reset();
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Create item with skipSelect flag
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var id = yield item.saveTx({
|
2015-04-30 21:06:38 +00:00
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// itemSelected should have been called once (from 'selectEventsSuppressed = false'
|
|
|
|
// in notify()) as a no-op
|
|
|
|
assert.equal(win.ZoteroPane.itemSelected.callCount, 1);
|
|
|
|
assert.isFalse(win.ZoteroPane.itemSelected.returnValues[0].value());
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Existing item should still be selected
|
|
|
|
selected = itemsView.getSelectedItems(true);
|
|
|
|
assert.lengthOf(selected, 1);
|
|
|
|
assert.equal(selected[0], existingItemID);
|
|
|
|
});
|
|
|
|
|
2016-05-05 06:14:54 +00:00
|
|
|
it("shouldn't clear quicksearch if skipSelect is passed", function* () {
|
|
|
|
var searchString = Zotero.Items.get(existingItemID).getField('title');
|
|
|
|
|
|
|
|
yield createDataObject('item');
|
|
|
|
|
|
|
|
var quicksearch = win.document.getElementById('zotero-tb-search');
|
|
|
|
quicksearch.value = searchString;
|
|
|
|
quicksearch.doCommand();
|
|
|
|
yield itemsView._refreshPromise;
|
|
|
|
|
|
|
|
assert.equal(itemsView.rowCount, 1);
|
|
|
|
|
|
|
|
// Create item with skipSelect flag
|
|
|
|
var item = new Zotero.Item('book');
|
|
|
|
var ran = Zotero.Utilities.randomString();
|
|
|
|
item.setField('title', ran);
|
|
|
|
var id = yield item.saveTx({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(itemsView.rowCount, 1);
|
|
|
|
assert.equal(quicksearch.value, searchString);
|
2016-05-05 09:26:19 +00:00
|
|
|
|
|
|
|
// Clear search
|
|
|
|
quicksearch.value = "";
|
|
|
|
quicksearch.doCommand();
|
|
|
|
yield itemsView._refreshPromise;
|
2016-05-05 06:14:54 +00:00
|
|
|
});
|
|
|
|
|
2015-06-23 20:56:10 +00:00
|
|
|
it("shouldn't change selection outside of trash if new trashed item is created with skipSelect", function* () {
|
|
|
|
yield selectLibrary(win);
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
|
|
|
|
itemsView.selection.clearSelection();
|
|
|
|
|
|
|
|
var item = createUnsavedDataObject('item');
|
|
|
|
item.deleted = true;
|
|
|
|
var id = yield item.saveTx({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
|
|
|
|
// Nothing should be selected
|
2015-09-29 08:09:15 +00:00
|
|
|
var selected = itemsView.getSelectedItems(true);
|
2015-06-23 20:56:10 +00:00
|
|
|
assert.lengthOf(selected, 0);
|
|
|
|
})
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
it("shouldn't select a modified item", function* () {
|
|
|
|
// Create item
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var id = yield item.saveTx();
|
2015-04-30 21:06:38 +00:00
|
|
|
|
|
|
|
itemsView.selection.clearSelection();
|
|
|
|
assert.lengthOf(itemsView.getSelectedItems(), 0);
|
2015-05-07 19:05:37 +00:00
|
|
|
// Reset call count on spy
|
|
|
|
win.ZoteroPane.itemSelected.reset();
|
2015-04-30 21:06:38 +00:00
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// Modify item
|
2015-04-30 21:06:38 +00:00
|
|
|
item.setField('title', 'no select on modify');
|
2015-05-10 08:20:47 +00:00
|
|
|
yield item.saveTx();
|
2015-04-30 21:06:38 +00:00
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// itemSelected should have been called once (from 'selectEventsSuppressed = false'
|
|
|
|
// in notify()) as a no-op
|
|
|
|
assert.equal(win.ZoteroPane.itemSelected.callCount, 1);
|
|
|
|
assert.isFalse(win.ZoteroPane.itemSelected.returnValues[0].value());
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Modified item should not be selected
|
|
|
|
assert.lengthOf(itemsView.getSelectedItems(), 0);
|
|
|
|
});
|
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
it("should maintain selection on a selected modified item", function* () {
|
2015-04-30 21:06:38 +00:00
|
|
|
// Create item
|
|
|
|
var item = new Zotero.Item('book');
|
2015-05-10 08:20:47 +00:00
|
|
|
var id = yield item.saveTx();
|
2015-04-30 21:06:38 +00:00
|
|
|
|
|
|
|
yield itemsView.selectItem(id);
|
|
|
|
var selected = itemsView.getSelectedItems(true);
|
|
|
|
assert.lengthOf(selected, 1);
|
|
|
|
assert.equal(selected[0], id);
|
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// Reset call count on spy
|
|
|
|
win.ZoteroPane.itemSelected.reset();
|
|
|
|
|
|
|
|
// Modify item
|
|
|
|
item.setField('title', 'maintain selection on modify');
|
2015-05-10 08:20:47 +00:00
|
|
|
yield item.saveTx();
|
2015-04-30 21:06:38 +00:00
|
|
|
|
2015-05-07 19:05:37 +00:00
|
|
|
// itemSelected should have been called once (from 'selectEventsSuppressed = false'
|
|
|
|
// in notify()) as a no-op
|
|
|
|
assert.equal(win.ZoteroPane.itemSelected.callCount, 1);
|
|
|
|
assert.isFalse(win.ZoteroPane.itemSelected.returnValues[0].value());
|
|
|
|
|
2015-04-30 21:06:38 +00:00
|
|
|
// Modified item should still be selected
|
|
|
|
selected = itemsView.getSelectedItems(true);
|
|
|
|
assert.lengthOf(selected, 1);
|
|
|
|
assert.equal(selected[0], id);
|
|
|
|
});
|
2015-06-09 05:29:06 +00:00
|
|
|
|
|
|
|
it("should reselect the same row when an item is removed", function* () {
|
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
itemsView = zp.itemsView;
|
|
|
|
|
|
|
|
var items = [];
|
2016-04-15 09:14:52 +00:00
|
|
|
var num = 6;
|
2015-06-09 05:29:06 +00:00
|
|
|
for (let i = 0; i < num; i++) {
|
|
|
|
let item = createUnsavedDataObject('item');
|
|
|
|
item.addToCollection(collection.id);
|
|
|
|
yield item.saveTx();
|
|
|
|
items.push(item);
|
|
|
|
}
|
|
|
|
assert.equal(itemsView.rowCount, num);
|
|
|
|
|
|
|
|
// Select the third item in the list
|
|
|
|
itemsView.selection.select(2);
|
|
|
|
var treeRow = itemsView.getRow(2);
|
|
|
|
yield treeRow.ref.eraseTx();
|
|
|
|
|
|
|
|
// Selection should stay on third row
|
|
|
|
assert.equal(itemsView.selection.currentIndex, 2);
|
|
|
|
|
|
|
|
yield Zotero.Items.erase(items.map(item => item.id));
|
|
|
|
})
|
2016-03-14 02:59:19 +00:00
|
|
|
|
2016-05-09 17:54:19 +00:00
|
|
|
it("should keep first visible item in view when other items are added with skipSelect and nothing in view is selected", function* () {
|
2016-05-09 17:26:33 +00:00
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
itemsView = zp.itemsView;
|
|
|
|
|
|
|
|
var treebox = itemsView._treebox;
|
|
|
|
var numVisibleRows = treebox.getPageLength();
|
|
|
|
|
|
|
|
// Get a numeric string left-padded with zeroes
|
|
|
|
function getTitle(i, max) {
|
|
|
|
return new String(new Array(max + 1).join(0) + i).slice(-1 * max);
|
|
|
|
}
|
|
|
|
|
|
|
|
var num = numVisibleRows + 10;
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
for (let i = 0; i < num; i++) {
|
|
|
|
let title = getTitle(i, num);
|
|
|
|
let item = createUnsavedDataObject('item', { title });
|
|
|
|
item.addToCollection(collection.id);
|
|
|
|
yield item.save();
|
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
// Scroll halfway
|
|
|
|
treebox.scrollToRow(Math.round(num / 2) - Math.round(numVisibleRows / 2));
|
|
|
|
|
|
|
|
var firstVisibleItemID = itemsView.getRow(treebox.getFirstVisibleRow()).ref.id;
|
|
|
|
|
|
|
|
// Add one item at the beginning
|
|
|
|
var item = createUnsavedDataObject(
|
|
|
|
'item', { title: getTitle(0, num), collections: [collection.id] }
|
|
|
|
);
|
|
|
|
yield item.saveTx({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
// Then add a few more in a transaction
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
|
|
var item = createUnsavedDataObject(
|
|
|
|
'item', { title: getTitle(0, num), collections: [collection.id] }
|
|
|
|
);
|
|
|
|
yield item.save({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
// Make sure the same item is still in the first visible row
|
|
|
|
assert.equal(itemsView.getRow(treebox.getFirstVisibleRow()).ref.id, firstVisibleItemID);
|
|
|
|
});
|
|
|
|
|
2016-05-09 17:54:19 +00:00
|
|
|
it("should keep first visible selected item in position when other items are added with skipSelect", function* () {
|
2016-05-09 17:26:33 +00:00
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
itemsView = zp.itemsView;
|
|
|
|
|
|
|
|
var treebox = itemsView._treebox;
|
|
|
|
var numVisibleRows = treebox.getPageLength();
|
|
|
|
|
|
|
|
// Get a numeric string left-padded with zeroes
|
|
|
|
function getTitle(i, max) {
|
|
|
|
return new String(new Array(max + 1).join(0) + i).slice(-1 * max);
|
|
|
|
}
|
|
|
|
|
|
|
|
var num = numVisibleRows + 10;
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
for (let i = 0; i < num; i++) {
|
|
|
|
let title = getTitle(i, num);
|
|
|
|
let item = createUnsavedDataObject('item', { title });
|
|
|
|
item.addToCollection(collection.id);
|
|
|
|
yield item.save();
|
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
// Scroll halfway
|
|
|
|
treebox.scrollToRow(Math.round(num / 2) - Math.round(numVisibleRows / 2));
|
|
|
|
|
|
|
|
// Select an item
|
|
|
|
itemsView.selection.select(Math.round(num / 2));
|
|
|
|
var selectedItem = itemsView.getSelectedItems()[0];
|
|
|
|
var offset = itemsView.getRowIndexByID(selectedItem.treeViewID) - treebox.getFirstVisibleRow();
|
|
|
|
|
|
|
|
// Add one item at the beginning
|
|
|
|
var item = createUnsavedDataObject(
|
|
|
|
'item', { title: getTitle(0, num), collections: [collection.id] }
|
|
|
|
);
|
|
|
|
yield item.saveTx({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
// Then add a few more in a transaction
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
|
|
var item = createUnsavedDataObject(
|
|
|
|
'item', { title: getTitle(0, num), collections: [collection.id] }
|
|
|
|
);
|
|
|
|
yield item.save({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
// Make sure the selected item is still at the same position
|
|
|
|
assert.equal(itemsView.getSelectedItems()[0], selectedItem);
|
|
|
|
var newOffset = itemsView.getRowIndexByID(selectedItem.treeViewID) - treebox.getFirstVisibleRow();
|
|
|
|
assert.equal(newOffset, offset);
|
|
|
|
});
|
|
|
|
|
2016-05-09 17:54:19 +00:00
|
|
|
it("shouldn't scroll items list if at top when other items are added with skipSelect", function* () {
|
2016-05-09 17:26:33 +00:00
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
itemsView = zp.itemsView;
|
|
|
|
|
|
|
|
var treebox = itemsView._treebox;
|
|
|
|
var numVisibleRows = treebox.getPageLength();
|
|
|
|
|
|
|
|
// Get a numeric string left-padded with zeroes
|
|
|
|
function getTitle(i, max) {
|
|
|
|
return new String(new Array(max + 1).join(0) + i).slice(-1 * max);
|
|
|
|
}
|
|
|
|
|
|
|
|
var num = numVisibleRows + 10;
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
// Start at "*1" so we can add items before
|
|
|
|
for (let i = 1; i < num; i++) {
|
|
|
|
let title = getTitle(i, num);
|
|
|
|
let item = createUnsavedDataObject('item', { title });
|
|
|
|
item.addToCollection(collection.id);
|
|
|
|
yield item.save();
|
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
// Scroll to top
|
|
|
|
treebox.scrollToRow(0);
|
|
|
|
|
|
|
|
// Add one item at the beginning
|
|
|
|
var item = createUnsavedDataObject(
|
|
|
|
'item', { title: getTitle(0, num), collections: [collection.id] }
|
|
|
|
);
|
|
|
|
yield item.saveTx({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
// Then add a few more in a transaction
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
|
|
var item = createUnsavedDataObject(
|
|
|
|
'item', { title: getTitle(0, num), collections: [collection.id] }
|
|
|
|
);
|
|
|
|
yield item.save({
|
|
|
|
skipSelect: true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
// Make sure the first row is still at the top
|
|
|
|
assert.equal(treebox.getFirstVisibleRow(), 0);
|
|
|
|
});
|
|
|
|
|
2016-03-26 06:59:54 +00:00
|
|
|
it("should update search results when items are added", function* () {
|
|
|
|
var search = createUnsavedDataObject('search');
|
|
|
|
var title = Zotero.Utilities.randomString();
|
|
|
|
search.fromJSON({
|
|
|
|
name: "Test",
|
|
|
|
conditions: [
|
|
|
|
{
|
|
|
|
condition: "title",
|
|
|
|
operator: "is",
|
|
|
|
value: title
|
|
|
|
}
|
|
|
|
]
|
|
|
|
});
|
|
|
|
yield search.saveTx();
|
|
|
|
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
assert.equal(zp.itemsView.rowCount, 0);
|
|
|
|
|
|
|
|
// Add an item matching search
|
|
|
|
var item = yield createDataObject('item', { title });
|
|
|
|
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
assert.equal(zp.itemsView.rowCount, 1);
|
|
|
|
assert.equal(zp.itemsView.getRowIndexByID(item.id), 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should update search results when search conditions are changed", function* () {
|
|
|
|
var search = createUnsavedDataObject('search');
|
|
|
|
var title1 = Zotero.Utilities.randomString();
|
|
|
|
var title2 = Zotero.Utilities.randomString();
|
|
|
|
search.fromJSON({
|
|
|
|
name: "Test",
|
|
|
|
conditions: [
|
|
|
|
{
|
|
|
|
condition: "title",
|
|
|
|
operator: "is",
|
|
|
|
value: title1
|
|
|
|
}
|
|
|
|
]
|
|
|
|
});
|
|
|
|
yield search.saveTx();
|
|
|
|
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
|
|
|
|
// Add an item that doesn't match search
|
|
|
|
var item = yield createDataObject('item', { title: title2 });
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
assert.equal(zp.itemsView.rowCount, 0);
|
|
|
|
|
|
|
|
// Modify conditions to match item
|
|
|
|
search.removeCondition(0);
|
|
|
|
search.addCondition("title", "is", title2);
|
|
|
|
yield search.saveTx();
|
|
|
|
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
|
|
|
|
assert.equal(zp.itemsView.rowCount, 1);
|
|
|
|
});
|
2016-03-14 02:59:19 +00:00
|
|
|
|
|
|
|
it("should remove items from Unfiled Items when added to a collection", function* () {
|
2016-03-15 05:17:07 +00:00
|
|
|
var userLibraryID = Zotero.Libraries.userLibraryID;
|
2016-03-14 02:59:19 +00:00
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
var item = yield createDataObject('item', { title: "Unfiled Item" });
|
2016-03-15 05:17:07 +00:00
|
|
|
yield zp.setVirtual(userLibraryID, 'unfiled', true);
|
|
|
|
var selected = yield cv.selectByID("U" + userLibraryID);
|
|
|
|
assert.ok(selected);
|
2016-03-14 02:59:19 +00:00
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
assert.isNumber(zp.itemsView.getRowIndexByID(item.id));
|
|
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
|
|
yield collection.addItem(item.id);
|
|
|
|
});
|
|
|
|
assert.isFalse(zp.itemsView.getRowIndexByID(item.id));
|
|
|
|
});
|
2015-04-30 21:06:38 +00:00
|
|
|
})
|
2015-05-23 08:25:47 +00:00
|
|
|
|
|
|
|
describe("#drop()", function () {
|
2016-04-23 02:45:37 +00:00
|
|
|
var httpd;
|
|
|
|
var port = 16213;
|
|
|
|
var baseURL = `http://localhost:${port}/`;
|
|
|
|
var pdfFilename = "test.pdf";
|
|
|
|
var pdfURL = baseURL + pdfFilename;
|
|
|
|
var pdfPath;
|
|
|
|
|
|
|
|
// Serve a PDF to test URL dragging
|
|
|
|
before(function () {
|
|
|
|
Components.utils.import("resource://zotero-unit/httpd.js");
|
|
|
|
httpd = new HttpServer();
|
|
|
|
httpd.start(port);
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append(pdfFilename);
|
|
|
|
pdfPath = file.path;
|
|
|
|
httpd.registerFile("/" + pdfFilename, file);
|
|
|
|
});
|
|
|
|
|
|
|
|
after(function* () {
|
|
|
|
var defer = new Zotero.Promise.defer();
|
|
|
|
httpd.stop(() => defer.resolve());
|
|
|
|
yield defer.promise;
|
|
|
|
});
|
|
|
|
|
2016-04-08 01:06:49 +00:00
|
|
|
it("should move a child item from one item to another", function* () {
|
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
var item1 = yield createDataObject('item', { title: "A", collections: [collection.id] });
|
|
|
|
var item2 = yield createDataObject('item', { title: "B", collections: [collection.id] });
|
|
|
|
var item3 = yield createDataObject('item', { itemType: 'note', parentID: item1.id });
|
|
|
|
|
|
|
|
let view = zp.itemsView;
|
|
|
|
yield view.selectItem(item3.id, true);
|
|
|
|
|
|
|
|
var deferred = Zotero.Promise.defer();
|
|
|
|
view.addEventListener('select', () => deferred.resolve());
|
|
|
|
|
|
|
|
view.drop(view.getRowIndexByID(item2.id), 0, {
|
|
|
|
dropEffect: 'copy',
|
|
|
|
effectAllowed: 'copy',
|
|
|
|
types: {
|
|
|
|
contains: function (type) {
|
|
|
|
return type == 'zotero/item';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
getData: function (type) {
|
|
|
|
if (type == 'zotero/item') {
|
|
|
|
return item3.id + "";
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mozItemCount: 1
|
|
|
|
})
|
|
|
|
|
|
|
|
yield deferred.promise;
|
|
|
|
|
|
|
|
// Old parent should be empty
|
|
|
|
assert.isFalse(view.isContainerOpen(view.getRowIndexByID(item1.id)));
|
|
|
|
assert.isTrue(view.isContainerEmpty(view.getRowIndexByID(item1.id)));
|
|
|
|
|
|
|
|
// New parent should be open
|
|
|
|
assert.isTrue(view.isContainerOpen(view.getRowIndexByID(item2.id)));
|
|
|
|
assert.isFalse(view.isContainerEmpty(view.getRowIndexByID(item2.id)));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should move a child item from last item in list to another", function* () {
|
|
|
|
var collection = yield createDataObject('collection');
|
|
|
|
yield waitForItemsLoad(win);
|
|
|
|
var item1 = yield createDataObject('item', { title: "A", collections: [collection.id] });
|
|
|
|
var item2 = yield createDataObject('item', { title: "B", collections: [collection.id] });
|
|
|
|
var item3 = yield createDataObject('item', { itemType: 'note', parentID: item2.id });
|
|
|
|
|
|
|
|
let view = zp.itemsView;
|
|
|
|
yield view.selectItem(item3.id, true);
|
|
|
|
|
|
|
|
var deferred = Zotero.Promise.defer();
|
|
|
|
view.addEventListener('select', () => deferred.resolve());
|
|
|
|
|
|
|
|
view.drop(view.getRowIndexByID(item1.id), 0, {
|
|
|
|
dropEffect: 'copy',
|
|
|
|
effectAllowed: 'copy',
|
|
|
|
types: {
|
|
|
|
contains: function (type) {
|
|
|
|
return type == 'zotero/item';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
getData: function (type) {
|
|
|
|
if (type == 'zotero/item') {
|
|
|
|
return item3.id + "";
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mozItemCount: 1
|
|
|
|
})
|
|
|
|
|
|
|
|
yield deferred.promise;
|
|
|
|
|
|
|
|
// Old parent should be empty
|
|
|
|
assert.isFalse(view.isContainerOpen(view.getRowIndexByID(item2.id)));
|
|
|
|
assert.isTrue(view.isContainerEmpty(view.getRowIndexByID(item2.id)));
|
|
|
|
|
|
|
|
// New parent should be open
|
|
|
|
assert.isTrue(view.isContainerOpen(view.getRowIndexByID(item1.id)));
|
|
|
|
assert.isFalse(view.isContainerEmpty(view.getRowIndexByID(item1.id)));
|
|
|
|
});
|
|
|
|
|
2015-05-23 08:25:47 +00:00
|
|
|
it("should create a top-level attachment when a file is dragged", function* () {
|
|
|
|
var file = getTestDataDirectory();
|
|
|
|
file.append('test.png');
|
|
|
|
|
|
|
|
var deferred = Zotero.Promise.defer();
|
|
|
|
itemsView.addEventListener('select', () => deferred.resolve());
|
|
|
|
|
|
|
|
itemsView.drop(0, -1, {
|
|
|
|
dropEffect: 'copy',
|
|
|
|
effectAllowed: 'copy',
|
|
|
|
types: {
|
|
|
|
contains: function (type) {
|
|
|
|
return type == 'application/x-moz-file';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mozItemCount: 1,
|
|
|
|
mozGetDataAt: function (type, i) {
|
|
|
|
if (type == 'application/x-moz-file' && i == 0) {
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
yield deferred.promise;
|
|
|
|
var items = itemsView.getSelectedItems();
|
|
|
|
var path = yield items[0].getFilePathAsync();
|
|
|
|
assert.equal(
|
|
|
|
(yield Zotero.File.getBinaryContentsAsync(path)),
|
|
|
|
(yield Zotero.File.getBinaryContentsAsync(file))
|
|
|
|
);
|
2016-04-23 02:45:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should create a top-level attachment when a URL is dragged", function* () {
|
|
|
|
var deferred = Zotero.Promise.defer();
|
|
|
|
itemsView.addEventListener('select', () => deferred.resolve());
|
|
|
|
|
|
|
|
itemsView.drop(0, -1, {
|
|
|
|
dropEffect: 'copy',
|
|
|
|
effectAllowed: 'copy',
|
|
|
|
types: {
|
|
|
|
contains: function (type) {
|
|
|
|
return type == 'text/x-moz-url';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
getData: function (type) {
|
|
|
|
if (type == 'text/x-moz-url') {
|
|
|
|
return pdfURL;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mozItemCount: 1,
|
|
|
|
})
|
|
|
|
|
|
|
|
yield deferred.promise;
|
|
|
|
var item = itemsView.getSelectedItems()[0];
|
|
|
|
assert.equal(item.getField('url'), pdfURL);
|
|
|
|
assert.equal(
|
|
|
|
(yield Zotero.File.getBinaryContentsAsync(yield item.getFilePathAsync())),
|
|
|
|
(yield Zotero.File.getBinaryContentsAsync(pdfPath))
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should create a child attachment when a URL is dragged", function* () {
|
|
|
|
var view = zp.itemsView;
|
|
|
|
var parentItem = yield createDataObject('item');
|
|
|
|
var parentRow = view.getRowIndexByID(parentItem.id);
|
|
|
|
|
|
|
|
var promise = waitForItemEvent('add');
|
|
|
|
|
|
|
|
itemsView.drop(parentRow, 0, {
|
|
|
|
dropEffect: 'copy',
|
|
|
|
effectAllowed: 'copy',
|
|
|
|
types: {
|
|
|
|
contains: function (type) {
|
|
|
|
return type == 'text/x-moz-url';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
getData: function (type) {
|
|
|
|
if (type == 'text/x-moz-url') {
|
|
|
|
return pdfURL;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mozItemCount: 1,
|
|
|
|
})
|
|
|
|
|
|
|
|
var itemIDs = yield promise;
|
|
|
|
var item = Zotero.Items.get(itemIDs[0]);
|
|
|
|
assert.equal(item.parentItemID, parentItem.id);
|
|
|
|
assert.equal(item.getField('url'), pdfURL);
|
|
|
|
assert.equal(
|
|
|
|
(yield Zotero.File.getBinaryContentsAsync(yield item.getFilePathAsync())),
|
|
|
|
(yield Zotero.File.getBinaryContentsAsync(pdfPath))
|
|
|
|
);
|
|
|
|
});
|
2015-05-23 08:25:47 +00:00
|
|
|
});
|
2015-04-30 21:06:38 +00:00
|
|
|
})
|