2024-11-12 06:13:17 +01:00
/* global setHTTPResponse:false, sinon: false, Zotero_Import_Mendeley: false, HttpServer: false, createAnnotation: false */
2021-11-04 04:32:36 +01:00
describe ( 'Zotero_Import_Mendeley' , function ( ) {
2022-10-16 20:10:58 +02:00
var server , httpd , httpdURL , importers ;
2024-12-06 19:14:09 +01:00
const getImporter = ( { importNotes = false } = { } ) => {
2022-10-16 20:10:58 +02:00
const importer = new Zotero _Import _Mendeley ( ) ;
2024-11-12 06:13:17 +01:00
importer . mendeleyAuth = { kind : 'direct' , tokens : { accessToken : 'access_token' , refreshToken : 'refresh_token' } } ;
2024-12-06 19:14:09 +01:00
importer . skipNotebooks = ! importNotes ;
if ( importNotes ) {
importer . _refManagerToken = {
kind : 'referenceManager' ,
accessToken : 'refman_token' ,
username : 'username' ,
password : 'password'
} ;
}
2022-10-16 20:10:58 +02:00
importers . push ( importer ) ;
return importer ;
} ;
2021-11-04 04:32:36 +01:00
before ( async ( ) => {
Components . utils . import ( 'chrome://zotero/content/import/mendeley/mendeleyImport.js' ) ;
2021-11-09 17:16:28 +01:00
2024-12-06 19:14:09 +01:00
// A real HTTP server is used to deliver a Bitcoin PDF so that annotations can be processed during import.
2025-06-19 08:01:52 +03:00
var { HttpServer } = ChromeUtils . import ( "chrome://remote/content/server/HTTPD.jsm" ) ; ;
2021-11-09 17:16:28 +01:00
const port = 16213 ;
httpd = new HttpServer ( ) ;
httpdURL = ` http://127.0.0.1: ${ port } ` ;
httpd . start ( port ) ;
httpd . registerFile (
'/file1.pdf' ,
2024-12-06 19:14:09 +01:00
Zotero . File . pathToFile ( OS . Path . join ( getTestDataDirectory ( ) . path , 'recognizePDF_test_title.pdf' ) )
2021-11-09 17:16:28 +01:00
) ;
} ) ;
after ( async ( ) => {
await new Zotero . Promise ( resolve => httpd . stop ( resolve ) ) ;
2021-11-04 04:32:36 +01:00
} ) ;
beforeEach ( async ( ) => {
2022-10-16 20:10:58 +02:00
importers = [ ] ;
2021-11-04 04:32:36 +01:00
Zotero . HTTP . mock = sinon . FakeXMLHttpRequest ;
2022-10-16 20:10:58 +02:00
server = sinon . fakeServer . create ( {
unsafeHeadersEnabled : false
} ) ;
2021-11-04 04:32:36 +01:00
server . autoRespond = true ;
2022-10-16 20:10:58 +02:00
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
2021-11-04 04:32:36 +01:00
method : 'POST' ,
2022-10-16 20:10:58 +02:00
url : ` oauth/token ` ,
2021-11-04 04:32:36 +01:00
status : 200 ,
headers : { } ,
json : {
access _token : 'ACCESS_TOKEN' , // eslint-disable-line camelcase
token _type : 'bearer' , // eslint-disable-line camelcase
expires _in : 3600 , // eslint-disable-line camelcase
refresh _token : 'REFRESH_TOKEN' , // eslint-disable-line camelcase
msso : null ,
scope : 'all'
}
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` folders?limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/folders-simple.json' )
)
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` annotations?limit=200 ` ,
status : 200 ,
headers : { } ,
2021-11-09 17:16:28 +01:00
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/annotations.json' )
)
2021-11-04 04:32:36 +01:00
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-simple.json' )
)
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
2024-12-06 19:14:09 +01:00
url : ` profiles/v2/me ` ,
2021-11-04 04:32:36 +01:00
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/user.json' )
)
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` groups/v2?type=all&limit=500 ` ,
status : 200 ,
headers : { } ,
2021-11-10 14:59:37 +01:00
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/groups.json' )
)
2021-11-04 04:32:36 +01:00
} ) ;
2021-11-09 17:16:28 +01:00
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
2024-12-06 19:14:09 +01:00
url : ` files/19fb5e5b-1a39-4851-b513-d48441a670e1 ` ,
2021-11-09 17:16:28 +01:00
status : 200 , // ideally would be 303 but mock http doesn't like it
headers : {
Location : ` ${ httpdURL } /file1.pdf `
} ,
text : ''
} ) ;
2021-11-10 14:59:37 +01:00
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` annotations?group_id=ec66aee6-455c-300c-b601-ba4d6a34a95e&limit=200 ` ,
status : 200 ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/group-annotations.json' )
)
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` annotations?group_id=cc697d28-054c-37d2-afa3-74fa4cf8a727&limit=200 ` ,
status : 200 ,
json : [ ]
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` annotations?group_id=6a15e9d6-c7e6-3716-8834-7a67d6f5f91f&limit=200 ` ,
status : 200 ,
json : [ ]
} ) ;
2021-11-04 04:32:36 +01:00
} ) ;
2022-10-16 20:10:58 +02:00
afterEach ( async ( ) => {
await Promise . all (
importers
. map ( importer => ( [
Zotero . Items . erase ( Array . from ( new Set ( importer . newItems ) ) . map ( i => i . id ) ) ,
Zotero . Collections . erase ( Array . from ( new Set ( importer . newCollections ) ) . map ( c => c . id ) )
] ) )
. reduce ( ( prev , a ) => ( [ ... prev , ... a ] ) , [ ] ) // .flat() in >= FF62
) ;
2021-11-04 04:32:36 +01:00
Zotero . HTTP . mock = null ;
} ) ;
describe ( '#import' , ( ) => {
2021-11-10 14:59:37 +01:00
it ( "should import collections, items, attachments & annotations" , async ( ) => {
2022-10-16 20:10:58 +02:00
const importer = getImporter ( ) ;
2021-11-04 04:32:36 +01:00
await importer . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const journal = ( await Zotero . Relations
2022-10-16 20:10:58 +02:00
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , 'b5f57b1a-f083-486c-aec7-5d5edd366dd2' ) )
2021-11-04 04:32:36 +01:00
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const report = ( await Zotero . Relations
2022-10-16 20:10:58 +02:00
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '616ec6d1-8d23-4414-8b6e-7bb129677577' ) )
2021-11-04 04:32:36 +01:00
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
2021-11-09 17:16:28 +01:00
const withpdf = ( await Zotero . Relations
2022-10-16 20:10:58 +02:00
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '3630a4bf-d97e-46c4-8611-61ec50f840c6' ) )
2021-11-09 17:16:28 +01:00
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const pdf = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:fileHash' , 'cc22c6611277df346ff8dc7386ba3880b2bafa15' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
2023-03-09 22:13:19 +01:00
const withTags = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '4308d8ec-e8ea-43fb-9d38-4e6628f7c10a' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
2022-10-16 20:10:58 +02:00
assert . equal ( journal . getRelations ( ) [ 'mendeleyDB:remoteDocumentUUID' ] , '7fea3cb3-f97d-3f16-8fad-f59caaa71688' ) ;
2021-11-04 04:32:36 +01:00
assert . equal ( journal . getField ( 'title' ) , 'Foo Bar' ) ;
assert . equal ( journal . itemTypeID , Zotero . ItemTypes . getID ( 'journalArticle' ) ) ;
2022-10-16 20:10:58 +02:00
assert . equal ( report . getRelations ( ) [ 'mendeleyDB:remoteDocumentUUID' ] , '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef' ) ;
2021-11-04 04:32:36 +01:00
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . itemTypeID , Zotero . ItemTypes . getID ( 'report' ) ) ;
2022-10-16 20:10:58 +02:00
assert . equal ( withpdf . getRelations ( ) [ 'mendeleyDB:remoteDocumentUUID' ] , 'c54b0c6f-c4ce-4706-8742-bc7d032df862' ) ;
2021-11-09 17:16:28 +01:00
assert . equal ( withpdf . getField ( 'title' ) , 'Item with PDF' ) ;
assert . equal ( withpdf . itemTypeID , Zotero . ItemTypes . getID ( 'journalArticle' ) ) ;
// creators
const creators = journal . getCreators ( ) ;
assert . lengthOf ( creators , 2 ) ;
assert . sameMembers ( creators . map ( c => c . firstName ) , [ "Tom" , "Lorem" ] ) ;
assert . sameMembers ( creators . map ( c => c . lastName ) , [ "Najdek" , "Ipsum" ] ) ;
2021-11-04 20:32:35 +01:00
2021-11-09 17:16:28 +01:00
// identifiers
2021-11-04 20:32:35 +01:00
assert . equal ( journal . getField ( 'DOI' ) , '10.1111' ) ;
2022-07-07 12:19:37 +02:00
assert . sameMembers ( journal . getField ( 'extra' ) . split ( '\n' ) , [ 'PMID: 11111111' , 'arXiv: 1111.2222' ] ) ;
2021-11-09 17:16:28 +01:00
2023-03-09 22:13:19 +01:00
// tags
assert . equal ( withTags . getTags ( ) . length , 4 ) ;
assert . sameMembers (
withTags . getTags ( ) . filter ( t => t . type === 1 ) . map ( t => t . tag ) ,
[ 'keyword1' , 'keyword2' ]
) ;
assert . sameMembers (
withTags . getTags ( ) . filter ( t => ! t . type ) . map ( t => t . tag ) ,
[ 'tag1' , 'tag2' ]
) ;
2021-11-09 17:16:28 +01:00
// attachment & annotations
assert . lengthOf ( withpdf . getAttachments ( ) , 1 ) ;
assert . equal ( pdf . parentID , withpdf . id ) ;
2022-09-13 01:57:24 +02:00
const yellowHighlight = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , '339d0202-d99f-48a2-aa0d-9b0c5631af26' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const redHighlight = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , '885615a7-170e-4613-af80-0227ea76ae55' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const blueNote = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , 'bfbdb972-171d-4b21-8ae6-f156ac9a2b41' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const greenNote = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , '734743eb-2be3-49ef-b1ac-3f1e84fea2f2' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const orangeNote = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , 'c436932f-b14b-4580-a649-4587a5cdc2c3' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const purpleGroupNote = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , '656fd591-451a-4bb0-8d5f-30c36c135fc9' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( blueNote . annotationComment , 'blue note 2' ) ;
assert . equal ( greenNote . annotationComment , 'green note' ) ;
assert . equal ( orangeNote . annotationComment , 'orange note1' ) ;
assert . equal ( purpleGroupNote . annotationComment , 'note by me' ) ;
// map yellow rgb(255, 245, 173) -> #ffd400'
assert . equal ( yellowHighlight . annotationColor , '#ffd400' ) ;
// map red: rgb(255, 181, 182) -> #ff6666
assert . equal ( redHighlight . annotationColor , '#ff6666' ) ;
// map blue: rgb(186, 226, 255) -> '#2ea8e5'
assert . equal ( blueNote . annotationColor , '#2ea8e5' ) ;
// map purple: rgb(211, 194, 255) -> '#a28ae5'
assert . equal ( purpleGroupNote . annotationColor , '#a28ae5' ) ;
// map green: rgb(220, 255, 176) -> #5fb236
assert . equal ( greenNote . annotationColor , '#5fb236' ) ;
// preserve other colors rgb(255, 222, 180) stays as #ffdeb4
assert . equal ( orangeNote . annotationColor , '#ffdeb4' ) ;
// group annotations by others and mismatched annotations are not included
2021-11-09 17:16:28 +01:00
const annotations = await pdf . getAnnotations ( ) ;
2022-09-13 01:57:24 +02:00
assert . equal ( annotations . length , 6 ) ;
2021-11-10 14:59:37 +01:00
assert . isFalse ( annotations . some ( a => a . annotationComment === 'note by other' ) ) ;
assert . isFalse ( annotations . some ( a => a . annotationComment === 'mismatched note' ) ) ;
2021-11-09 17:16:28 +01:00
// collection
2021-11-04 04:32:36 +01:00
const parentCollection = await Zotero . Collections . getAsync (
journal . getCollections ( ) . pop ( )
) ;
assert . equal ( parentCollection . name , 'folder1' ) ;
} ) ;
2022-10-16 20:10:58 +02:00
it ( "should update previously imported item, based on config" , async ( ) => {
const importer1 = getImporter ( ) ;
await importer1 . translate ( {
2021-11-04 04:32:36 +01:00
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const report = ( await Zotero . Relations
2022-10-16 20:10:58 +02:00
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '616ec6d1-8d23-4414-8b6e-7bb129677577' ) )
2021-11-04 04:32:36 +01:00
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
2022-10-16 20:10:58 +02:00
2021-11-04 04:32:36 +01:00
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . getField ( 'year' ) , '2002' ) ;
2022-10-16 20:10:58 +02:00
assert . equal ( report . getField ( 'dateAdded' ) , '2021-11-04 11:53:10' ) ;
2021-11-04 04:32:36 +01:00
assert . equal ( report . itemTypeID , Zotero . ItemTypes . getID ( 'report' ) ) ;
assert . lengthOf ( report . getTags ( ) , 0 ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-updated.json' )
)
} ) ;
2022-10-16 20:10:58 +02:00
const importer2 = getImporter ( ) ;
importer2 . newItemsOnly = false ;
await importer2 . translate ( {
2021-11-04 04:32:36 +01:00
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
assert . equal ( report . getField ( 'title' ) , 'Report updated to Journal Article' ) ;
assert . equal ( report . itemTypeID , Zotero . ItemTypes . getID ( 'journalArticle' ) ) ;
assert . equal ( report . getField ( 'year' ) , '2002' ) ;
assert . sameMembers ( report . getTags ( ) . map ( t => t . tag ) , [ '\u2605' ] ) ;
2022-10-16 20:10:58 +02:00
// dateAdded shouldn't change on an updated item. See #2881
assert . equal ( report . getField ( 'dateAdded' ) , '2021-11-04 11:53:10' ) ;
} ) ;
it ( "shouldn't update previously imported item, based on config" , async ( ) => {
const importer1 = getImporter ( ) ;
await importer1 . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const report = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '616ec6d1-8d23-4414-8b6e-7bb129677577' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const noNewItemHere = await Zotero . Relations . getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '86e56a00-5ae5-4fe8-a977-9298a03b16d6' ) ;
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . getField ( 'year' ) , '2002' ) ;
assert . equal ( report . itemTypeID , Zotero . ItemTypes . getID ( 'report' ) ) ;
assert . lengthOf ( report . getTags ( ) , 0 ) ;
assert . lengthOf ( noNewItemHere , 0 ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-updated.json' )
)
} ) ;
const importer2 = getImporter ( ) ;
importer2 . newItemsOnly = true ;
await importer2 . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . itemTypeID , Zotero . ItemTypes . getID ( 'report' ) ) ;
assert . equal ( report . getField ( 'year' ) , '2002' ) ;
assert . lengthOf ( report . getTags ( ) , 0 ) ;
const newItem = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '86e56a00-5ae5-4fe8-a977-9298a03b16d6' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( newItem . getField ( 'title' ) , 'Completely new item' ) ;
} ) ;
it ( "should correct IDs if available on subsequent import" , async ( ) => {
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-simple-no-desktop-id.json' )
)
} ) ;
const importer = getImporter ( ) ;
importer . newItemsOnly = true ;
await importer . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const report = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:remoteDocumentUUID' , '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . getRelations ( ) [ 'mendeleyDB:documentUUID' ] , '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef' ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-simple.json' )
)
} ) ;
await importer . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . getRelations ( ) [ 'mendeleyDB:documentUUID' ] , '616ec6d1-8d23-4414-8b6e-7bb129677577' ) ;
2021-11-04 04:32:36 +01:00
} ) ;
2022-12-15 19:35:29 +01:00
it ( "should only correct IDs and not add new items if \"relinkOnly\" is configured" , async ( ) => {
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-simple-no-desktop-id.json' )
)
} ) ;
const importer1 = getImporter ( ) ;
await importer1 . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const report = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:remoteDocumentUUID' , '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . getRelations ( ) [ 'mendeleyDB:documentUUID' ] , '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef' ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-updated.json' )
)
} ) ;
const importer2 = getImporter ( ) ;
importer2 . relinkOnly = true ;
await importer2 . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
assert . equal ( report . getField ( 'title' ) , 'Sample Report' ) ;
assert . equal ( report . getRelations ( ) [ 'mendeleyDB:documentUUID' ] , '616ec6d1-8d23-4414-8b6e-7bb129677577' ) ;
const noNewItemHere = await Zotero . Relations . getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '86e56a00-5ae5-4fe8-a977-9298a03b16d6' ) ;
assert . lengthOf ( noNewItemHere , 0 ) ;
2023-03-08 01:40:42 +01:00
} ) ;
2023-03-09 22:13:19 +01:00
it ( "should handle empty creators and tags" , async ( ) => {
2023-03-08 01:40:42 +01:00
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` documents?view=all&limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
2023-03-09 22:13:19 +01:00
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/items-bad-data.json' )
2023-03-08 01:40:42 +01:00
)
} ) ;
const importer = getImporter ( ) ;
await importer . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const journalNoAuthors = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , '9c03fca4-ee5b-435e-abdd-fb6d7d11cd02' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( journalNoAuthors . getField ( 'title' ) , 'This one has no authors' ) ;
assert . equal ( journalNoAuthors . getCreators ( ) . length , 0 ) ;
const journalEmptyAuthors = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , 'fd86e48e-1931-4282-b72d-78c535b0398c' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
2022-12-15 19:35:29 +01:00
2023-03-08 01:40:42 +01:00
assert . equal ( journalEmptyAuthors . getField ( 'title' ) , 'This one has empty authors' ) ;
assert . equal ( journalEmptyAuthors . getCreators ( ) . length , 0 ) ;
2023-03-09 22:13:19 +01:00
const journalEmptyTags = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:documentUUID' , 'c7ec2737-044a-493b-9d94-d7f67be68765' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( journalEmptyTags . getField ( 'title' ) , 'This one has empty tags and keywords' ) ;
assert . equal ( journalEmptyTags . getTags ( ) . length , 0 ) ;
2022-12-15 19:35:29 +01:00
} ) ;
2024-11-12 06:13:17 +01:00
it ( 'should translate a notebook content into Zotero note content' , async ( ) => {
let item = await createDataObject ( 'item' ) ;
item . itemType = 'journalArticle' ;
item . title = 'Journal Article' ;
await item . saveTx ( ) ;
let attachment = await importFileAttachment ( 'test.pdf' , { parentID : item . id } ) ;
await attachment . saveTx ( ) ;
var annotation = await createAnnotation ( 'highlight' , attachment ) ;
annotation . annotationText = 'Highlight text' ;
annotation . annotationComment = 'Highlight comment' ;
annotation . annotationPageLabel = '57' ;
2024-12-06 19:14:09 +01:00
annotation . addRelation ( 'mendeleyDB:annotationUUID' , '339d0202-d99f-48a2-aa0d-9b0c5631af26' ) ;
2024-11-12 06:13:17 +01:00
await annotation . saveTx ( ) ;
let mendeleyNotebook = JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/notebook.json' )
) ;
const importer = getImporter ( ) ;
const noteContent = await importer . _translateNotebookToNoteContent ( Zotero . Libraries . userLibraryID , mendeleyNotebook ) ;
assert . match (
noteContent ,
/^<h1>TEST<\/h1>\n<p><span class="highlight" data-annotation="((?:(?:%[0-9A-F]{2}|[^<>'" %])+))">“Highlight text”<\/span> <span class="citation" data-citation="((?:(?:%[0-9A-F]{2}|[^<>'" %])+))">\(<span class="citation-item">, p. 57<\/span>\)<\/span> Highlight comment<\/p>\n<p>Lorem Ipsum<\/p>$/i
) ;
await annotation . eraseTx ( ) ;
await attachment . eraseTx ( ) ;
await item . eraseTx ( ) ;
} ) ;
2024-12-06 19:14:09 +01:00
it ( 'should import a notebook from Mendeley' , async ( ) => {
const importer = getImporter ( { importNotes : true } ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` notes/v1?limit=500 ` ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/notebooks.json' )
)
} ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : 'notes/v1/8041a43b-f740-41ec-be42-a24cc5106d68' ,
status : 200 ,
headers : { } ,
json : JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/notebook.json' )
)
} ) ;
await importer . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const note = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:notebookUUID' , '8041a43b-f740-41ec-be42-a24cc5106d68' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . match (
note . note ,
/^<h1>TEST<\/h1>\n<p><span class="highlight" data-annotation="((?:(?:%[0-9A-F]{2}|[^<>'" %])+))">“A purely peer-to-peer version of electronic cash would allow online payments to be sent directly from one party to another without going through a financial institution”<\/span> <span class="citation" data-citation="((?:(?:%[0-9A-F]{2}|[^<>'" %])+))">\(<span class="citation-item">“Item with PDF”, 2005, p. 1<\/span>\)<\/span><\/p>\n<p>Lorem Ipsum<\/p>$/i
) ;
} ) ;
it ( 'should handle incorrect annotations' , async ( ) => {
let annotationsResponse = JSON . parse (
await Zotero . File . getContentsFromURLAsync ( 'resource://zotero-unit-tests/data/mendeleyMock/annotations.json' )
) ;
delete annotationsResponse . find ( a => a . id == '885615a7-170e-4613-af80-0227ea76ae55' ) . type ;
delete annotationsResponse . find ( a => a . id == 'bfbdb972-171d-4b21-8ae6-f156ac9a2b41' ) . color ;
annotationsResponse . push ( { type : 'note' , id : 'invalid' } ) ;
setHTTPResponse ( server , 'https://api.mendeley.com/' , {
method : 'GET' ,
url : ` annotations?limit=200 ` ,
status : 200 ,
headers : { } ,
json : annotationsResponse
} ) ;
const importer = getImporter ( ) ;
await importer . translate ( {
libraryID : Zotero . Libraries . userLibraryID ,
collections : null ,
linkFiles : false ,
} ) ;
const pdf = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:fileHash' , 'cc22c6611277df346ff8dc7386ba3880b2bafa15' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
const annotations = await pdf . getAnnotations ( ) ;
// Typeless notes and invalid annotations should be discarded.
assert . lengthOf ( annotations , 5 ) ;
assert . lengthOf ( await Zotero . Relations . getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , '885615a7-170e-4613-af80-0227ea76ae55' ) , 0 ) ;
assert . lengthOf ( await Zotero . Relations . getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , 'invalid' ) , 0 ) ;
// Colorless note annotations should have a default colour.
const colorlessNote = ( await Zotero . Relations
. getByPredicateAndObject ( 'item' , 'mendeleyDB:annotationUUID' , 'bfbdb972-171d-4b21-8ae6-f156ac9a2b41' ) )
. filter ( item => item . libraryID == Zotero . Libraries . userLibraryID && ! item . deleted )
. shift ( ) ;
assert . equal ( colorlessNote . annotationColor , '#ffd400' ) ;
} ) ;
2021-11-04 04:32:36 +01:00
} ) ;
} ) ;