zotero/test/tests/utilities_internalTest.js
Dan Stillman e9ea9ae171 Leave Event Place and Publisher Place in Extra on import
These CSL variables are both currently mapped to the Zotero Place field,
but that's imprecise and will change:

https://github.com/citation-style-language/zotero-bits/issues/6

So for now, don't convert these to a Place line or make them eligible
for migration to a real field (once we turn that on).

https://groups.google.com/d/msgid/zotero-dev/806a22e3-3d6a-4d86-8747-10c787291a93%40googlegroups.com
2020-04-04 04:17:51 -04:00

455 lines
16 KiB
JavaScript

"use strict";
describe("Zotero.Utilities.Internal", function () {
var ZUI;
before(function () {
ZUI = Zotero.Utilities.Internal;
});
describe("#md5()", function () {
it("should generate hex string given file path", function* () {
var file = OS.Path.join(getTestDataDirectory().path, 'test.png');
assert.equal(
Zotero.Utilities.Internal.md5(Zotero.File.pathToFile(file)),
'93da8f1e5774c599f0942dcecf64b11c'
);
})
})
describe("#md5Async()", function () {
it("should generate hex string given file path", function* () {
var file = OS.Path.join(getTestDataDirectory().path, 'test.png');
yield assert.eventually.equal(
Zotero.Utilities.Internal.md5Async(file),
'93da8f1e5774c599f0942dcecf64b11c'
);
});
it("should generate hex string given file path for file bigger than chunk size", function* () {
var tmpDir = Zotero.getTempDirectory().path;
var file = OS.Path.join(tmpDir, 'md5Async');
let encoder = new TextEncoder();
let arr = encoder.encode("".padStart(100000, "a"));
yield OS.File.writeAtomic(file, arr);
yield assert.eventually.equal(
Zotero.Utilities.Internal.md5Async(file),
'1af6d6f2f682f76f80e606aeaaee1680'
);
yield OS.File.remove(file);
});
})
describe("#gzip()/gunzip()", function () {
it("should compress and decompress a Unicode text string", function* () {
var text = "Voilà! \u1F429";
var compstr = yield Zotero.Utilities.Internal.gzip(text);
assert.isAbove(compstr.length, 0);
assert.notEqual(compstr.length, text.length);
var str = yield Zotero.Utilities.Internal.gunzip(compstr);
assert.equal(str, text);
});
});
describe("#delayGenerator", function () {
var spy;
before(function () {
spy = sinon.spy(Zotero.Promise, "delay");
});
afterEach(function () {
spy.resetHistory();
});
after(function () {
spy.restore();
});
it("should delay for given amounts of time without limit", function* () {
var intervals = [1, 2];
var gen = Zotero.Utilities.Internal.delayGenerator(intervals);
// When intervals are exhausted, keep using last interval
var testIntervals = intervals.slice();
testIntervals.push(intervals[intervals.length - 1]);
for (let i of testIntervals) {
let val = yield gen.next().value;
assert.isTrue(val);
assert.isTrue(spy.calledWith(i));
spy.resetHistory();
}
});
it("should return false when maxTime is reached", function* () {
var intervals = [5, 10];
var gen = Zotero.Utilities.Internal.delayGenerator(intervals, 30);
// When intervals are exhausted, keep using last interval
var testIntervals = intervals.slice();
testIntervals.push(intervals[intervals.length - 1]);
for (let i of testIntervals) {
let val = yield gen.next().value;
assert.isTrue(val);
assert.isTrue(spy.calledWith(i));
spy.resetHistory();
}
// Another interval would put us over maxTime, so return false immediately
let val = yield gen.next().value;
assert.isFalse(val);
assert.isFalse(spy.called);
});
});
describe("#extractExtraFields()", function () {
it("should ignore 'type: note' and 'type: attachment'", function () {
var str = 'type: note';
var { itemType, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.isNull(itemType);
assert.equal(extra, 'type: note');
});
it("should use the first mapped Zotero type for a CSL type", function () {
var str = 'type: personal_communication';
var { itemType, fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(itemType, 'letter');
});
it("should extract a field", function () {
var val = '10.1234/abcdef';
var str = `DOI: ${val}`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, 1);
assert.equal(fields.get('DOI'), val);
assert.strictEqual(extra, '');
});
it("should extract a field for a given item", function () {
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
var val = '10.1234/abcdef';
var str = `DOI: ${val}`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str, item);
assert.equal(fields.size, 1);
assert.equal(fields.get('DOI'), val);
assert.strictEqual(extra, '');
});
it("should extract a CSL field", function () {
var val = '10.1234/abcdef';
var str = `container-title: ${val}`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, Zotero.Schema.CSL_TEXT_MAPPINGS['container-title'].length);
assert.equal(fields.get('publicationTitle'), val);
assert.strictEqual(extra, '');
});
it("should extract a CSL field for a given item type", function () {
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
var val = '10.1234/abcdef';
var str = `container-title: ${val}`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str, item);
assert.equal(fields.size, 1);
assert.equal(fields.get('publicationTitle'), val);
assert.strictEqual(extra, '');
});
it("should extract a field with different case", function () {
var val = '10.1234/abcdef';
var str = `doi: ${val}`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, 1);
assert.equal(fields.get('DOI'), val);
assert.strictEqual(extra, '');
});
it("should extract a field with other fields, text, and whitespace", function () {
var date = '2020-04-01';
var doi = '10.1234/abcdef';
var str = `Line 1\nDate: ${date}\nFoo: Bar\nDOI: ${doi}\n\nLine 2`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, 2);
assert.equal(fields.get('date'), date);
assert.equal(fields.get('DOI'), doi);
assert.equal(extra, 'Line 1\nFoo: Bar\n\nLine 2');
});
it("should extract the first instance of a field", function () {
var date1 = '2020-04-01';
var date2 = '2020-04-02';
var str = `Date: ${date1}\nDate: ${date2}`;
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, 1);
assert.equal(fields.get('date'), date1);
assert.equal(extra, "Date: " + date2);
});
it("shouldn't extract a field from a line that begins with a whitespace", function () {
var str = '\n number-of-pages: 11';
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, 0);
});
it("shouldn't extract a field that already exists on the item", function () {
var item = createUnsavedDataObject('item', { itemType: 'book' });
item.setField('numPages', 10);
var str = 'number-of-pages: 11';
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str, item);
assert.equal(fields.size, 0);
});
it("should extract an author and add it to existing creators", function () {
var item = createUnsavedDataObject('item', { itemType: 'book' });
item.setCreator(0, { creatorType: 'author', name: 'Foo' });
var str = 'author: Bar';
var { fields, creators, extra } = Zotero.Utilities.Internal.extractExtraFields(str, item);
assert.equal(fields.size, 0);
assert.lengthOf(creators, 1);
assert.equal(creators[0].creatorType, 'author');
assert.equal(creators[0].name, 'Bar');
});
it("should extract a CSL date field", function () {
var str = 'issued: 2000';
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.equal(fields.size, 1);
assert.equal(fields.get('date'), 2000);
assert.strictEqual(extra, '');
});
it("should extract a CSL name", function () {
var str = 'container-author: Last || First';
var { creators, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
assert.lengthOf(creators, 1);
assert.propertyVal(creators[0], 'creatorType', 'bookAuthor');
assert.propertyVal(creators[0], 'firstName', 'First');
assert.propertyVal(creators[0], 'lastName', 'Last');
assert.strictEqual(extra, '');
});
it("should extract a CSL name that's valid for a given item type", function () {
var item = createUnsavedDataObject('item', { itemType: 'bookSection' });
var str = 'container-author: Last || First';
var { creators, extra } = Zotero.Utilities.Internal.extractExtraFields(str, item);
assert.lengthOf(creators, 1);
assert.propertyVal(creators[0], 'creatorType', 'bookAuthor');
assert.propertyVal(creators[0], 'firstName', 'First');
assert.propertyVal(creators[0], 'lastName', 'Last');
assert.strictEqual(extra, '');
});
it("shouldn't extract a CSL name that's not valid for a given item type", function () {
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
var str = 'container-author: Last || First';
var { creators, extra } = Zotero.Utilities.Internal.extractExtraFields(str, item);
assert.lengthOf(creators, 0);
assert.strictEqual(extra, str);
});
it("should extract the citeproc-js cheater syntax", function () {
var issued = '{:number-of-pages:11}\n{:issued:2014}';
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(issued);
assert.equal(fields.size, 2);
assert.equal(fields.get('numPages'), 11);
assert.equal(fields.get('date'), 2014);
assert.strictEqual(extra, '');
});
it("should ignore both Event Place and Publisher Place (temporary)", function () {
var str = "Event Place: Foo\nPublisher Place: Bar";
var { fields, extra } = Zotero.Utilities.Internal.extractExtraFields(str);
Zotero.debug([...fields.entries()]);
assert.equal(fields.size, 0);
assert.equal(extra, "Event Place: Foo\nPublisher Place: Bar");
});
});
describe("#combineExtraFields", function () {
var originalDate = "1887";
var publicationPlace = "New York";
var doi = '10.1234/123456789';
var fieldMap = new Map();
fieldMap.set('originalDate', originalDate);
fieldMap.set('publicationPlace', publicationPlace);
fieldMap.set('DOI', doi);
var fieldStr = `DOI: ${doi}\nOriginal Date: ${originalDate}\nPublication Place: ${publicationPlace}`;
it("should create 'field: value' pairs from field map", function () {
var extra = "";
var newExtra = ZUI.combineExtraFields(extra, fieldMap);
assert.equal(newExtra, fieldStr);
});
it("should add fields above existing Extra content", function () {
var extra = "This is a note.";
var newExtra = ZUI.combineExtraFields(extra, fieldMap);
assert.equal(newExtra, fieldStr + '\n' + extra);
});
it("should replace existing fields", function () {
var extra = "This is a note.\nOriginal Date: 1886\nFoo: Bar";
var newExtra = ZUI.combineExtraFields(extra, fieldMap);
assert.equal(
newExtra,
fieldStr.split(/\n/).filter(x => !x.startsWith('Original Date')).join("\n")
+ "\nThis is a note.\nOriginal Date: 1887\nFoo: Bar"
);
});
});
describe("#extractIdentifiers()", function () {
it("should extract ISBN-10", async function () {
var id = "0838985890";
var identifiers = ZUI.extractIdentifiers(id);
assert.lengthOf(identifiers, 1);
assert.lengthOf(Object.keys(identifiers[0]), 1);
assert.propertyVal(identifiers[0], "ISBN", id);
});
it("should extract ISBN-13", async function () {
var identifiers = ZUI.extractIdentifiers("978-0838985892");
assert.lengthOf(identifiers, 1);
assert.lengthOf(Object.keys(identifiers[0]), 1);
assert.propertyVal(identifiers[0], "ISBN", "9780838985892");
});
it("should extract multiple ISBN-13s", async function () {
var identifiers = ZUI.extractIdentifiers("978-0838985892 9781479347711 ");
assert.lengthOf(identifiers, 2);
assert.lengthOf(Object.keys(identifiers[0]), 1);
assert.lengthOf(Object.keys(identifiers[1]), 1);
assert.propertyVal(identifiers[0], "ISBN", "9780838985892");
assert.propertyVal(identifiers[1], "ISBN", "9781479347711");
});
it("should extract DOI", async function () {
var id = "10.4103/0976-500X.85940";
var identifiers = ZUI.extractIdentifiers(id);
assert.lengthOf(identifiers, 1);
assert.lengthOf(Object.keys(identifiers[0]), 1);
assert.propertyVal(identifiers[0], "DOI", id);
});
it("should extract PMID", async function () {
var identifiers = ZUI.extractIdentifiers("1 PMID:24297125,222 3-4 1234567890, 123456789");
assert.lengthOf(identifiers, 4);
assert.lengthOf(Object.keys(identifiers[0]), 1);
assert.lengthOf(Object.keys(identifiers[1]), 1);
assert.lengthOf(Object.keys(identifiers[2]), 1);
assert.lengthOf(Object.keys(identifiers[3]), 1);
assert.propertyVal(identifiers[0], "PMID", "1");
assert.propertyVal(identifiers[1], "PMID", "24297125");
assert.propertyVal(identifiers[2], "PMID", "222");
assert.propertyVal(identifiers[3], "PMID", "123456789");
});
it("should extract multiple old and new style arXivs", async function () {
var identifiers = ZUI.extractIdentifiers("0706.0044 arXiv:0706.00441v1,12345678,hep-ex/9809001v1, math.GT/0309135.");
assert.lengthOf(identifiers, 4);
assert.lengthOf(Object.keys(identifiers[0]), 1);
assert.lengthOf(Object.keys(identifiers[1]), 1);
assert.lengthOf(Object.keys(identifiers[2]), 1);
assert.lengthOf(Object.keys(identifiers[3]), 1);
assert.propertyVal(identifiers[0], "arXiv", "0706.0044");
assert.propertyVal(identifiers[1], "arXiv", "0706.00441");
assert.propertyVal(identifiers[2], "arXiv", "hep-ex/9809001");
assert.propertyVal(identifiers[3], "arXiv", "math.GT/0309135");
});
});
describe("#resolveLocale()", function () {
var availableLocales;
before(function () {
availableLocales = Services.locale.getAvailableLocales();
});
function resolve(locale) {
return Zotero.Utilities.Internal.resolveLocale(locale, availableLocales);
}
it("should return en-US for en-US", function () {
assert.equal(resolve('en-US'), 'en-US');
});
it("should return en-US for en", function () {
assert.equal(resolve('en'), 'en-US');
});
it("should return fr-FR for fr-FR", function () {
assert.equal(resolve('fr-FR'), 'fr-FR');
});
it("should return fr-FR for fr", function () {
assert.equal(resolve('fr'), 'fr-FR');
});
it("should return ar for ar", function () {
assert.equal(resolve('ar'), 'ar');
});
it("should return pt-PT for pt", function () {
assert.equal(resolve('pt'), 'pt-PT');
});
it("should return zh-CN for zh-CN", function () {
assert.equal(resolve('zh-CN'), 'zh-CN');
});
it("should return zh-TW for zh-TW", function () {
assert.equal(resolve('zh-TW'), 'zh-TW');
});
it("should return zh-CN for zh", function () {
assert.equal(resolve('zh'), 'zh-CN');
});
});
describe("#camelToTitleCase()", function () {
it("should convert 'fooBar' to 'Foo Bar'", function () {
assert.equal(Zotero.Utilities.Internal.camelToTitleCase('fooBar'), 'Foo Bar');
});
it("should keep all-caps strings intact", function () {
assert.equal(Zotero.Utilities.Internal.camelToTitleCase('DOI'), 'DOI');
});
it("should convert 'fooBAR' to 'Foo BAR'", function () {
assert.equal(Zotero.Utilities.Internal.camelToTitleCase('fooBAR'), 'Foo BAR');
});
});
describe("#getNextName()", function () {
it("should get the next available numbered name", function () {
var existing = ['Name', 'Name 1', 'Name 3'];
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name 2');
});
it("should return 'Name 1' if no numbered names", function () {
var existing = ['Name'];
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name 1');
});
it("should return 'Name' if only numbered names", function () {
var existing = ['Name 1', 'Name 3'];
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name');
});
it("should trim given name if trim=true", function () {
var existing = ['Name', 'Name 1', 'Name 2', 'Name 3'];
assert.equal(Zotero.Utilities.Internal.getNextName('Name 2', existing, true), 'Name 4');
});
});
})