Make various collection methods synchronous

- Collection::getDescendents()
- Collections.getByLibrary()
- Collections.getByParent()

And various things that depend on those. (View with -w.)
This commit is contained in:
Dan Stillman 2016-03-25 18:40:47 -04:00
parent 7dfb62b8fc
commit 15a9fd5494
11 changed files with 275 additions and 237 deletions

View file

@ -401,128 +401,126 @@
</constructor>
<method name="onConditionSelected">
<body><![CDATA[
return Zotero.spawn(function* () {
// Skip if correct condition already selected
if (this.id('conditionsmenu').value==this.selectedCondition){
return;
}
var conditionsMenu = this.id('conditionsmenu');
var operatorsList = this.id('operatorsmenu');
this.selectedCondition = conditionsMenu.value;
this.selectedOperator = operatorsList.value;
var condition = Zotero.SearchConditions.get(conditionsMenu.value);
var operators = condition['operators'];
// Display appropriate operators for condition
var selectThis;
for(var i = 0, len = operatorsList.firstChild.childNodes.length; i < len; i++)
// Skip if correct condition already selected
if (this.id('conditionsmenu').value==this.selectedCondition){
return;
}
var conditionsMenu = this.id('conditionsmenu');
var operatorsList = this.id('operatorsmenu');
this.selectedCondition = conditionsMenu.value;
this.selectedOperator = operatorsList.value;
var condition = Zotero.SearchConditions.get(conditionsMenu.value);
var operators = condition['operators'];
// Display appropriate operators for condition
var selectThis;
for(var i = 0, len = operatorsList.firstChild.childNodes.length; i < len; i++)
{
var val = operatorsList.firstChild.childNodes[i].getAttribute('value');
var hidden = !operators[val];
operatorsList.firstChild.childNodes[i].setAttribute('hidden', hidden);
if (!hidden && (selectThis == null || this.selectedOperator == val))
{
var val = operatorsList.firstChild.childNodes[i].getAttribute('value');
var hidden = !operators[val];
operatorsList.firstChild.childNodes[i].setAttribute('hidden', hidden);
if (!hidden && (selectThis == null || this.selectedOperator == val))
{
selectThis = i;
selectThis = i;
}
}
operatorsList.selectedIndex = selectThis;
// Generate drop-down menu instead of textbox for certain conditions
switch (conditionsMenu.value){
case 'collection':
var rows = [];
var libraryID = this.parent.search.libraryID;
var cols = Zotero.Collections.getByLibrary(libraryID, true);
for (var i in cols) {
// Indent subcollections
var indent = '';
if (cols[i].level) {
for (var j=1; j<cols[i].level; j++) {
indent += ' ';
}
indent += '- ';
}
rows.push([indent + cols[i].name, 'C' + cols[i].key]);
}
}
operatorsList.selectedIndex = selectThis;
this.createValueMenu(rows);
break;
// Generate drop-down menu instead of textbox for certain conditions
switch (conditionsMenu.value){
case 'collection':
var rows = [];
var libraryID = this.parent.search.libraryID;
var cols = yield Zotero.Collections.getByLibrary(libraryID, true);
for (var i in cols) {
// Indent subcollections
var indent = '';
if (cols[i].level) {
for (var j=1; j<cols[i].level; j++) {
indent += ' ';
}
indent += '- ';
}
rows.push([indent + cols[i].name, 'C' + cols[i].key]);
case 'savedSearch':
var rows = [];
var libraryID = this.parent.search.libraryID;
var searches = Zotero.Searches.getAll(libraryID);
for (var i in searches) {
if (searches[i].id != this.parent.search.id) {
rows.push([searches[i].name, 'S' + searches[i].key]);
}
this.createValueMenu(rows);
break;
}
this.createValueMenu(rows);
break;
case 'itemType':
var t = Zotero.ItemTypes.getTypes();
case 'savedSearch':
var rows = [];
var libraryID = this.parent.search.libraryID;
var searches = Zotero.Searches.getAll(libraryID);
for (var i in searches) {
if (searches[i].id != this.parent.search.id) {
rows.push([searches[i].name, 'S' + searches[i].key]);
}
}
this.createValueMenu(rows);
break;
case 'itemType':
var t = Zotero.ItemTypes.getTypes();
// Sort by localized name
var types = [];
for (var i=0; i<t.length; i++) {
types.push({
id: t[i].id,
name: t[i].name,
localized: Zotero.ItemTypes.getLocalizedString(t[i].id)
});
}
var collation = Zotero.getLocaleCollation();
types.sort(function(a, b) {
return collation.compareString(1, a.localized, b.localized);
// Sort by localized name
var types = [];
for (var i=0; i<t.length; i++) {
types.push({
id: t[i].id,
name: t[i].name,
localized: Zotero.ItemTypes.getLocalizedString(t[i].id)
});
for (var i in types) {
types[i][0] = types[i].localized;
types[i][1] = types[i].name;
delete types[i]['name'];
delete types[i]['id'];
}
this.createValueMenu(types);
break;
}
var collation = Zotero.getLocaleCollation();
types.sort(function(a, b) {
return collation.compareString(1, a.localized, b.localized);
});
case 'fileTypeID':
var types = Zotero.FileTypes.getTypes();
for (var i in types) {
types[i][0] = Zotero.getString('fileTypes.' + types[i]['name']);
types[i][1] = types[i]['id'];
delete types[i]['name'];
delete types[i]['id'];
}
this.createValueMenu(types);
break;
default:
if (operatorsList.value=='isInTheLast')
{
this.id('value-date-age').value = this.value;
}
// Textbox
else {
// If switching from menu to textbox, clear value
if (this.id('valuefield').hidden){
this.id('valuefield').value = '';
}
// If switching between textbox conditions, get loaded value for new one
else {
this.id('valuefield').value = this.value;
}
// Update field drop-down if applicable
this.id('valuefield').update(conditionsMenu.value, this.mode);
}
}
for (var i in types) {
types[i][0] = types[i].localized;
types[i][1] = types[i].name;
delete types[i]['name'];
delete types[i]['id'];
}
this.createValueMenu(types);
break;
this.onOperatorSelected();
}.bind(this));
case 'fileTypeID':
var types = Zotero.FileTypes.getTypes();
for (var i in types) {
types[i][0] = Zotero.getString('fileTypes.' + types[i]['name']);
types[i][1] = types[i]['id'];
delete types[i]['name'];
delete types[i]['id'];
}
this.createValueMenu(types);
break;
default:
if (operatorsList.value=='isInTheLast')
{
this.id('value-date-age').value = this.value;
}
// Textbox
else {
// If switching from menu to textbox, clear value
if (this.id('valuefield').hidden){
this.id('valuefield').value = '';
}
// If switching between textbox conditions, get loaded value for new one
else {
this.id('valuefield').value = this.value;
}
// Update field drop-down if applicable
this.id('valuefield').update(conditionsMenu.value, this.mode);
}
}
this.onOperatorSelected();
]]></body>
</method>
<method name="onOperatorSelected">
@ -593,50 +591,48 @@
<parameter name="parent"/>
<parameter name="condition"/>
<body><![CDATA[
return Zotero.spawn(function* () {
this.parent = parent;
this.conditionID = condition['id'];
this.parent = parent;
this.conditionID = condition['id'];
if(this.parent.search)
{
this.dontupdate = true; //so that the search doesn't get updated while we are creating controls.
var prefix = '';
if(this.parent.search)
{
this.dontupdate = true; //so that the search doesn't get updated while we are creating controls.
var prefix = '';
// Handle special conditions
switch (condition.condition) {
case 'savedSearch':
prefix = 'S';
break;
// Handle special conditions
switch (condition.condition) {
case 'savedSearch':
prefix = 'S';
break;
case 'collection':
prefix = 'C';
break;
}
this.id('conditionsmenu').value = condition.condition;
// Convert datetimes from UTC to localtime
if ((condition['condition']=='accessDate' ||
condition['condition']=='dateAdded' ||
condition['condition']=='dateModified') &&
Zotero.Date.isSQLDateTime(condition['value'])){
condition['value'] =
Zotero.Date.dateToSQL(Zotero.Date.sqlToDate(condition['value'], true));
}
this.mode = condition['mode'];
this.id('operatorsmenu').value = condition['operator'];
this.value = prefix +
(condition.value ? condition.value : '');
this.dontupdate = false;
case 'collection':
prefix = 'C';
break;
}
yield this.onConditionSelected();
this.id('conditionsmenu').value = condition.condition;
this.id('conditionsmenu').focus();
}.bind(this));
// Convert datetimes from UTC to localtime
if ((condition['condition']=='accessDate' ||
condition['condition']=='dateAdded' ||
condition['condition']=='dateModified') &&
Zotero.Date.isSQLDateTime(condition['value'])){
condition['value'] =
Zotero.Date.dateToSQL(Zotero.Date.sqlToDate(condition['value'], true));
}
this.mode = condition['mode'];
this.id('operatorsmenu').value = condition['operator'];
this.value = prefix +
(condition.value ? condition.value : '');
this.dontupdate = false;
}
this.onConditionSelected();
this.id('conditionsmenu').focus();
]]></body>
</method>
<!-- Gets the value from the field and updates the associated search condition -->

View file

@ -304,7 +304,7 @@ var Zotero_File_Interface = new function() {
let leafName = translation.location.leafName;
collectionName = (translation.location.isDirectory() || leafName.indexOf(".") === -1 ? leafName
: leafName.substr(0, leafName.lastIndexOf(".")));
let allCollections = yield Zotero.Collections.getByLibrary(libraryID);
let allCollections = Zotero.Collections.getByLibrary(libraryID);
for(var i=0; i<allCollections.length; i++) {
if(allCollections[i].name == collectionName) {
collectionName += " "+(new Date()).toLocaleString();

View file

@ -46,12 +46,12 @@ Zotero.API = {
switch (params.scopeObject) {
case 'collections':
if (params.scopeObjectKey) {
var col = yield Zotero.Collections.getByLibraryAndKeyAsync(
var col = Zotero.Collections.getByLibraryAndKeyAsync(
params.libraryID, params.scopeObjectKey
);
}
else {
var col = yield Zotero.Collections.getAsync(params.scopeObjectID);
var col = Zotero.Collections.get(params.scopeObjectID);
}
if (!col) {
throw new Error('Invalid collection ID or key');

View file

@ -1153,10 +1153,10 @@ Zotero.CollectionTreeView.prototype._expandRow = Zotero.Promise.coroutine(functi
}
if (isLibrary) {
var collections = yield Zotero.Collections.getByLibrary(libraryID, treeRow.ref.id);
var collections = Zotero.Collections.getByLibrary(libraryID, treeRow.ref.id);
}
else if (isCollection) {
var collections = yield Zotero.Collections.getByParent(treeRow.ref.id);
var collections = Zotero.Collections.getByParent(treeRow.ref.id);
}
if (isLibrary) {
@ -1549,10 +1549,9 @@ Zotero.CollectionTreeView.prototype.canDropCheck = function (row, orient, dataTr
}
// Nor in their children
// TODO: figure out synchronously from tree
/*if (yield col.hasDescendent('collection', treeRow.ref.id)) {
if (col.hasDescendent('collection', treeRow.ref.id)) {
return false;
}*/
}
}
// Dragging a collection to a different library
else {
@ -1657,9 +1656,9 @@ Zotero.CollectionTreeView.prototype.canDropCheckAsync = Zotero.Promise.coroutine
return false;
}
var descendents = yield col.getDescendents(false, 'collection');
var descendents = col.getDescendents(false, 'collection');
for each(var descendent in descendents) {
descendent = yield Zotero.Collections.getAsync(descendent.id);
descendent = Zotero.Collections.get(descendent.id);
// Disallow if linked collection already exists for any subcollections
//
// If this is allowed in the future for the root collection,

View file

@ -242,7 +242,7 @@ Zotero.Collection.prototype._initSave = Zotero.Promise.coroutine(function* (env)
throw new Error('Cannot move collection into itself!');
}
if (this.id && (yield this.hasDescendent('collection', newParent.id))) {
if (this.id && this.hasDescendent('collection', newParent.id)) {
throw ('Cannot move collection "' + this.name + '" into one of its own descendents');
}
@ -440,15 +440,15 @@ Zotero.Collection.prototype.hasItem = function(itemID) {
}
Zotero.Collection.prototype.hasDescendent = Zotero.Promise.coroutine(function* (type, id) {
var descendents = yield this.getDescendents();
Zotero.Collection.prototype.hasDescendent = function (type, id) {
var descendents = this.getDescendents();
for (var i=0, len=descendents.length; i<len; i++) {
if (descendents[i].type == type && descendents[i].id == id) {
return true;
}
}
return false;
});
};
/**
@ -551,7 +551,7 @@ Zotero.Collection.prototype._eraseData = Zotero.Promise.coroutine(function* (env
var collections = [this.id];
var descendents = yield this.getDescendents(false, null, true);
var descendents = this.getDescendents(false, null, true);
var items = [];
var del = [];
@ -701,7 +701,6 @@ Zotero.Collection.prototype.toJSON = function (options = {}) {
/**
* Returns an array of descendent collections and items
*
* @param {Boolean} [recursive=false] Descend into subcollections
* @param {Boolean} [nested=false] Return multidimensional array with 'children'
* nodes instead of flat array
* @param {String} [type] 'item', 'collection', or NULL for both
@ -709,13 +708,11 @@ Zotero.Collection.prototype.toJSON = function (options = {}) {
* @return {Promise<Object[]>} - A promise for an array of objects with 'id', 'key',
* 'type' ('item' or 'collection'), 'parent', and, if collection, 'name' and the nesting 'level'
*/
Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (recursive, nested, type, includeDeletedItems, level) {
Zotero.Collection.prototype.getDescendents = function (nested, type, includeDeletedItems, level) {
if (!this.id) {
throw new Error('Cannot be called on an unsaved item');
}
var toReturn = [];
if (!level) {
level = 1;
}
@ -726,39 +723,40 @@ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (re
case 'collection':
break;
default:
throw ("Invalid type '" + type + "' in Collection.getChildren()");
throw new (`Invalid type '${type}'`);
}
}
// 0 == collection
// 1 == item
var sql = 'SELECT collectionID AS id, collectionName AS name, '
+ "0 AS type, collectionName AS collectionName, key "
+ 'FROM collections WHERE parentCollectionID=?1';
var collections = Zotero.Collections.getByParent(this.id);
var children = collections.map(c => ({
id: c.id,
name: c.name,
type: 0,
key: c.key
}));
if (!type || type == 'item') {
sql += ' UNION SELECT itemID AS id, NULL AS name, 1 AS type, NULL AS collectionName, key '
+ 'FROM collectionItems JOIN items USING (itemID) WHERE collectionID=?1';
if (!includeDeletedItems) {
sql += " AND itemID NOT IN (SELECT itemID FROM deletedItems)";
}
let items = this.getChildItems(false, includeDeletedItems);
children = children.concat(items.map(i => ({
id: i.id,
name: null,
type: 1,
key: i.key
})));
}
var children = yield Zotero.DB.queryAsync(sql, this.id);
children.sort(function (a, b) {
if (a.name === null || b.name === null) return 0;
return Zotero.localeCompare(a.name, b.name)
});
var toReturn = [];
for(var i=0, len=children.length; i<len; i++) {
// This seems to not work without parseInt() even though
// typeof children[i]['type'] == 'number' and
// children[i]['type'] === parseInt(children[i]['type']),
// which sure seems like a bug to me
switch (parseInt(children[i].type)) {
switch (children[i].type) {
case 0:
if (!type || type=='collection') {
toReturn.push({
id: children[i].id,
name: children[i].collectionName,
name: children[i].name,
key: children[i].key,
type: 'collection',
level: level,
@ -766,19 +764,17 @@ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (re
});
}
if (recursive) {
let child = yield this.ObjectsClass.getAsync(children[i].id);
let descendents = yield child.getChildren(
true, nested, type, includeDeletedItems, level+1
);
if (nested) {
toReturn[toReturn.length-1].children = descendents;
}
else {
for (var j=0, len2=descendents.length; j<len2; j++) {
toReturn.push(descendents[j]);
}
let child = this.ObjectsClass.get(children[i].id);
let descendents = child.getDescendents(
nested, type, includeDeletedItems, level + 1
);
if (nested) {
toReturn[toReturn.length-1].children = descendents;
}
else {
for (var j=0, len2=descendents.length; j<len2; j++) {
toReturn.push(descendents[j]);
}
}
break;
@ -797,17 +793,7 @@ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (re
}
return toReturn;
});
/**
* Alias for the recursive mode of getChildren()
*
* @return {Promise}
*/
Zotero.Collection.prototype.getDescendents = function (nested, type, includeDeletedItems) {
return this.getChildren(true, nested, type, includeDeletedItems);
}
};
/**

View file

@ -62,7 +62,7 @@ Zotero.Collections = function() {
*
* @param {Integer} libraryID
* @param {Boolean} [recursive=false]
* @return {Promise<Zotero.Collection[]>}
* @return {Zotero.Collection[]}
*/
this.getByLibrary = function (libraryID, recursive) {
return _getByContainer(libraryID, null, recursive);
@ -74,24 +74,26 @@ Zotero.Collections = function() {
*
* @param {Integer} parentCollectionID
* @param {Boolean} [recursive=false]
* @return {Promise<Zotero.Collection[]>}
* @return {Zotero.Collection[]}
*/
this.getByParent = function (parentCollectionID, recursive) {
return _getByContainer(null, parentCollectionID, recursive);
}
var _getByContainer = Zotero.Promise.coroutine(function* (libraryID, parentID, recursive) {
let children;
var _getByContainer = function (libraryID, parentID, recursive) {
let children = [];
if (parentID) {
let parent = Zotero.Collections.get(parentID);
children = parent.getChildCollections();
} else if (libraryID) {
let sql = "SELECT collectionID AS id FROM collections "
+ "WHERE libraryID=? AND parentCollectionID IS NULL";
let ids = yield Zotero.DB.columnQueryAsync(sql, [libraryID]);
children = yield this.getAsync(ids);
for (let id in this._objectCache) {
let c = this._objectCache[id];
if (c.libraryID == libraryID && !c.parentKey) {
children.push(c);
}
}
} else {
throw new Error("Either library ID or parent collection ID must be provided");
}
@ -110,9 +112,9 @@ Zotero.Collections = function() {
var obj = children[i];
toReturn.push(obj);
var desc = yield obj.getDescendents(false, 'collection');
var desc = obj.getDescendents(false, 'collection');
for (var j in desc) {
var obj2 = yield this.getAsync(desc[j]['id']);
var obj2 = this.get(desc[j].id);
if (!obj2) {
throw new Error('Collection ' + desc[j] + ' not found');
}
@ -130,7 +132,7 @@ Zotero.Collections = function() {
}
return toReturn;
}.bind(this));
}.bind(this);
this.getCollectionsContainingItems = function (itemIDs, asIDs) {

View file

@ -2315,7 +2315,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine
getCollections = configOptions.getCollections || false;
switch (this._export.type) {
case 'collection':
yield this._itemGetter.setCollection(this._export.collection, getCollections);
this._itemGetter.setCollection(this._export.collection, getCollections);
break;
case 'items':
this._itemGetter.setItems(this._export.items);

View file

@ -657,13 +657,13 @@ Zotero.Translate.ItemGetter.prototype = {
this.numItems = this._itemsLeft.length;
},
"setCollection": Zotero.Promise.coroutine(function* (collection, getChildCollections) {
"setCollection": function (collection, getChildCollections) {
// get items in this collection
var items = new Set(collection.getChildItems());
if(getChildCollections) {
// get child collections
this._collectionsLeft = yield Zotero.Collections.getByParent(collection.id, true);
this._collectionsLeft = Zotero.Collections.getByParent(collection.id, true);
// get items in child collections
for (let collection of this._collectionsLeft) {
@ -674,13 +674,13 @@ Zotero.Translate.ItemGetter.prototype = {
this._itemsLeft = Array.from(items.values());
this.numItems = this._itemsLeft.length;
}),
},
"setAll": Zotero.Promise.coroutine(function* (libraryID, getChildCollections) {
this._itemsLeft = yield Zotero.Items.getAll(libraryID, true);
if(getChildCollections) {
this._collectionsLeft = yield Zotero.Collections.getByLibrary(libraryID, true);
this._collectionsLeft = Zotero.Collections.getByLibrary(libraryID, true);
}
this.numItems = this._itemsLeft.length;

View file

@ -200,4 +200,57 @@ describe("Zotero.Collection", function() {
assert.lengthOf(collection.getChildItems(false, true), 1);
})
})
describe("#getDescendents()", function () {
var collection0, collection1, collection2, collection3, item1, item2, item3;
before(function* () {
collection0 = yield createDataObject('collection');
item1 = yield createDataObject('item', { collections: [collection0.id] });
collection1 = yield createDataObject('collection', { parentKey: collection0.key });
item2 = yield createDataObject('item', { collections: [collection1.id] });
collection2 = yield createDataObject('collection', { parentKey: collection1.key });
collection3 = yield createDataObject('collection', { parentKey: collection1.key });
item3 = yield createDataObject('item', { collections: [collection2.id] });
item3.deleted = true;
yield item3.saveTx();
});
it("should return a flat array of collections and items", function* () {
var desc = collection0.getDescendents();
assert.lengthOf(desc, 5);
assert.sameMembers(
desc.map(x => x.type + ':' + x.id + ':' + (x.name || '') + ':' + x.parent),
[
'item:' + item1.id + '::' + collection0.id,
'item:' + item2.id + '::' + collection1.id,
'collection:' + collection1.id + ':' + collection1.name + ':' + collection0.id,
'collection:' + collection2.id + ':' + collection2.name + ':' + collection1.id,
'collection:' + collection3.id + ':' + collection3.name + ':' + collection1.id
]
);
});
it("should return nested arrays of collections and items", function* () {
var desc = collection0.getDescendents(true);
assert.lengthOf(desc, 2);
assert.sameMembers(
desc.map(x => x.type + ':' + x.id + ':' + (x.name || '') + ':' + x.parent),
[
'item:' + item1.id + '::' + collection0.id,
'collection:' + collection1.id + ':' + collection1.name + ':' + collection0.id,
]
);
var c = desc[0].type == 'collection' ? desc[0] : desc[1];
assert.lengthOf(c.children, 3);
assert.sameMembers(
c.children.map(x => x.type + ':' + x.id + ':' + (x.name || '') + ':' + x.parent),
[
'item:' + item2.id + '::' + collection1.id,
'collection:' + collection2.id + ':' + collection2.name + ':' + collection1.id,
'collection:' + collection3.id + ':' + collection3.name + ':' + collection1.id
]
);
});
});
})

View file

@ -4,7 +4,7 @@ describe("Zotero.Collections", function () {
var col1 = yield createDataObject('collection');
var col2 = yield createDataObject('collection');
var col3 = yield createDataObject('collection', { parentID: col2.id });
var cols = yield Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID);
var cols = Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID);
assert.isAbove(cols.length, 1);
assert.includeMembers(cols.map(col => col.id), [col1.id, col2.id]);
assert.ok(cols.every(col =>
@ -23,7 +23,7 @@ describe("Zotero.Collections", function () {
var col5 = yield createDataObject('collection', { name: "E", parentID: col2.id });
var col6 = yield createDataObject('collection', { name: "G", parentID: col3.id });
var col7 = yield createDataObject('collection', { name: "F", parentID: col3.id });
var cols = yield Zotero.Collections.getByLibrary(libraryID, true);
var cols = Zotero.Collections.getByLibrary(libraryID, true);
assert.isAbove(cols.length, 6);
var ids = cols.map(col => col.id);
assert.includeMembers(
@ -44,8 +44,8 @@ describe("Zotero.Collections", function () {
var col1 = yield createDataObject('collection');
var col2 = yield createDataObject('collection');
var col3 = yield createDataObject('collection', { parentID: col2.id });
assert.lengthOf((yield Zotero.Collections.getByParent(col1.id)), 0);
var cols = yield Zotero.Collections.getByParent(col2.id);
assert.lengthOf(Zotero.Collections.getByParent(col1.id), 0);
var cols = Zotero.Collections.getByParent(col2.id);
assert.lengthOf(cols, 1);
assert.sameMembers(cols.map(col => col.id), [col3.id]);
})
@ -55,8 +55,8 @@ describe("Zotero.Collections", function () {
var col2 = yield createDataObject('collection');
var col3 = yield createDataObject('collection', { parentID: col2.id });
var col4 = yield createDataObject('collection', { parentID: col3.id });
assert.lengthOf((yield Zotero.Collections.getByParent(col1.id)), 0);
var cols = yield Zotero.Collections.getByParent(col2.id, true);
assert.lengthOf(Zotero.Collections.getByParent(col1.id), 0);
var cols = Zotero.Collections.getByParent(col2.id, true);
assert.lengthOf(cols, 2);
assert.includeMembers(cols.map(col => col.id), [col3.id, col4.id]);
})

View file

@ -16,7 +16,9 @@ describe("Zotero_File_Interface", function() {
testFile.append("allTypesAndFields.js");
yield win.Zotero_File_Interface.importFile(testFile);
let importedCollection = yield Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID).filter(x => x.name == 'allTypesAndFields');
let importedCollection = Zotero.Collections.getByLibrary(
Zotero.Libraries.userLibraryID
).filter(x => x.name == 'allTypesAndFields');
assert.equal(importedCollection.length, 1);
let childItems = importedCollection[0].getChildItems();
let savedItems = {};