diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 836d4348ff..9b6a5dfcdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,3 +73,18 @@ jobs: - name: Run tests run: xvfb-run test/runtests.sh -x firefox-x86_64/firefox -f + + - name: Cache utilities Node modules + id: utilities-node-cache + uses: actions/cache@v2 + with: + path: chrome/content/zotero/xpcom/utilities/node_modules + key: utilities-node-modules-${{ hashFiles('chrome/content/zotero/xpcom/utilities/package-lock.json') }} + + - name: Install utilities Node modules + if: steps.utilities-node-cache.outputs.cache-hit != 'true' + run: npm install --prefix chrome/content/zotero/xpcom/utilities + + - name: Run utilities tests + run: | + npm test --prefix chrome/content/zotero/xpcom/utilities -- -j resource/schema/global/schema.json diff --git a/chrome/content/zotero/xpcom/utilities b/chrome/content/zotero/xpcom/utilities index 90f6c8aeda..63bd5bb4c6 160000 --- a/chrome/content/zotero/xpcom/utilities +++ b/chrome/content/zotero/xpcom/utilities @@ -1 +1 @@ -Subproject commit 90f6c8aeda15e1433ac24903440ab470bcfbed4f +Subproject commit 63bd5bb4c60221071d4d4cf8dcf59993a1917973 diff --git a/scripts/config.js b/scripts/config.js index 41018bdf99..508850c649 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -99,6 +99,8 @@ const ignoreMask = [ 'resource/schema/global/scripts/*', 'chrome/content/zotero/xpcom/translate/example/**/*', 'chrome/content/zotero/xpcom/translate/README.md', + 'chrome/content/zotero/xpcom/utilities/node_modules/**/*', + 'chrome/content/zotero/xpcom/utilities/test/**/*', ]; const jsFiles = [ diff --git a/test/tests/data/citeProcJSExport.js b/test/tests/data/citeProcJSExport.js deleted file mode 100644 index 080a4f2901..0000000000 --- a/test/tests/data/citeProcJSExport.js +++ /dev/null @@ -1,1769 +0,0 @@ -{ - "artwork": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "artistLast", - "given": "artistFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "dimensions": "Artwork size", - "id": 37, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "graphic" - }, - "audioRecording": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "performerLast", - "given": "performerFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-title": "Series title", - "composer": [ - { - "family": "composerLast", - "given": "composerFirst" - } - ], - "dimensions": "1:22:33", - "event-place": "Place", - "id": 38, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "number-of-volumes": "7", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "song", - "volume": "6" - }, - "bill": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "sponsorLast", - "given": "sponsorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "authority": "Legislative body", - "chapter-number": "Session", - "container-title": "Code", - "id": 39, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number": "3", - "page": "1-10", - "references": "History", - "section": "Section", - "title-short": "Short title", - "title": "Title", - "type": "bill", - "volume": "6" - }, - "blogPost": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "container-title": "Publication title", - "genre": "Type", - "id": 40, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "title-short": "Short title", - "title": "Title", - "type": "post-weblog" - }, - "book": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-number": "9", - "collection-title": "Series", - "edition": "8", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "event-place": "Place", - "id": 41, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number-of-pages": "4", - "number-of-volumes": "7", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "book", - "volume": "6" - }, - "bookSection": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-number": "9", - "collection-title": "Series", - "container-author": [ - { - "family": "bookAuthorLast", - "given": "bookAuthorFirst" - } - ], - "container-title": "Publication title", - "edition": "8", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "event-place": "Place", - "id": 42, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number-of-volumes": "7", - "page": "1-10", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "chapter", - "volume": "6" - }, - "case": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "authority": "Court", - "container-title": "Reporter", - "id": 43, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number": "3", - "page": "1-10", - "references": "History", - "title-short": "Short title", - "title": "Title", - "type": "legal_case", - "volume": "6" - }, - "computerProgram": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "programmerLast", - "given": "programmerFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-title": "Series title", - "event-place": "Place", - "genre": "Programming language", - "id": 44, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "medium": "System", - "note": "Extra", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "book", - "version": "Version" - }, - "conferencePaper": { - "DOI": "10.1234/example.doi", - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-title": "Series", - "container-title": "Publication title", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "event": "Conference name", - "event-place": "Place", - "id": 45, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "page": "1-10", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "paper-conference", - "volume": "6" - }, - "dictionaryEntry": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-number": "9", - "collection-title": "Series", - "container-title": "Publication title", - "edition": "8", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "event-place": "Place", - "id": 46, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number-of-volumes": "7", - "page": "1-10", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "entry-dictionary", - "volume": "6" - }, - "document": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "id": 47, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "publisher": "Publisher", - "reviewed-author": [ - { - "family": "reviewedAuthorLast", - "given": "reviewedAuthorFirst" - } - ], - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "article" - }, - "email": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "id": 48, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "recipient": [ - { - "family": "recipientLast", - "given": "recipientFirst" - } - ], - "title-short": "Short title", - "title": "Title", - "type": "personal_communication" - }, - "encyclopediaArticle": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-number": "9", - "collection-title": "Series", - "container-title": "Publication title", - "edition": "8", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "event-place": "Place", - "id": 49, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number-of-volumes": "7", - "page": "1-10", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "entry-encyclopedia", - "volume": "6" - }, - "film": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "directorLast", - "given": "directorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "dimensions": "1:22:33", - "genre": "Type", - "id": 50, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "publisher": "Publisher", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "motion_picture" - }, - "forumPost": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "container-title": "Publication title", - "genre": "Type", - "id": 51, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "title-short": "Short title", - "title": "Title", - "type": "post" - }, - "hearing": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "contributorLast", - "given": "contributorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "authority": "Legislative body", - "chapter-number": "Session", - "event-place": "Place", - "id": 52, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number": "3", - "number-of-volumes": "7", - "page": "1-10", - "publisher": "Publisher", - "publisher-place": "Place", - "references": "History", - "section": "Committee", - "title-short": "Short title", - "title": "Title", - "type": "bill" - }, - "instantMessage": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "id": 53, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "recipient": [ - { - "family": "recipientLast", - "given": "recipientFirst" - } - ], - "title-short": "Short title", - "title": "Title", - "type": "personal_communication" - }, - "interview": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "intervieweeLast", - "given": "intervieweeFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "id": 54, - "interviewer": [ - { - "family": "interviewerLast", - "given": "interviewerFirst" - } - ], - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "interview" - }, - "journalArticle": { - "DOI": "10.1234/example.doi", - "ISSN": "1234-5679", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-title": "Series title", - "container-title": "Publication title", - "editor": [ - { - "family": "editorLast", - "given": "editorFirst" - } - ], - "id": 55, - "issue": "5", - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "journalAbbreviation": "Journal abbreviation", - "language": "en-US", - "note": "Extra", - "page": "1-10", - "reviewed-author": [ - { - "family": "reviewedAuthorLast", - "given": "reviewedAuthorFirst" - } - ], - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "article-journal", - "volume": "6" - }, - "letter": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "genre": "Type", - "id": 56, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "recipient": [ - { - "family": "recipientLast", - "given": "recipientFirst" - } - ], - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "personal_communication" - }, - "magazineArticle": { - "ISSN": "1234-5679", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "container-title": "Publication title", - "id": 57, - "issue": "5", - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "page": "1-10", - "reviewed-author": [ - { - "family": "reviewedAuthorLast", - "given": "reviewedAuthorFirst" - } - ], - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "article-magazine", - "volume": "6" - }, - "manuscript": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "event-place": "Place", - "genre": "Type", - "id": 58, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number-of-pages": "4", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "manuscript" - }, - "map": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "cartographerLast", - "given": "cartographerFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-title": "Series title", - "edition": "8", - "event-place": "Place", - "genre": "Type", - "id": 59, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "publisher": "Publisher", - "publisher-place": "Place", - "scale": "Scale", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "map" - }, - "newspaperArticle": { - "ISSN": "1234-5679", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "container-title": "Publication title", - "edition": "8", - "event-place": "Place", - "id": 60, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "page": "1-10", - "publisher-place": "Place", - "reviewed-author": [ - { - "family": "reviewedAuthorLast", - "given": "reviewedAuthorFirst" - } - ], - "section": "Section", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "article-newspaper" - }, - "patent": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "inventorLast", - "given": "inventorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "authority": "Issuing authority", - "call-number": "Application number", - "event-place": "Place", - "id": 61, - "issue": "Priority numbers", - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number": "3", - "page": "1-10", - "publisher-place": "Place", - "references": "References", - "title-short": "Short title", - "status": "Legal status", - "submitted": { - "date-parts": [ - [ - "2000", - 1, - 2 - ] - ] - }, - "title": "Title", - "type": "patent" - }, - "podcast": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "podcasterLast", - "given": "podcasterFirst" - }, - { - "literal": "Institutional Author" - } - ], - "collection-title": "Series title", - "dimensions": "1:22:33", - "id": 62, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "number": "3", - "title-short": "Short title", - "title": "Title", - "type": "broadcast" - }, - "presentation": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "presenterLast", - "given": "presenterFirst" - }, - { - "literal": "Institutional Author" - } - ], - "event": "Meeting name", - "event-place": "Place", - "genre": "Type", - "id": 63, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "publisher-place": "Place", - "title-short": "Short title", - "title": "Title", - "type": "speech" - }, - "radioBroadcast": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "directorLast", - "given": "directorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "container-title": "Publication title", - "dimensions": "1:22:33", - "event-place": "Place", - "id": 64, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "number": "3", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "broadcast" - }, - "report": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-editor": [ - { - "family": "seriesEditorLast", - "given": "seriesEditorFirst" - } - ], - "collection-title": "Series title", - "event-place": "Place", - "genre": "Type", - "id": 65, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number": "3", - "page": "1-10", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "report" - }, - "statute": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "chapter-number": "Session", - "container-title": "Code", - "id": 66, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number": "3", - "page": "1-10", - "references": "History", - "section": "Section", - "title-short": "Short title", - "title": "Title", - "type": "legislation", - "volume": "Code number" - }, - "thesis": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "event-place": "Place", - "genre": "Type", - "id": 67, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "number-of-pages": "4", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "thesis" - }, - "tvBroadcast": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "directorLast", - "given": "directorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "container-title": "Publication title", - "dimensions": "1:22:33", - "event-place": "Place", - "id": 68, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "number": "3", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "broadcast" - }, - "videoRecording": { - "ISBN": "978-1-234-56789-7", - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "archive": "Archive", - "archive_location": "Archive location", - "author": [ - { - "family": "directorLast", - "given": "directorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "call-number": "Call number", - "collection-title": "Series title", - "dimensions": "1:22:33", - "event-place": "Place", - "id": 69, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "medium": "Medium", - "note": "Extra", - "number-of-volumes": "7", - "publisher": "Publisher", - "publisher-place": "Place", - "title-short": "Short title", - "source": "Library catalog", - "title": "Title", - "type": "motion_picture", - "volume": "6" - }, - "webpage": { - "URL": "http://www.example.com", - "abstract": "Abstract note", - "accessed": { - "date-parts": [ - [ - "1997", - 6, - 13 - ] - ] - }, - "author": [ - { - "family": "authorLast", - "given": "authorFirst" - }, - { - "literal": "Institutional Author" - } - ], - "container-title": "Publication title", - "genre": "Type", - "id": 70, - "issued": { - "date-parts": [ - [ - "1999", - 12, - 31 - ] - ] - }, - "language": "en-US", - "note": "Extra", - "title-short": "Short title", - "title": "Title", - "translator": [ - { - "family": "translatorLast", - "given": "translatorFirst" - } - ], - "type": "webpage" - } -} diff --git a/test/tests/utilitiesSubmoduleTest.js b/test/tests/utilitiesSubmoduleTest.js new file mode 100644 index 0000000000..95e2b029ad --- /dev/null +++ b/test/tests/utilitiesSubmoduleTest.js @@ -0,0 +1,33 @@ +describe("Zotero.Utilities.Item", function () { + describe("itemToCSLJSON()", async function () { + it("should accept Zotero.Item and Zotero export item format", async function () { + let data = await populateDBWithSampleData(loadSampleData('journalArticle')); + let item = await Zotero.Items.getAsync(data.journalArticle.id); + + let fromZoteroItem; + try { + fromZoteroItem = Zotero.Utilities.Item.itemToCSLJSON(item); + } + catch (e) { + assert.fail(e, null, 'accepts Zotero Item'); + } + assert.isObject(fromZoteroItem, 'converts Zotero Item to object'); + assert.isNotNull(fromZoteroItem, 'converts Zotero Item to non-null object'); + + + let fromExportItem; + try { + fromExportItem = Zotero.Utilities.Item.itemToCSLJSON( + Zotero.Utilities.Internal.itemToExportFormat(item) + ); + } + catch (e) { + assert.fail(e, null, 'accepts Zotero export item'); + } + assert.isObject(fromExportItem, 'converts Zotero export item to object'); + assert.isNotNull(fromExportItem, 'converts Zotero export item to non-null object'); + + assert.deepEqual(fromZoteroItem, fromExportItem, 'conversion from Zotero Item and from export item are the same'); + }); + }); +}); diff --git a/test/tests/utilitiesTest.js b/test/tests/utilitiesTest.js deleted file mode 100644 index 75b93fc711..0000000000 --- a/test/tests/utilitiesTest.js +++ /dev/null @@ -1,283 +0,0 @@ -describe("Zotero.Utilities", function() { - describe("cleanAuthor", function() { - it('should parse author names', function() { - for(let useComma of [false, true]) { - for(let first_expected of [["First", "First"], - ["First Middle", "First Middle"], - ["F. R. S.", "F. R. S."], - ["F.R.S.", "F. R. S."], - ["F R S", "F. R. S."], - ["FRS", "F. R. S."]]) { - let [first, expected] = first_expected; - let str = useComma ? "Last, "+first : first+" Last"; - let author = Zotero.Utilities.cleanAuthor(str, "author", useComma); - assert.equal(author.firstName, expected); - assert.equal(author.lastName, "Last"); - } - } - }); - - it('should not parse words starting with symbols as last name', function() { - let author = Zotero.Utilities.cleanAuthor('First Middle Last [CountryName]', false); - assert.equal(author.firstName, 'First Middle'); - // Brackets at the beginning and end of a string get removed for strings - // such as [First Last] -> Last, First. - // The current output is not ideal, but better than "[CountryName, First Middle Last" - assert.equal(author.lastName, 'Last [CountryName'); - }); - - it('should parse names starting with unicode characters correctly', function() { - let author = Zotero.Utilities.cleanAuthor('Ąžuolas Žolynas', false); - assert.equal(author.firstName, 'Ąžuolas'); - assert.equal(author.lastName, 'Žolynas'); - }) - }); - - - describe("#isHTTPURL()", function () { - it("should return true for HTTP URL", function () { - assert.isTrue(Zotero.Utilities.isHTTPURL('http://example.com')); - }); - - it("should return true for HTTPS URL", function () { - assert.isTrue(Zotero.Utilities.isHTTPURL('https://example.com')); - }); - - it("should return false for plausible HTTP URL if allowNoScheme not provided", function () { - assert.isFalse(Zotero.Utilities.isHTTPURL('example.com')); - }); - - it("should return false for plausible HTTP URL if allowNoScheme is true", function () { - assert.isTrue(Zotero.Utilities.isHTTPURL('example.com', true)); - }); - - it("should return false for file URL", function () { - assert.isFalse(Zotero.Utilities.isHTTPURL('file:///c:/path/to/file.txt')); - }); - - it("should return false for mailto URLs in allowNoScheme mode", function () { - assert.isFalse(Zotero.Utilities.isHTTPURL('mailto:foo@example.com', true)); - }); - - it("should return false for zotero: URL", function () { - assert.isFalse(Zotero.Utilities.isHTTPURL('zotero://select/library/items/AAAAAAAA')); - }); - }); - - - describe("#cleanDOI()", function () { - var cleanDOI = Zotero.Utilities.cleanDOI; - var doi = '10.1088/1748-9326/11/4/048002'; - var shortDOI = '10/aabbe'; - - it("should parse a DOI", function () { - assert.equal(cleanDOI(`${doi}`), doi); - }); - - it("should parse a short DOI", function () { - assert.equal(cleanDOI(`${shortDOI}`), shortDOI); - }); - - it("should parse a DOI at the end of a sentence", function () { - assert.equal(cleanDOI(`Foo bar ${doi}. Foo bar`), doi); - }); - - // FIXME - it.skip("should parse a DOI in parentheses", function () { - assert.equal(cleanDOI(`Foo bar (${doi}) foo bar`), doi); - }); - - // FIXME - it.skip("should parse a DOI in brackets", function () { - assert.equal(cleanDOI(`Foo bar [${doi}] foo bar`), doi); - }); - }); - - - describe("#cleanISBN()", function() { - let cleanISBN = Zotero.Utilities.cleanISBN; - it("should return false for non-ISBN string", function() { - assert.isFalse(cleanISBN(''), 'returned false for empty string'); - assert.isFalse(cleanISBN('Random String 123'), 'returned false for non-ISBN string'); - assert.isFalse(cleanISBN('1234X67890'), 'returned false for ISBN10-looking string with X in the middle'); - assert.isFalse(cleanISBN('987123456789X'), 'returned false for ISBN13-looking string with X as check-digit'); - }); - it("should return false for invalid ISBN string", function() { - assert.isFalse(cleanISBN('1234567890'), 'returned false for invalid ISBN10'); - assert.isFalse(cleanISBN('9871234567890'), 'returned false for invalid ISBN13'); - }); - it("should return valid ISBN string given clean, valid ISBN string", function() { - assert.equal(cleanISBN('123456789X'), '123456789X', 'passed through valid ISBN10'); - assert.equal(cleanISBN('123456789x'), '123456789X', 'passed through valid ISBN10 with lower case input'); - assert.equal(cleanISBN('9781234567897'), '9781234567897', 'passed through valid ISBN13'); - assert.equal(cleanISBN('9791843123391'), '9791843123391', 'passed through valid ISBN13 in 979 range'); - }); - it("should strip off internal characters in ISBN string", function() { - let ignoredChars = '\x2D\xAD\u2010\u2011\u2012\u2013\u2014\u2015\u2043\u2212' // Dashes - + ' \xA0\r\n\t\x0B\x0C\u1680\u2000\u2001\u2002\u2003\u2004\u2005' // Spaces - + '\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF'; - for (let i=0; iISBN:978-1 234\xA056789 - 7(print)\nISBN-10:123\x2D456789X (print)'), '9781234567897'); - }); - it("should not validate check digit when dontValidate is set", function() { - assert.equal(cleanISBN('9781234567890', true), '9781234567890', 'plain ISBN13 with wrong check digit'); - assert.equal(cleanISBN('1234567890', true), '1234567890', 'plain ISBN10 with wrong check digit'); - assert.equal(cleanISBN('1234567890 9781234567897', true), '1234567890', 'returned first ISBN10 (invalid) in the list with valid and invalid ISBNs'); - assert.equal(cleanISBN('9781234567890 123456789X', true), '9781234567890', 'returned first ISBN13 (invalid) in the list with valid and invalid ISBNs'); - }); - it("should not pass non-ISBN strings if dontValidate is set", function() { - assert.isFalse(cleanISBN('', true), 'returned false for empty string'); - assert.isFalse(cleanISBN('Random String 123', true), 'returned false for non-ISBN string'); - assert.isFalse(cleanISBN('1234X67890', true), 'returned false for ISBN10-looking string with X in the middle'); - assert.isFalse(cleanISBN('123456789Y', true), 'returned false for ISBN10-looking string with Y as check digit'); - assert.isFalse(cleanISBN('987123456789X', true), 'returned false for ISBN13-looking string with X as check-digit'); - assert.isFalse(cleanISBN('1239781234567897', true), 'did not ignore number prefix'); - assert.isFalse(cleanISBN('9781234567897123', true), 'did not ignore number suffix'); - assert.isFalse(cleanISBN('1239781234567897123', true), 'did not ignore surrounding numbers'); - }); - }); - describe("toISBN13", function() { - let toISBN13 = Zotero.Utilities.toISBN13; - it("should throw on invalid ISBN", function() { - let errorMsg = 'ISBN not found in "', - invalidStrings = ['', 'random string', '1234567890123']; - for (let i=0; iISSN:1234\xA0-\t5679(print)\neISSN (electronic):0028-0836'), '1234-5679'); - }); - }); - describe("#ellipsize()", function () { - describe("with wordBoundary", function () { - it("should truncate at word boundary", function* () { - assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 3, true), "abc…"); - }); - - it("should trim whitespace after word boundary", function* () { - assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 4, true), "abc…"); - }); - - it("should trim characters after word boundary", function () { - assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 5, true), "abc…"); - }); - - it("should truncate in the middle of a word", function () { - assert.equal(Zotero.Utilities.ellipsize("abcdefghi", 6, true), "abcdef…"); - }); - - it("should truncate at word boundary with previous space within radius", function () { - assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 7, true), "abc def…"); - }); - - it("should return string as is if shorter than length", function () { - assert.equal(Zotero.Utilities.ellipsize("abcdefg", 8, true), "abcdefg"); - }); - - it("should return string as is if equal to length", function () { - assert.equal(Zotero.Utilities.ellipsize("abcdefgh", 8, true), "abcdefgh"); - }); - }); - }); -}); diff --git a/test/tests/utilities_itemTest.js b/test/tests/utilities_itemTest.js deleted file mode 100644 index b193a5fd27..0000000000 --- a/test/tests/utilities_itemTest.js +++ /dev/null @@ -1,343 +0,0 @@ -describe("Zotero.Utilities.Item", function() { - describe("itemFromCSLJSON", function () { - it("should stably perform itemToCSLJSON -> itemFromCSLJSON -> itemToCSLJSON", function* () { - this.timeout(10000); - let data = loadSampleData('citeProcJSExport'); - - for (let i in data) { - let json = data[i]; - - // TEMP: https://github.com/zotero/zotero/issues/1667 - if (i == 'podcast') { - delete json['collection-title']; - } - - let item = new Zotero.Item(); - Zotero.Utilities.itemFromCSLJSON(item, json); - yield item.saveTx(); - - let newJSON = Zotero.Utilities.itemToCSLJSON(item); - - delete newJSON.id; - delete json.id; - - assert.deepEqual(newJSON, json, i + ' export -> import -> export is stable'); - } - - }); - it("should recognize the legacy shortTitle key", function* () { - this.timeout(20000); - - let data = loadSampleData('citeProcJSExport'); - - var json = data.artwork; - var canonicalKeys = Object.keys(json); - json.shortTitle = json["title-short"]; - delete json["title-short"]; - - let item = new Zotero.Item(); - Zotero.Utilities.itemFromCSLJSON(item, json); - yield item.saveTx(); - - let newJSON = Zotero.Utilities.itemToCSLJSON(item); - assert.hasAllKeys(newJSON, canonicalKeys); - }); - it("should import exported standalone note", function* () { - let note = new Zotero.Item('note'); - note.setNote('Some note longer than 50 characters, which will become the title.'); - yield note.saveTx(); - - let jsonNote = Zotero.Utilities.itemToCSLJSON(note); - - let item = new Zotero.Item(); - Zotero.Utilities.itemFromCSLJSON(item, jsonNote); - - assert.equal(item.getField('title'), jsonNote.title, 'title imported correctly'); - }); - it("should import exported standalone attachment", function* () { - let attachment = yield importFileAttachment("empty.pdf"); - attachment.setField('title', 'Empty'); - attachment.setField('accessDate', '2001-02-03 12:13:14'); - attachment.setField('url', 'http://example.com'); - attachment.setNote('Note'); - yield attachment.saveTx(); - - let jsonAttachment = Zotero.Utilities.itemToCSLJSON(attachment); - - let item = new Zotero.Item(); - Zotero.Utilities.itemFromCSLJSON(item, jsonAttachment); - - assert.equal(item.getField('title'), jsonAttachment.title, 'title imported correctly'); - }); - // For Zotero.Item created in translation sandbox in connectors - it("should not depend on Zotero.Item existing", function* () { - let item = new Zotero.Item; - var Item = Zotero.Item; - delete Zotero.Item; - assert.throws(() => "" instanceof Zotero.Item); - - let data = loadSampleData('citeProcJSExport'); - assert.doesNotThrow(Zotero.Utilities.itemFromCSLJSON.bind(Zotero.Utilities, item, Object.values(data)[0])); - - Zotero.Item = Item; - assert.doesNotThrow(() => "" instanceof Zotero.Item); - }) - }); - - describe("itemToCSLJSON", function() { - it("should accept Zotero.Item and Zotero export item format", Zotero.Promise.coroutine(function* () { - let data = yield populateDBWithSampleData(loadSampleData('journalArticle')); - let item = yield Zotero.Items.getAsync(data.journalArticle.id); - - let fromZoteroItem; - try { - fromZoteroItem = Zotero.Utilities.itemToCSLJSON(item); - } catch(e) { - assert.fail(e, null, 'accepts Zotero Item'); - } - assert.isObject(fromZoteroItem, 'converts Zotero Item to object'); - assert.isNotNull(fromZoteroItem, 'converts Zotero Item to non-null object'); - - - let fromExportItem; - try { - fromExportItem = Zotero.Utilities.itemToCSLJSON( - Zotero.Utilities.Internal.itemToExportFormat(item) - ); - } catch(e) { - assert.fail(e, null, 'accepts Zotero export item'); - } - assert.isObject(fromExportItem, 'converts Zotero export item to object'); - assert.isNotNull(fromExportItem, 'converts Zotero export item to non-null object'); - - assert.deepEqual(fromZoteroItem, fromExportItem, 'conversion from Zotero Item and from export item are the same'); - })); - it("should convert standalone notes to expected format", Zotero.Promise.coroutine(function* () { - let note = new Zotero.Item('note'); - note.setNote('Some note longer than 50 characters, which will become the title.'); - yield note.saveTx(); - - let cslJSONNote = Zotero.Utilities.itemToCSLJSON(note); - assert.equal(cslJSONNote.type, 'document', 'note is exported as "document"'); - assert.equal(cslJSONNote.title, note.getNoteTitle(), 'note title is set to Zotero pseudo-title'); - })); - it("should convert standalone attachments to expected format", Zotero.Promise.coroutine(function* () { - let file = getTestDataDirectory(); - file.append("empty.pdf"); - - let attachment = yield Zotero.Attachments.importFromFile({"file":file}); - attachment.setField('title', 'Empty'); - attachment.setField('accessDate', '2001-02-03 12:13:14'); - attachment.setField('url', 'http://example.com'); - attachment.setNote('Note'); - - yield attachment.saveTx(); - - let cslJSONAttachment = Zotero.Utilities.itemToCSLJSON(attachment); - assert.equal(cslJSONAttachment.type, 'document', 'attachment is exported as "document"'); - assert.equal(cslJSONAttachment.title, 'Empty', 'attachment title is correct'); - assert.deepEqual(cslJSONAttachment.accessed, {"date-parts":[["2001",2,3]]}, 'attachment access date is mapped correctly'); - })); - it("should refuse to convert unexpected item types", Zotero.Promise.coroutine(function* () { - let data = yield populateDBWithSampleData(loadSampleData('journalArticle')); - let item = yield Zotero.Items.getAsync(data.journalArticle.id); - - let exportFormat = Zotero.Utilities.Internal.itemToExportFormat(item); - exportFormat.itemType = 'foo'; - - assert.throws(Zotero.Utilities.itemToCSLJSON.bind(Zotero.Utilities, exportFormat), /^Unexpected Zotero Item type ".*"$/, 'throws an error when trying to map invalid item types'); - })); - - it("should parse particles in creator names", function* () { - let creators = [ - { - // No particles - firstName: 'John', - lastName: 'Smith', - creatorType: 'author', - expect: { - given: 'John', - family: 'Smith' - } - }, - { - // dropping and non-dropping - firstName: 'Jean de', - lastName: 'la Fontaine', - creatorType: 'author', - expect: { - given: 'Jean', - "dropping-particle": 'de', - "non-dropping-particle": 'la', - family: 'Fontaine' - } - }, - { - // only non-dropping - firstName: 'Vincent', - lastName: 'van Gogh', - creatorType: 'author', - expect: { - given: 'Vincent', - "non-dropping-particle": 'van', - family: 'Gogh' - } - }, - { - // only dropping - firstName: 'Alexander von', - lastName: 'Humboldt', - creatorType: 'author', - expect: { - given: 'Alexander', - "dropping-particle": 'von', - family: 'Humboldt' - } - }, - { - // institutional author - lastName: 'Jean de la Fontaine', - creatorType: 'author', - fieldMode: 1, - expect: { - literal: 'Jean de la Fontaine' - } - }, - { - // protected last name - firstName: 'Jean de', - lastName: '"la Fontaine"', - creatorType: 'author', - expect: { - given: 'Jean de', - family: 'la Fontaine' - } - } - ]; - - let data = yield populateDBWithSampleData({ - item: { - itemType: 'journalArticle', - creators: creators - } - }); - - let item = Zotero.Items.get(data.item.id); - let cslCreators = Zotero.Utilities.itemToCSLJSON(item).author; - - assert.deepEqual(cslCreators[0], creators[0].expect, 'simple name is not parsed'); - assert.deepEqual(cslCreators[1], creators[1].expect, 'name with dropping and non-dropping particles is parsed'); - assert.deepEqual(cslCreators[2], creators[2].expect, 'name with only non-dropping particle is parsed'); - assert.deepEqual(cslCreators[3], creators[3].expect, 'name with only dropping particle is parsed'); - assert.deepEqual(cslCreators[4], creators[4].expect, 'institutional author is not parsed'); - assert.deepEqual(cslCreators[5], creators[5].expect, 'protected last name prevents parsing'); - }); - - it("should convert UTC access date to local time", async function () { - var offset = new Date().getTimezoneOffset(); - var item = new Zotero.Item('webpage'); - var localDate; - if (offset < 0) { - localDate = '2019-01-09 00:00:00'; - } - else if (offset > 0) { - localDate = '2019-01-09 23:59:59'; - } - // Can't test timezone offset if in UTC - else { - this.skip(); - return; - } - var utcDate = Zotero.Date.sqlToDate(localDate); - item.setField('accessDate', Zotero.Date.dateToSQL(utcDate, true)); - await item.saveTx(); - let accessed = Zotero.Utilities.itemToCSLJSON(item).accessed; - - assert.equal(accessed['date-parts'][0][0], 2019); - assert.equal(accessed['date-parts'][0][1], 1); - assert.equal(accessed['date-parts'][0][2], 9); - }); - }); - - - describe("#noteToTitle()", function () { - it("should stop after first block element with content", async function () { - var str = "

Foo

Bar

"; - var title = Zotero.Utilities.Item.noteToTitle(str, { stopAtLineBreak: true }); - assert.equal(title, 'Foo'); - }); - - it("should skip first line if no content", async function () { - var str = "
\n

Foo

\n
\n

Bar

"; - var title = Zotero.Utilities.Item.noteToTitle(str); - assert.equal(title, 'Foo'); - }); - - it("should stop at
when options.stopAtLineBreak is true", async function () { - var str = "

Annotations
(2/18/2022, 3:49:43 AM)

Foo

"; - var title = Zotero.Utilities.Item.noteToTitle(str, { stopAtLineBreak: true }); - assert.equal(title, 'Annotations'); - }); - }); - - - describe("#compareCallNumbers()", function () { - function checkSort(numbersInOrder) { - let numbersResorted = [...numbersInOrder] - .sort(() => Math.random() - 0.5) // First shuffle - .sort(Zotero.Utilities.Item.compareCallNumbers); // Then re-sort - assert.deepEqual(numbersResorted, numbersInOrder); - } - - it("should correctly order integer call numbers", function () { - let numbersInOrder = [ - '1', - '2', - '12', - '20', - '21', - '100', - '101', - ]; - checkSort(numbersInOrder); - }); - - it("should correctly order Dewey Decimal call numbers", function () { - let numbersInOrder = [ - '641.5/Cor', - '641.5/wol', - '641.55541/Ray', - '641.594/Mun', - '641.5945/Foo', - '641.596/Mon', - '642.000/ABC', - ]; - checkSort(numbersInOrder); - }); - - it("should correctly order LC call numbers", function () { - let numbersInOrder = [ - 'PJ403.B64 C666', - 'PJ3930.S49 A53 2015', - 'PJ4519 .B9798 A58 1999', - 'PJ4519 .B99 A65 1976', - ]; - checkSort(numbersInOrder); - - numbersInOrder = [ - 'PJ6611.B35 2014', - 'PJ6611 .Z36 2001', - ]; - checkSort(numbersInOrder); - - numbersInOrder = [ - 'PC43 .O95 2016', - 'PC45 .P4 1976', - 'PC4074.7 .P46 2000', - 'PC4075', - 'PC4075 .P69 2001', - ]; - checkSort(numbersInOrder); - }); - }); -});