a94323fc15
Added Zotero.DataObjects.sortByParent() to sort child items immediately after their parent items. Zotero.DataObjects.sortByLevel(), which is used for collections, sorts each level together, but that's less appropriate for items where, e.g., an embedded-image attachment should immediately follow the note that depends on it.
261 lines
7.7 KiB
JavaScript
261 lines
7.7 KiB
JavaScript
"use strict";
|
|
|
|
describe("Zotero.DataObjects", function () {
|
|
var types = ['collection', 'item', 'search'];
|
|
|
|
describe("#get()", function () {
|
|
it("should return false for nonexistent objects", function* () {
|
|
assert.isFalse(Zotero.Items.get(3464363));
|
|
});
|
|
});
|
|
|
|
describe("#getAsync()", function () {
|
|
// TEMP: Currently just a warning
|
|
it.skip("show throw if passed an invalid id", function* () {
|
|
var e = yield getPromiseError(Zotero.Items.getAsync("[Object]"));
|
|
assert.ok(e);
|
|
assert.include(e.message, '(string)');
|
|
});
|
|
});
|
|
|
|
describe("#getLibraryAndKeyFromID()", function () {
|
|
it("should return a libraryID and key within a transaction", function* () {
|
|
for (let type of types) {
|
|
let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(type);
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
let obj = createUnsavedDataObject(type);
|
|
yield obj.save();
|
|
|
|
var {libraryID, key} = objectsClass.getLibraryAndKeyFromID(obj.id);
|
|
assert.equal(libraryID, Zotero.Libraries.userLibraryID);
|
|
assert.ok(key);
|
|
assert.typeOf(key, 'string');
|
|
assert.equal(key, obj.key);
|
|
|
|
yield obj.erase();
|
|
});
|
|
}
|
|
});
|
|
|
|
it("should return false after a save failure", function* () {
|
|
for (let type of types) {
|
|
let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(type);
|
|
var obj;
|
|
try {
|
|
yield Zotero.DB.executeTransaction(function* () {
|
|
obj = createUnsavedDataObject(type);
|
|
yield obj.save();
|
|
throw 'Aborting transaction -- ignore';
|
|
});
|
|
}
|
|
catch (e) {
|
|
if (typeof e != 'string' || !e.startsWith('Aborting transaction')) throw e;
|
|
}
|
|
|
|
// The registered identifiers should be reset in a rollback handler
|
|
var libraryKey = objectsClass.getLibraryAndKeyFromID(obj.id);
|
|
assert.isFalse(libraryKey);
|
|
}
|
|
});
|
|
})
|
|
|
|
describe("#exists()", function () {
|
|
it("should return false after object is deleted", function* () {
|
|
for (let type of types) {
|
|
let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(type);
|
|
let obj = yield createDataObject(type);
|
|
let id = obj.id;
|
|
yield obj.eraseTx();
|
|
assert.isFalse(objectsClass.exists(id), type + " does not exist");
|
|
}
|
|
})
|
|
})
|
|
|
|
|
|
describe("#sortByLevel()", function () {
|
|
it("should return collections sorted from top-level to deepest", async function () {
|
|
// - A
|
|
// - B
|
|
// - C
|
|
// - D
|
|
// - E
|
|
// - F
|
|
// - G
|
|
// - H
|
|
// - I
|
|
//
|
|
// Leave out B and G
|
|
//
|
|
// Order should be {A, E}, {D, F}, {C, I}, {H} (internal order is undefined)
|
|
|
|
var check = function (arr) {
|
|
assert.sameMembers(arr.slice(0, 2), [c1, c5]);
|
|
assert.sameMembers(arr.slice(2, 4), [c4, c6]);
|
|
assert.sameMembers(arr.slice(4, 6), [c3, c9]);
|
|
assert.equal(arr[6], c8);
|
|
};
|
|
|
|
var c1 = await createDataObject('collection', { "name": "A" });
|
|
var c2 = await createDataObject('collection', { "name": "B", parentID: c1.id });
|
|
var c3 = await createDataObject('collection', { "name": "C", parentID: c2.id });
|
|
var c4 = await createDataObject('collection', { "name": "D", parentID: c1.id });
|
|
var c5 = await createDataObject('collection', { "name": "E" });
|
|
var c6 = await createDataObject('collection', { "name": "F", parentID: c5.id });
|
|
var c7 = await createDataObject('collection', { "name": "G", parentID: c6.id });
|
|
var c8 = await createDataObject('collection', { "name": "H", parentID: c7.id });
|
|
var c9 = await createDataObject('collection', { "name": "I", parentID: c6.id });
|
|
|
|
var arr = Zotero.Collections.sortByLevel([c1, c3, c4, c5, c6, c8, c9]);
|
|
//Zotero.debug(arr.map(id => Zotero.Collections.get(id).name));
|
|
check(arr);
|
|
|
|
// Check reverse order
|
|
arr = Zotero.Collections.sortByLevel([c1, c3, c4, c5, c6, c8, c9].reverse());
|
|
//Zotero.debug(arr.map(id => Zotero.Collections.get(id).name));
|
|
check(arr);
|
|
});
|
|
});
|
|
|
|
|
|
describe("#sortByParent", function () {
|
|
it("should return items sorted hierarchically", async function () {
|
|
// - A
|
|
// - B
|
|
// - C
|
|
// - D
|
|
// - E
|
|
// - F
|
|
// - G
|
|
// - H
|
|
// - I
|
|
//
|
|
// Leave out B and G
|
|
//
|
|
// Order should be top-down, with child items included immediately after their parents.
|
|
// The order of items at the same level is undefined.
|
|
|
|
function check(arr) {
|
|
var str = arr.map(o => title(o)).join('');
|
|
var possibilities = [
|
|
'ACDEFHI',
|
|
'ACDEFIH',
|
|
|
|
'ADCEFHI',
|
|
'ADCEFIH',
|
|
|
|
'EFHIACD',
|
|
'EFHIADC',
|
|
|
|
'EFIHACD',
|
|
'EFIHADC',
|
|
];
|
|
assert.oneOf(str, possibilities);
|
|
}
|
|
|
|
function title(o) {
|
|
return o.getDisplayTitle() || o.getTags()[0].tag;
|
|
}
|
|
|
|
var a = await createDataObject('item', { title: "A" });
|
|
var b = await createDataObject('item', { note: "B", itemType: 'note', parentID: a.id });
|
|
var c = await createEmbeddedImage(b, { tags: [{ tag: 'C' }] });
|
|
var d = await importPDFAttachment(a, { title: 'D' });
|
|
var e = await createDataObject('item', { title: "E" });
|
|
var f = await importPDFAttachment(e, { title: 'F' });
|
|
var g = await createAnnotation('image', f, { tags: [{ tag: 'G' }] });
|
|
var h = await createEmbeddedImage(g, { tags: [{ tag: 'H' }] });
|
|
var i = await createAnnotation('highlight', f, { tags: [{ tag: 'I' }] });
|
|
|
|
var arr = Zotero.Items.sortByParent([a, c, d, e, f, h, i]);
|
|
Zotero.debug(arr.map(o => title(o)));
|
|
check(arr);
|
|
|
|
// Reverse order
|
|
arr = Zotero.Items.sortByParent([a, c, d, e, f, h, i].reverse());
|
|
Zotero.debug(arr.map(o => title(o)));
|
|
check(arr);
|
|
|
|
// Top-level first
|
|
arr = Zotero.Items.sortByParent([a, e, c, d, f, h, i]);
|
|
Zotero.debug(arr.map(o => title(o)));
|
|
check(arr);
|
|
|
|
// Child first
|
|
arr = Zotero.Items.sortByParent([c, h, d, i, f, a, e]);
|
|
Zotero.debug(arr.map(o => title(o)));
|
|
check(arr);
|
|
|
|
// Random
|
|
arr = Zotero.Items.sortByParent([i, e, d, h, c, a, f]);
|
|
Zotero.debug(arr.map(o => title(o)));
|
|
check(arr);
|
|
});
|
|
});
|
|
|
|
|
|
describe("#_setIdentifier", function () {
|
|
it("should not allow an id change", function* () {
|
|
var item = yield createDataObject('item');
|
|
try {
|
|
item.id = item.id + 1;
|
|
}
|
|
catch (e) {
|
|
assert.equal(e.message, "ID cannot be changed");
|
|
return;
|
|
}
|
|
assert.fail("ID change allowed");
|
|
})
|
|
|
|
it("should not allow a key change", function* () {
|
|
var item = yield createDataObject('item');
|
|
try {
|
|
item.key = Zotero.DataObjectUtilities.generateKey();
|
|
}
|
|
catch (e) {
|
|
assert.equal(e.message, "Key cannot be changed");
|
|
return;
|
|
}
|
|
assert.fail("Key change allowed");
|
|
})
|
|
|
|
it("should not allow key to be set if id is set", function* () {
|
|
var item = createUnsavedDataObject('item');
|
|
item.id = Zotero.Utilities.rand(100000, 1000000);
|
|
try {
|
|
item.libraryID = Zotero.Libraries.userLibraryID;
|
|
item.key = Zotero.DataObjectUtilities.generateKey();
|
|
}
|
|
catch (e) {
|
|
assert.equal(e.message, "Cannot set key if id is already set");
|
|
return;
|
|
}
|
|
assert.fail("ID change allowed");
|
|
})
|
|
|
|
it("should not allow id to be set if key is set", function* () {
|
|
var item = createUnsavedDataObject('item');
|
|
item.libraryID = Zotero.Libraries.userLibraryID;
|
|
item.key = Zotero.DataObjectUtilities.generateKey();
|
|
try {
|
|
item.id = Zotero.Utilities.rand(100000, 1000000);
|
|
}
|
|
catch (e) {
|
|
assert.equal(e.message, "Cannot set id if key is already set");
|
|
return;
|
|
}
|
|
assert.fail("Key change allowed");
|
|
})
|
|
|
|
it("should not allow key to be set if library isn't set", function* () {
|
|
var item = createUnsavedDataObject('item');
|
|
try {
|
|
item.key = Zotero.DataObjectUtilities.generateKey();
|
|
}
|
|
catch (e) {
|
|
assert.equal(e.message, "libraryID must be set before key");
|
|
return;
|
|
}
|
|
assert.fail("libraryID change allowed");
|
|
})
|
|
})
|
|
})
|