2021-05-21 15:17:21 +02:00
import { PaginationOrderDir } from '../../models/utils/types' ;
import Api , { RequestMethod } from '../../services/rest/Api' ;
2022-06-20 14:56:54 +02:00
import { extractMediaUrls } from './routes/notes' ;
2021-05-21 15:17:21 +02:00
import shim from '../../shim' ;
2021-08-12 17:54:10 +02:00
import { setupDatabaseAndSynchronizer , switchClient , checkThrowAsync , db , msleep , supportDir } from '../../testing/test-utils' ;
2021-05-21 15:17:21 +02:00
import Folder from '../../models/Folder' ;
import Resource from '../../models/Resource' ;
import Note from '../../models/Note' ;
import Tag from '../../models/Tag' ;
import NoteTag from '../../models/NoteTag' ;
import ResourceService from '../../services/ResourceService' ;
import SearchEngine from '../../services/searchengine/SearchEngine' ;
2022-06-20 14:56:54 +02:00
const { MarkupToHtml } = require ( '@joplin/renderer' ) ;
2022-04-09 12:58:08 +02:00
import { ResourceEntity } from '../database/types' ;
2020-11-05 18:58:23 +02:00
2020-11-12 21:13:28 +02:00
const createFolderForPagination = async ( num : number , time : number ) = > {
2020-11-05 18:58:23 +02:00
await Folder . save ( {
title : ` folder ${ num } ` ,
updated_time : time ,
created_time : time ,
} , { autoTimestamp : false } ) ;
} ;
2018-09-27 10:14:05 +02:00
2020-11-17 11:53:50 +02:00
const createNoteForPagination = async ( numOrTitle : number | string , time : number ) = > {
const title = typeof numOrTitle === 'string' ? numOrTitle : ` note ${ numOrTitle } ` ;
const body = typeof numOrTitle === 'string' ? ` Note body ${ numOrTitle } ` : ` noteBody ${ numOrTitle } ` ;
2020-11-09 19:17:51 +02:00
await Note . save ( {
2020-11-17 11:53:50 +02:00
title : title ,
body : body ,
2020-11-09 19:17:51 +02:00
updated_time : time ,
created_time : time ,
} , { autoTimestamp : false } ) ;
} ;
2020-11-12 21:13:28 +02:00
let api : Api = null ;
2018-09-27 10:14:05 +02:00
2023-02-20 17:02:29 +02:00
describe ( 'services_rest_Api' , ( ) = > {
2018-09-27 10:14:05 +02:00
2022-11-15 12:23:50 +02:00
beforeEach ( async ( ) = > {
2018-09-27 10:14:05 +02:00
api = new Api ( ) ;
await setupDatabaseAndSynchronizer ( 1 ) ;
await switchClient ( 1 ) ;
} ) ;
2020-12-01 20:05:24 +02:00
it ( 'should ping' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . GET , 'ping' ) ;
2020-10-10 15:09:54 +02:00
expect ( response ) . toBe ( 'JoplinClipperServer' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 10:14:05 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should handle Not Found errors' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const hasThrown = await checkThrowAsync ( async ( ) = > await api . route ( RequestMethod . GET , 'pong' ) ) ;
2020-10-10 15:09:54 +02:00
expect ( hasThrown ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 10:14:05 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should get folders' , ( async ( ) = > {
2020-10-10 15:09:54 +02:00
await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . GET , 'folders' ) ;
expect ( response . items . length ) . toBe ( 1 ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 10:14:05 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should update folders' , ( async ( ) = > {
2020-03-14 01:46:14 +02:00
const f1 = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . PUT , ` folders/ ${ f1 . id } ` , null , JSON . stringify ( {
2018-09-28 20:24:57 +02:00
title : 'modifié' ,
} ) ) ;
2020-03-14 01:46:14 +02:00
const f1b = await Folder . load ( f1 . id ) ;
2018-09-28 20:24:57 +02:00
expect ( f1b . title ) . toBe ( 'modifié' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-28 20:24:57 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should delete folders' , ( async ( ) = > {
2020-03-14 01:46:14 +02:00
const f1 = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . DELETE , ` folders/ ${ f1 . id } ` ) ;
2018-09-28 20:24:57 +02:00
2020-03-14 01:46:14 +02:00
const f1b = await Folder . load ( f1 . id ) ;
2018-09-28 20:24:57 +02:00
expect ( ! f1b ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2019-07-30 09:35:42 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create folders' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . POST , 'folders' , null , JSON . stringify ( {
2018-09-28 20:24:57 +02:00
title : 'from api' ,
} ) ) ;
expect ( ! ! response . id ) . toBe ( true ) ;
2020-03-14 01:46:14 +02:00
const f = await Folder . all ( ) ;
2018-09-28 20:24:57 +02:00
expect ( f . length ) . toBe ( 1 ) ;
expect ( f [ 0 ] . title ) . toBe ( 'from api' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2019-07-30 09:35:42 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should get one folder' , ( async ( ) = > {
2020-03-14 01:46:14 +02:00
const f1 = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . GET , ` folders/ ${ f1 . id } ` ) ;
2018-09-28 20:24:57 +02:00
expect ( response . id ) . toBe ( f1 . id ) ;
2020-11-05 18:58:23 +02:00
const hasThrown = await checkThrowAsync ( async ( ) = > await api . route ( RequestMethod . GET , 'folders/doesntexist' ) ) ;
2018-09-28 20:24:57 +02:00
expect ( hasThrown ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-28 20:24:57 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should get the folder notes' , ( async ( ) = > {
2020-03-14 01:46:14 +02:00
const f1 = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
const response2 = await api . route ( RequestMethod . GET , ` folders/ ${ f1 . id } /notes ` ) ;
expect ( response2 . items . length ) . toBe ( 0 ) ;
2018-09-29 13:54:44 +02:00
2020-10-10 15:09:54 +02:00
await Note . save ( { title : 'un' , parent_id : f1.id } ) ;
await Note . save ( { title : 'deux' , parent_id : f1.id } ) ;
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . GET , ` folders/ ${ f1 . id } /notes ` ) ;
expect ( response . items . length ) . toBe ( 2 ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-29 13:54:44 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should fail on invalid paths' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const hasThrown = await checkThrowAsync ( async ( ) = > await api . route ( RequestMethod . GET , 'schtroumpf' ) ) ;
2018-09-28 20:24:57 +02:00
expect ( hasThrown ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-28 20:24:57 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should get notes' , ( async ( ) = > {
2018-09-27 20:35:10 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f1 = await Folder . save ( { title : 'mon carnet' } ) ;
const f2 = await Folder . save ( { title : 'mon deuxième carnet' } ) ;
2018-09-27 20:35:10 +02:00
const n1 = await Note . save ( { title : 'un' , parent_id : f1.id } ) ;
2020-10-10 15:09:54 +02:00
await Note . save ( { title : 'deux' , parent_id : f1.id } ) ;
2018-09-27 20:35:10 +02:00
const n3 = await Note . save ( { title : 'trois' , parent_id : f2.id } ) ;
2019-07-30 09:35:42 +02:00
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . GET , 'notes' ) ;
expect ( response . items . length ) . toBe ( 3 ) ;
2018-09-27 20:35:10 +02:00
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . GET , ` notes/ ${ n1 . id } ` ) ;
2018-09-27 20:35:10 +02:00
expect ( response . id ) . toBe ( n1 . id ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . GET , ` notes/ ${ n3 . id } ` , { fields : 'id,title' } ) ;
2018-09-27 20:35:10 +02:00
expect ( Object . getOwnPropertyNames ( response ) . length ) . toBe ( 3 ) ;
expect ( response . id ) . toBe ( n3 . id ) ;
expect ( response . title ) . toBe ( 'trois' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 20:35:10 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create notes' , ( async ( ) = > {
2018-09-27 10:14:05 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2018-09-27 10:14:05 +02:00
title : 'testing' ,
parent_id : f.id ,
} ) ) ;
expect ( response . title ) . toBe ( 'testing' ) ;
expect ( ! ! response . id ) . toBe ( true ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2018-09-27 10:14:05 +02:00
title : 'testing' ,
parent_id : f.id ,
} ) ) ;
expect ( response . title ) . toBe ( 'testing' ) ;
expect ( ! ! response . id ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 10:14:05 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should allow setting note properties' , ( async ( ) = > {
2020-11-12 21:13:28 +02:00
let response : any = null ;
2020-10-10 15:09:54 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2020-10-10 15:09:54 +02:00
title : 'testing' ,
parent_id : f.id ,
latitude : '48.732071' ,
longitude : '-3.458700' ,
altitude : '21' ,
} ) ) ;
const noteId = response . id ;
2020-10-16 17:26:19 +02:00
2020-10-10 15:09:54 +02:00
{
const note = await Note . load ( noteId ) ;
expect ( note . latitude ) . toBe ( '48.73207100' ) ;
expect ( note . longitude ) . toBe ( '-3.45870000' ) ;
expect ( note . altitude ) . toBe ( '21.0000' ) ;
}
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . PUT , ` notes/ ${ noteId } ` , null , JSON . stringify ( {
2020-10-10 15:09:54 +02:00
latitude : '49' ,
longitude : '-3' ,
altitude : '22' ,
} ) ) ;
{
const note = await Note . load ( noteId ) ;
expect ( note . latitude ) . toBe ( '49.00000000' ) ;
expect ( note . longitude ) . toBe ( '-3.00000000' ) ;
expect ( note . altitude ) . toBe ( '22.0000' ) ;
}
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should preserve user timestamps when creating notes' , ( async ( ) = > {
2019-06-22 13:31:04 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2019-06-22 13:31:04 +02:00
const updatedTime = Date . now ( ) - 1000 ;
const createdTime = Date . now ( ) - 10000 ;
2019-07-30 09:35:42 +02:00
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2019-06-22 13:31:04 +02:00
parent_id : f.id ,
user_updated_time : updatedTime ,
user_created_time : createdTime ,
} ) ) ;
expect ( response . user_updated_time ) . toBe ( updatedTime ) ;
expect ( response . user_created_time ) . toBe ( createdTime ) ;
2020-10-21 19:12:36 +02:00
const timeBefore = Date . now ( ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2020-10-21 19:12:36 +02:00
parent_id : f.id ,
} ) ) ;
const newNote = await Note . load ( response . id ) ;
expect ( newNote . user_updated_time ) . toBeGreaterThanOrEqual ( timeBefore ) ;
expect ( newNote . user_created_time ) . toBeGreaterThanOrEqual ( timeBefore ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should preserve user timestamps when updating notes' , ( async ( ) = > {
2020-10-21 19:12:36 +02:00
const folder = await Folder . save ( { title : 'mon carnet' } ) ;
const updatedTime = Date . now ( ) - 1000 ;
const createdTime = Date . now ( ) - 10000 ;
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2020-10-21 19:12:36 +02:00
parent_id : folder.id ,
} ) ) ;
const noteId = response . id ;
{
// Check that if user timestamps are supplied, they are preserved by the API
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . PUT , ` notes/ ${ noteId } ` , null , JSON . stringify ( {
2020-10-21 19:12:36 +02:00
user_updated_time : updatedTime ,
user_created_time : createdTime ,
title : 'mod' ,
} ) ) ;
const modNote = await Note . load ( noteId ) ;
expect ( modNote . title ) . toBe ( 'mod' ) ;
expect ( modNote . user_updated_time ) . toBe ( updatedTime ) ;
expect ( modNote . user_created_time ) . toBe ( createdTime ) ;
}
{
// Check if no user timestamps are supplied they are automatically updated.
const beforeTime = Date . now ( ) ;
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . PUT , ` notes/ ${ noteId } ` , null , JSON . stringify ( {
2020-10-21 19:12:36 +02:00
title : 'mod2' ,
} ) ) ;
const modNote = await Note . load ( noteId ) ;
expect ( modNote . title ) . toBe ( 'mod2' ) ;
expect ( modNote . user_updated_time ) . toBeGreaterThanOrEqual ( beforeTime ) ;
expect ( modNote . user_created_time ) . toBeGreaterThanOrEqual ( createdTime ) ;
}
2019-09-24 00:23:10 +02:00
} ) ) ;
2019-06-22 13:31:04 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create notes with supplied ID' , ( async ( ) = > {
2018-11-08 03:14:13 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2018-11-08 03:14:13 +02:00
id : '12345678123456781234567812345678' ,
title : 'testing' ,
parent_id : f.id ,
} ) ) ;
expect ( response . id ) . toBe ( '12345678123456781234567812345678' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-11-08 03:14:13 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create todos' , ( async ( ) = > {
2019-06-28 14:46:55 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'stuff to do' } ) ;
2019-06-28 14:46:55 +02:00
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2019-06-28 14:46:55 +02:00
title : 'testing' ,
parent_id : f.id ,
2019-07-30 09:35:42 +02:00
is_todo : 1 ,
2019-06-28 14:46:55 +02:00
} ) ) ;
expect ( response . is_todo ) . toBe ( 1 ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2019-06-28 14:46:55 +02:00
title : 'testing 2' ,
parent_id : f.id ,
2019-07-30 09:35:42 +02:00
is_todo : 0 ,
2019-06-28 14:46:55 +02:00
} ) ) ;
expect ( response . is_todo ) . toBe ( 0 ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2019-06-28 14:46:55 +02:00
title : 'testing 3' ,
parent_id : f.id ,
} ) ) ;
expect ( response . is_todo ) . toBeUndefined ( ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2019-06-28 14:46:55 +02:00
title : 'testing 4' ,
parent_id : f.id ,
2019-07-30 09:35:42 +02:00
is_todo : '1' ,
2023-01-11 21:14:19 +02:00
todo_due : '2' ,
todo_completed : '3' ,
2019-06-28 14:46:55 +02:00
} ) ) ;
2023-01-11 21:14:19 +02:00
expect ( response . todo_due ) . toBe ( 2 ) ;
expect ( response . todo_completed ) . toBe ( 3 ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2019-06-28 14:46:55 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create folders with supplied ID' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . POST , 'folders' , null , JSON . stringify ( {
2019-02-07 00:36:39 +02:00
id : '12345678123456781234567812345678' ,
title : 'from api' ,
} ) ) ;
expect ( response . id ) . toBe ( '12345678123456781234567812345678' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2019-07-30 09:35:42 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create notes with images' , ( async ( ) = > {
2018-09-27 10:14:05 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2018-09-27 10:14:05 +02:00
title : 'testing image' ,
parent_id : f.id ,
2019-07-30 09:35:42 +02:00
image_data_url : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANZJREFUeNoAyAA3/wFwtO3K6gUB/vz2+Prw9fj/+/r+/wBZKAAExOgF4/MC9ff+MRH6Ui4E+/0Bqc/zutj6AgT+/Pz7+vv7++nu82c4DlMqCvLs8goA/gL8/fz09fb59vXa6vzZ6vjT5fbn6voD/fwC8vX4UiT9Zi//APHyAP8ACgUBAPv5APz7BPj2+DIaC2o3E+3o6ywaC5fT6gD6/QD9/QEVf9kD+/dcLQgJA/7v8vqfwOf18wA1IAIEVycAyt//v9XvAPv7APz8LhoIAPz9Ri4OAgwARgx4W/6fVeEAAAAASUVORK5CYII=' ,
2018-09-27 10:14:05 +02:00
} ) ) ;
const resources = await Resource . all ( ) ;
expect ( resources . length ) . toBe ( 1 ) ;
const resource = resources [ 0 ] ;
expect ( response . body . indexOf ( resource . id ) >= 0 ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 10:14:05 +02:00
2022-03-28 17:35:41 +02:00
it ( 'should not compress images uploaded through resource API' , ( async ( ) = > {
2021-05-21 15:17:21 +02:00
const originalImagePath = ` ${ supportDir } /photo-large.png ` ;
2021-03-14 17:28:34 +02:00
await api . route ( RequestMethod . POST , 'resources' , null , JSON . stringify ( {
title : 'testing resource' ,
} ) , [
{
path : originalImagePath ,
} ,
] ) ;
const resources = await Resource . all ( ) ;
expect ( resources . length ) . toBe ( 1 ) ;
const uploadedImagePath = Resource . fullPath ( resources [ 0 ] ) ;
const originalImageSize = ( await shim . fsDriver ( ) . stat ( originalImagePath ) ) . size ;
const uploadedImageSize = ( await shim . fsDriver ( ) . stat ( uploadedImagePath ) ) . size ;
expect ( originalImageSize ) . toEqual ( uploadedImageSize ) ;
} ) ) ;
2022-03-28 17:35:41 +02:00
it ( 'should update a resource' , ( async ( ) = > {
await api . route ( RequestMethod . POST , 'resources' , null , JSON . stringify ( {
title : 'resource' ,
} ) , [
{
path : ` ${ supportDir } /photo.jpg ` ,
} ,
] ) ;
2022-04-09 12:58:08 +02:00
const resourceV1 : ResourceEntity = ( await Resource . all ( ) ) [ 0 ] ;
2022-03-28 17:35:41 +02:00
await msleep ( 1 ) ;
await api . route ( RequestMethod . PUT , ` resources/ ${ resourceV1 . id } ` , null , JSON . stringify ( {
title : 'resource mod' ,
} ) , [
{
path : ` ${ supportDir } /photo-large.png ` ,
} ,
] ) ;
2022-04-09 12:58:08 +02:00
const resourceV2 : ResourceEntity = ( await Resource . all ( ) ) [ 0 ] ;
2022-03-28 17:35:41 +02:00
expect ( resourceV2 . title ) . toBe ( 'resource mod' ) ;
expect ( resourceV2 . mime ) . toBe ( 'image/png' ) ;
expect ( resourceV2 . file_extension ) . toBe ( 'png' ) ;
expect ( resourceV2 . updated_time ) . toBeGreaterThan ( resourceV1 . updated_time ) ;
expect ( resourceV2 . created_time ) . toBe ( resourceV1 . created_time ) ;
expect ( resourceV2 . size ) . toBeGreaterThan ( resourceV1 . size ) ;
expect ( resourceV2 . size ) . toBe ( ( await shim . fsDriver ( ) . stat ( Resource . fullPath ( resourceV2 ) ) ) . size ) ;
} ) ) ;
2022-04-11 18:01:01 +02:00
it ( 'should allow updating a resource file only' , ( async ( ) = > {
await api . route ( RequestMethod . POST , 'resources' , null , JSON . stringify ( {
title : 'resource' ,
} ) , [ { path : ` ${ supportDir } /photo.jpg ` } ] ) ;
const resourceV1 : ResourceEntity = ( await Resource . all ( ) ) [ 0 ] ;
await msleep ( 1 ) ;
await api . route ( RequestMethod . PUT , ` resources/ ${ resourceV1 . id } ` , null , null , [
{
path : ` ${ supportDir } /photo-large.png ` ,
} ,
] ) ;
const resourceV2 : ResourceEntity = ( await Resource . all ( ) ) [ 0 ] ;
// It should have updated the file content, but not the metadata
expect ( resourceV2 . title ) . toBe ( resourceV1 . title ) ;
expect ( resourceV2 . size ) . toBeGreaterThan ( resourceV1 . size ) ;
} ) ) ;
2022-04-09 12:58:08 +02:00
it ( 'should update resource properties' , ( async ( ) = > {
await api . route ( RequestMethod . POST , 'resources' , null , JSON . stringify ( {
title : 'resource' ,
} ) , [ { path : ` ${ supportDir } /photo.jpg ` } ] ) ;
const resourceV1 : ResourceEntity = ( await Resource . all ( ) ) [ 0 ] ;
await msleep ( 1 ) ;
await api . route ( RequestMethod . PUT , ` resources/ ${ resourceV1 . id } ` , null , JSON . stringify ( {
title : 'my new title' ,
} ) ) ;
const resourceV2 : ResourceEntity = ( await Resource . all ( ) ) [ 0 ] ;
expect ( resourceV2 . title ) . toBe ( 'my new title' ) ;
expect ( resourceV2 . mime ) . toBe ( resourceV1 . mime ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should delete resources' , ( async ( ) = > {
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2019-07-13 16:57:53 +02:00
title : 'testing image' ,
parent_id : f.id ,
2019-07-30 09:35:42 +02:00
image_data_url : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANZJREFUeNoAyAA3/wFwtO3K6gUB/vz2+Prw9fj/+/r+/wBZKAAExOgF4/MC9ff+MRH6Ui4E+/0Bqc/zutj6AgT+/Pz7+vv7++nu82c4DlMqCvLs8goA/gL8/fz09fb59vXa6vzZ6vjT5fbn6voD/fwC8vX4UiT9Zi//APHyAP8ACgUBAPv5APz7BPj2+DIaC2o3E+3o6ywaC5fT6gD6/QD9/QEVf9kD+/dcLQgJA/7v8vqfwOf18wA1IAIEVycAyt//v9XvAPv7APz8LhoIAPz9Ri4OAgwARgx4W/6fVeEAAAAASUVORK5CYII=' ,
2019-07-13 16:57:53 +02:00
} ) ) ;
const resource = ( await Resource . all ( ) ) [ 0 ] ;
const filePath = Resource . fullPath ( resource ) ;
expect ( await shim . fsDriver ( ) . exists ( filePath ) ) . toBe ( true ) ;
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . DELETE , ` resources/ ${ resource . id } ` ) ;
2019-07-13 16:57:53 +02:00
expect ( await shim . fsDriver ( ) . exists ( filePath ) ) . toBe ( false ) ;
expect ( ! ( await Resource . load ( resource . id ) ) ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2019-07-30 09:35:42 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should create notes from HTML' , ( async ( ) = > {
2018-09-27 10:14:05 +02:00
let response = null ;
2019-07-30 09:35:42 +02:00
const f = await Folder . save ( { title : 'mon carnet' } ) ;
2020-11-05 18:58:23 +02:00
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
2018-09-27 10:14:05 +02:00
title : 'testing HTML' ,
parent_id : f.id ,
body_html : '<b>Bold text</b>' ,
} ) ) ;
expect ( response . body ) . toBe ( '**Bold text**' ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-27 10:14:05 +02:00
2022-06-20 14:56:54 +02:00
it ( 'should extract media urls from body' , ( ( ) = > {
const tests = [
{
language : MarkupToHtml.MARKUP_LANGUAGE_HTML ,
body : '<div> <img src="https://example.com/img.png" /> <embed src="https://example.com/sample.pdf"/> <object data="https://example.com/file.PDF"></object> </div>' ,
result : [ 'https://example.com/img.png' , 'https://example.com/sample.pdf' , 'https://example.com/file.PDF' ] ,
} ,
{
language : MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN ,
body : 'test text \n ![img 1](https://example.com/img1.png) [embedded_pdf](https://example.com/sample1.pdf) [embedded_pdf](https://example.com/file.PDF)' ,
result : [ 'https://example.com/img1.png' , 'https://example.com/sample1.pdf' , 'https://example.com/file.PDF' ] ,
} ,
2023-02-24 20:50:04 +02:00
{
language : MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN ,
body : '> <a id="attachment68076"></a>[![Enable or Disable Sync Your Settings in Windows 10-disabled_sync_your_settings.png](https://www.tenforums.com/attachments/tutorials/68076d1485964056t-enable-disable-sync-your-settings-windows-10-a-disabled_sync_your_settings.png?s=0bbd1c630a9a924f05134d51b4768d2b "Enable or Disable Sync Your Settings in Windows 10-disabled_sync_your_settings.png")](https://www.tenforums.com/attachments/tutorials/68076d1457326453-enable-disable-sync-your-settings-windows-10-a-disabled_sync_your_settings.png?s=0bbd1c630a9a924f05134d51b4768d2b)' ,
result : [ 'https://www.tenforums.com/attachments/tutorials/68076d1485964056t-enable-disable-sync-your-settings-windows-10-a-disabled_sync_your_settings.png?s=0bbd1c630a9a924f05134d51b4768d2b' ] ,
} ,
2022-06-20 14:56:54 +02:00
{
language : MarkupToHtml.MARKUP_LANGUAGE_HTML ,
body : '<div> <embed src="https://example.com/sample"/> <embed /> <object data="https://example.com/file.pdfff"></object> <a href="https://test.com/file.pdf">Link</a> </div>' ,
result : [ ] ,
} ,
] ;
2023-06-30 10:39:21 +02:00
// eslint-disable-next-line github/array-foreach -- Old code before rule was applied
2022-06-20 14:56:54 +02:00
tests . forEach ( ( test ) = > {
const urls = extractMediaUrls ( test . language , test . body ) ;
expect ( urls ) . toEqual ( test . result ) ;
} ) ;
} ) ) ;
it ( 'should create notes with pdf embeds' , ( async ( ) = > {
let response = null ;
const f = await Folder . save ( { title : 'pdf test1' } ) ;
response = await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( {
title : 'testing PDF embeds' ,
parent_id : f.id ,
body_html : ` <div> <embed src="file:// ${ supportDir } /welcome.pdf" type="application/pdf" /> </div> ` ,
} ) ) ;
const resources = await Resource . all ( ) ;
expect ( resources . length ) . toBe ( 1 ) ;
const resource = resources [ 0 ] ;
expect ( response . body . indexOf ( resource . id ) >= 0 ) . toBe ( true ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should handle tokens' , ( async ( ) = > {
2018-09-27 20:35:10 +02:00
api = new Api ( 'mytoken' ) ;
2020-11-05 18:58:23 +02:00
let hasThrown = await checkThrowAsync ( async ( ) = > await api . route ( RequestMethod . GET , 'notes' ) ) ;
2018-09-27 20:35:10 +02:00
expect ( hasThrown ) . toBe ( true ) ;
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . GET , 'notes' , { token : 'mytoken' } ) ;
expect ( response . items . length ) . toBe ( 0 ) ;
2018-09-27 20:35:10 +02:00
2020-11-05 18:58:23 +02:00
hasThrown = await checkThrowAsync ( async ( ) = > await api . route ( RequestMethod . POST , 'notes' , null , JSON . stringify ( { title : 'testing' } ) ) ) ;
2018-09-30 11:15:46 +02:00
expect ( hasThrown ) . toBe ( true ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-30 11:15:46 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should add tags to notes' , ( async ( ) = > {
2019-07-30 09:35:42 +02:00
const tag = await Tag . save ( { title : 'mon étiquette' } ) ;
const note = await Note . save ( { title : 'ma note' } ) ;
2018-09-28 20:24:57 +02:00
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . POST , ` tags/ ${ tag . id } /notes ` , null , JSON . stringify ( {
2018-09-28 20:24:57 +02:00
id : note.id ,
} ) ) ;
2019-07-30 09:35:42 +02:00
const noteIds = await Tag . noteIds ( tag . id ) ;
2018-09-28 20:24:57 +02:00
expect ( noteIds [ 0 ] ) . toBe ( note . id ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-28 20:24:57 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should remove tags from notes' , ( async ( ) = > {
2019-07-30 09:35:42 +02:00
const tag = await Tag . save ( { title : 'mon étiquette' } ) ;
const note = await Note . save ( { title : 'ma note' } ) ;
2018-09-28 20:24:57 +02:00
await Tag . addNote ( tag . id , note . id ) ;
2020-11-05 18:58:23 +02:00
await api . route ( RequestMethod . DELETE , ` tags/ ${ tag . id } /notes/ ${ note . id } ` ) ;
2018-09-28 20:24:57 +02:00
2019-07-30 09:35:42 +02:00
const noteIds = await Tag . noteIds ( tag . id ) ;
2018-09-28 20:24:57 +02:00
expect ( noteIds . length ) . toBe ( 0 ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-28 20:24:57 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should list all tag notes' , ( async ( ) = > {
2019-07-30 09:35:42 +02:00
const tag = await Tag . save ( { title : 'mon étiquette' } ) ;
const tag2 = await Tag . save ( { title : 'mon étiquette 2' } ) ;
const note1 = await Note . save ( { title : 'ma note un' } ) ;
const note2 = await Note . save ( { title : 'ma note deux' } ) ;
2018-09-28 20:24:57 +02:00
await Tag . addNote ( tag . id , note1 . id ) ;
await Tag . addNote ( tag . id , note2 . id ) ;
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . GET , ` tags/ ${ tag . id } /notes ` ) ;
expect ( response . items . length ) . toBe ( 2 ) ;
expect ( 'id' in response . items [ 0 ] ) . toBe ( true ) ;
expect ( 'title' in response . items [ 0 ] ) . toBe ( true ) ;
2018-09-29 13:54:44 +02:00
2020-11-05 18:58:23 +02:00
const response2 = await api . route ( RequestMethod . GET , ` notes/ ${ note1 . id } /tags ` ) ;
expect ( response2 . items . length ) . toBe ( 1 ) ;
2018-09-29 13:54:44 +02:00
await Tag . addNote ( tag2 . id , note1 . id ) ;
2021-02-01 14:41:25 +02:00
const response3 = await api . route ( RequestMethod . GET , ` notes/ ${ note1 . id } /tags ` , { fields : 'id' } ) ;
2020-11-05 18:58:23 +02:00
expect ( response3 . items . length ) . toBe ( 2 ) ;
2021-02-01 14:41:25 +02:00
// Also check that it only returns the required fields
response3 . items . sort ( ( a : any , b : any ) = > {
return a . id < b . id ? - 1 : + 1 ;
} ) ;
const sortedTagIds = [ tag . id , tag2 . id ] ;
sortedTagIds . sort ( ) ;
expect ( JSON . stringify ( response3 . items ) ) . toBe ( ` [{"id":" ${ sortedTagIds [ 0 ] } "},{"id":" ${ sortedTagIds [ 1 ] } "}] ` ) ;
2019-09-24 00:23:10 +02:00
} ) ) ;
2018-09-28 20:24:57 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should update tags when updating notes' , ( async ( ) = > {
2020-03-13 20:44:47 +02:00
const tag1 = await Tag . save ( { title : 'mon étiquette 1' } ) ;
const tag2 = await Tag . save ( { title : 'mon étiquette 2' } ) ;
const tag3 = await Tag . save ( { title : 'mon étiquette 3' } ) ;
const note = await Note . save ( {
title : 'ma note un' ,
} ) ;
2021-01-22 19:41:11 +02:00
await Tag . addNote ( tag1 . id , note . id ) ;
await Tag . addNote ( tag2 . id , note . id ) ;
2020-03-13 20:44:47 +02:00
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . PUT , ` notes/ ${ note . id } ` , null , JSON . stringify ( {
2020-03-13 20:44:47 +02:00
tags : ` ${ tag1 . title } , ${ tag3 . title } ` ,
} ) ) ;
const tagIds = await NoteTag . tagIdsByNoteId ( note . id ) ;
expect ( response . tags === ` ${ tag1 . title } , ${ tag3 . title } ` ) . toBe ( true ) ;
expect ( tagIds . length === 2 ) . toBe ( true ) ;
expect ( tagIds . includes ( tag1 . id ) ) . toBe ( true ) ;
expect ( tagIds . includes ( tag3 . id ) ) . toBe ( true ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should create and update tags when updating notes' , ( async ( ) = > {
2020-03-13 20:44:47 +02:00
const tag1 = await Tag . save ( { title : 'mon étiquette 1' } ) ;
const tag2 = await Tag . save ( { title : 'mon étiquette 2' } ) ;
const newTagTitle = 'mon étiquette 3' ;
const note = await Note . save ( {
title : 'ma note un' ,
} ) ;
2021-01-22 19:41:11 +02:00
await Tag . addNote ( tag1 . id , note . id ) ;
await Tag . addNote ( tag2 . id , note . id ) ;
2020-03-13 20:44:47 +02:00
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . PUT , ` notes/ ${ note . id } ` , null , JSON . stringify ( {
2020-03-13 20:44:47 +02:00
tags : ` ${ tag1 . title } , ${ newTagTitle } ` ,
} ) ) ;
const newTag = await Tag . loadByTitle ( newTagTitle ) ;
const tagIds = await NoteTag . tagIdsByNoteId ( note . id ) ;
expect ( response . tags === ` ${ tag1 . title } , ${ newTag . title } ` ) . toBe ( true ) ;
expect ( tagIds . length === 2 ) . toBe ( true ) ;
expect ( tagIds . includes ( tag1 . id ) ) . toBe ( true ) ;
expect ( tagIds . includes ( newTag . id ) ) . toBe ( true ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should not update tags if tags is not mentioned when updating' , ( async ( ) = > {
2020-03-13 20:44:47 +02:00
const tag1 = await Tag . save ( { title : 'mon étiquette 1' } ) ;
const tag2 = await Tag . save ( { title : 'mon étiquette 2' } ) ;
const note = await Note . save ( {
title : 'ma note un' ,
} ) ;
2021-01-22 19:41:11 +02:00
await Tag . addNote ( tag1 . id , note . id ) ;
await Tag . addNote ( tag2 . id , note . id ) ;
2020-03-13 20:44:47 +02:00
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . PUT , ` notes/ ${ note . id } ` , null , JSON . stringify ( {
2020-03-13 20:44:47 +02:00
title : 'Some other title' ,
} ) ) ;
const tagIds = await NoteTag . tagIdsByNoteId ( note . id ) ;
expect ( response . tags === undefined ) . toBe ( true ) ;
expect ( tagIds . length === 2 ) . toBe ( true ) ;
expect ( tagIds . includes ( tag1 . id ) ) . toBe ( true ) ;
expect ( tagIds . includes ( tag2 . id ) ) . toBe ( true ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should remove tags from note if tags is set to empty string when updating' , ( async ( ) = > {
2020-03-13 20:44:47 +02:00
const tag1 = await Tag . save ( { title : 'mon étiquette 1' } ) ;
const tag2 = await Tag . save ( { title : 'mon étiquette 2' } ) ;
const note = await Note . save ( {
title : 'ma note un' ,
} ) ;
2021-01-22 19:41:11 +02:00
await Tag . addNote ( tag1 . id , note . id ) ;
await Tag . addNote ( tag2 . id , note . id ) ;
2020-03-13 20:44:47 +02:00
2020-11-05 18:58:23 +02:00
const response = await api . route ( RequestMethod . PUT , ` notes/ ${ note . id } ` , null , JSON . stringify ( {
2020-03-13 20:44:47 +02:00
tags : '' ,
} ) ) ;
const tagIds = await NoteTag . tagIdsByNoteId ( note . id ) ;
expect ( response . tags === '' ) . toBe ( true ) ;
expect ( tagIds . length === 0 ) . toBe ( true ) ;
} ) ) ;
2020-11-05 18:58:23 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should paginate results' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
await createFolderForPagination ( 1 , 1001 ) ;
await createFolderForPagination ( 2 , 1002 ) ;
await createFolderForPagination ( 3 , 1003 ) ;
await createFolderForPagination ( 4 , 1004 ) ;
{
2020-11-11 13:52:47 +02:00
const baseQuery = {
2020-11-05 18:58:23 +02:00
fields : [ 'id' , 'title' , 'updated_time' ] ,
limit : 2 ,
order_dir : PaginationOrderDir.ASC ,
order_by : 'updated_time' ,
2020-11-11 13:52:47 +02:00
} ;
2020-11-05 18:58:23 +02:00
2020-11-11 13:52:47 +02:00
const r1 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery } ) ;
expect ( r1 . has_more ) . toBe ( true ) ;
2020-11-05 18:58:23 +02:00
expect ( r1 . items . length ) . toBe ( 2 ) ;
expect ( r1 . items [ 0 ] . title ) . toBe ( 'folder1' ) ;
expect ( r1 . items [ 1 ] . title ) . toBe ( 'folder2' ) ;
2020-11-11 13:52:47 +02:00
const r2 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery , page : 2 } ) ;
2020-11-05 18:58:23 +02:00
2020-11-11 13:52:47 +02:00
// The API currently doesn't check if there's effectively a
// page of data after the current one. If the number of
// returned items === limit, it sets `has_more` and the next
// result set will be empty
expect ( r1 . has_more ) . toBe ( true ) ;
2020-11-05 18:58:23 +02:00
expect ( r2 . items . length ) . toBe ( 2 ) ;
expect ( r2 . items [ 0 ] . title ) . toBe ( 'folder3' ) ;
expect ( r2 . items [ 1 ] . title ) . toBe ( 'folder4' ) ;
2020-11-11 13:52:47 +02:00
const r3 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery , page : 3 } ) ;
2020-11-05 18:58:23 +02:00
expect ( r3 . items . length ) . toBe ( 0 ) ;
2020-11-19 23:01:19 +02:00
expect ( r3 . has_more ) . toBe ( false ) ;
2020-11-05 18:58:23 +02:00
}
{
2020-11-11 13:52:47 +02:00
const baseQuery = {
2020-11-05 18:58:23 +02:00
fields : [ 'id' , 'title' , 'updated_time' ] ,
limit : 3 ,
order_dir : PaginationOrderDir.ASC ,
order_by : 'updated_time' ,
2020-11-11 13:52:47 +02:00
} ;
const r1 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery } ) ;
2020-11-05 18:58:23 +02:00
expect ( r1 . items . length ) . toBe ( 3 ) ;
expect ( r1 . items [ 0 ] . title ) . toBe ( 'folder1' ) ;
expect ( r1 . items [ 1 ] . title ) . toBe ( 'folder2' ) ;
expect ( r1 . items [ 2 ] . title ) . toBe ( 'folder3' ) ;
2020-11-11 13:52:47 +02:00
const r2 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery , page : 2 } ) ;
2020-11-05 18:58:23 +02:00
expect ( r2 . items . length ) . toBe ( 1 ) ;
expect ( r2 . items [ 0 ] . title ) . toBe ( 'folder4' ) ;
2020-11-19 23:01:19 +02:00
expect ( r2 . has_more ) . toBe ( false ) ;
2020-11-05 18:58:23 +02:00
}
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should paginate results and handle duplicate field values' , ( async ( ) = > {
2020-11-11 13:52:47 +02:00
// If, for example, ordering by updated_time, and two of the rows
// have the same updated_time, it should make sure that the sort
// order is stable and all results are correctly returned.
2020-11-05 18:58:23 +02:00
await createFolderForPagination ( 1 , 1001 ) ;
await createFolderForPagination ( 2 , 1002 ) ;
await createFolderForPagination ( 3 , 1002 ) ;
await createFolderForPagination ( 4 , 1003 ) ;
2020-11-11 13:52:47 +02:00
const baseQuery = {
2020-11-05 18:58:23 +02:00
fields : [ 'id' , 'title' , 'updated_time' ] ,
limit : 2 ,
order_dir : PaginationOrderDir.ASC ,
order_by : 'updated_time' ,
2020-11-11 13:52:47 +02:00
} ;
const r1 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery } ) ;
2020-11-05 18:58:23 +02:00
expect ( r1 . items . length ) . toBe ( 2 ) ;
expect ( r1 . items [ 0 ] . title ) . toBe ( 'folder1' ) ;
expect ( [ 'folder2' , 'folder3' ] . includes ( r1 . items [ 1 ] . title ) ) . toBe ( true ) ;
2020-11-11 13:52:47 +02:00
const r2 = await api . route ( RequestMethod . GET , 'folders' , { . . . baseQuery , page : 2 } ) ;
2020-11-05 18:58:23 +02:00
expect ( r2 . items . length ) . toBe ( 2 ) ;
expect ( r2 . items [ 0 ] . title ) . toBe ( r1 . items [ 1 ] . title === 'folder2' ? 'folder3' : 'folder2' ) ;
expect ( r2 . items [ 1 ] . title ) . toBe ( 'folder4' ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should paginate results and return the requested fields only' , ( async ( ) = > {
2020-11-09 19:17:51 +02:00
await createNoteForPagination ( 1 , 1001 ) ;
await createNoteForPagination ( 2 , 1002 ) ;
await createNoteForPagination ( 3 , 1003 ) ;
2020-11-11 13:52:47 +02:00
const baseQuery = {
2020-11-09 19:17:51 +02:00
fields : [ 'id' , 'title' , 'body' ] ,
limit : 2 ,
order_dir : PaginationOrderDir.ASC ,
order_by : 'updated_time' ,
2020-11-11 13:52:47 +02:00
} ;
2020-11-09 19:17:51 +02:00
2020-11-11 13:52:47 +02:00
const r1 = await api . route ( RequestMethod . GET , 'notes' , { . . . baseQuery } ) ;
expect ( Object . keys ( r1 . items [ 0 ] ) . sort ( ) . join ( ',' ) ) . toBe ( 'body,id,title' ) ;
2020-11-09 19:17:51 +02:00
expect ( r1 . items . length ) . toBe ( 2 ) ;
expect ( r1 . items [ 0 ] . title ) . toBe ( 'note1' ) ;
expect ( r1 . items [ 0 ] . body ) . toBe ( 'noteBody1' ) ;
expect ( r1 . items [ 1 ] . title ) . toBe ( 'note2' ) ;
expect ( r1 . items [ 1 ] . body ) . toBe ( 'noteBody2' ) ;
2020-11-11 13:52:47 +02:00
const r2 = await api . route ( RequestMethod . GET , 'notes' , { . . . baseQuery , fields : [ 'id' ] , page : 2 } ) ;
2020-11-09 19:17:51 +02:00
2020-11-11 13:52:47 +02:00
expect ( Object . keys ( r2 . items [ 0 ] ) . sort ( ) . join ( ',' ) ) . toBe ( 'id' ) ;
2020-11-09 19:17:51 +02:00
expect ( r2 . items . length ) . toBe ( 1 ) ;
2020-11-11 13:52:47 +02:00
expect ( ! ! r2 . items [ 0 ] . id ) . toBe ( true ) ;
2020-11-09 19:17:51 +02:00
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should paginate folder notes' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const folder = await Folder . save ( { } ) ;
const note1 = await Note . save ( { parent_id : folder.id } ) ;
await msleep ( 1 ) ;
const note2 = await Note . save ( { parent_id : folder.id } ) ;
await msleep ( 1 ) ;
const note3 = await Note . save ( { parent_id : folder.id } ) ;
const r1 = await api . route ( RequestMethod . GET , ` folders/ ${ folder . id } /notes ` , {
limit : 2 ,
} ) ;
expect ( r1 . items . length ) . toBe ( 2 ) ;
expect ( r1 . items [ 0 ] . id ) . toBe ( note1 . id ) ;
expect ( r1 . items [ 1 ] . id ) . toBe ( note2 . id ) ;
const r2 = await api . route ( RequestMethod . GET , ` folders/ ${ folder . id } /notes ` , {
2020-11-11 13:52:47 +02:00
limit : 2 ,
page : 2 ,
2020-11-05 18:58:23 +02:00
} ) ;
expect ( r2 . items . length ) . toBe ( 1 ) ;
expect ( r2 . items [ 0 ] . id ) . toBe ( note3 . id ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should sort search paginated results' , ( async ( ) = > {
2020-11-17 11:53:50 +02:00
SearchEngine . instance ( ) . setDb ( db ( ) ) ;
await createNoteForPagination ( 'note c' , 1000 ) ;
await createNoteForPagination ( 'note e' , 1001 ) ;
await createNoteForPagination ( 'note b' , 1002 ) ;
await createNoteForPagination ( 'note a' , 1003 ) ;
await createNoteForPagination ( 'note d' , 1004 ) ;
await SearchEngine . instance ( ) . syncTables ( ) ;
{
const baseQuery = {
query : 'note' ,
fields : [ 'id' , 'title' , 'updated_time' ] ,
limit : 3 ,
order_dir : PaginationOrderDir.ASC ,
order_by : 'updated_time' ,
} ;
const r1 = await api . route ( RequestMethod . GET , 'search' , baseQuery ) ;
expect ( r1 . items [ 0 ] . updated_time ) . toBe ( 1000 ) ;
expect ( r1 . items [ 1 ] . updated_time ) . toBe ( 1001 ) ;
expect ( r1 . items [ 2 ] . updated_time ) . toBe ( 1002 ) ;
const r2 = await api . route ( RequestMethod . GET , 'search' , { . . . baseQuery , page : 2 } ) ;
expect ( r2 . items [ 0 ] . updated_time ) . toBe ( 1003 ) ;
expect ( r2 . items [ 1 ] . updated_time ) . toBe ( 1004 ) ;
}
{
const baseQuery = {
query : 'note' ,
fields : [ 'id' , 'title' , 'updated_time' ] ,
limit : 2 ,
order_dir : PaginationOrderDir.DESC ,
order_by : 'title' ,
} ;
const r1 = await api . route ( RequestMethod . GET , 'search' , baseQuery ) ;
expect ( r1 . items [ 0 ] . title ) . toBe ( 'note e' ) ;
expect ( r1 . items [ 1 ] . title ) . toBe ( 'note d' ) ;
const r2 = await api . route ( RequestMethod . GET , 'search' , { . . . baseQuery , page : 2 } ) ;
expect ( r2 . items [ 0 ] . title ) . toBe ( 'note c' ) ;
expect ( r2 . items [ 1 ] . title ) . toBe ( 'note b' ) ;
const r3 = await api . route ( RequestMethod . GET , 'search' , { . . . baseQuery , page : 3 } ) ;
expect ( r3 . items [ 0 ] . title ) . toBe ( 'note a' ) ;
}
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should return default fields' , ( async ( ) = > {
2020-11-05 18:58:23 +02:00
const folder = await Folder . save ( { title : 'folder' } ) ;
const note1 = await Note . save ( { title : 'note1' , parent_id : folder.id } ) ;
await Note . save ( { title : 'note2' , parent_id : folder.id } ) ;
const tag = await Tag . save ( { title : 'tag' } ) ;
await Tag . addNote ( tag . id , note1 . id ) ;
{
const r = await api . route ( RequestMethod . GET , ` folders/ ${ folder . id } ` ) ;
expect ( 'id' in r ) . toBe ( true ) ;
expect ( 'title' in r ) . toBe ( true ) ;
expect ( 'parent_id' in r ) . toBe ( true ) ;
}
{
const r = await api . route ( RequestMethod . GET , ` folders/ ${ folder . id } /notes ` ) ;
expect ( 'id' in r . items [ 0 ] ) . toBe ( true ) ;
expect ( 'title' in r . items [ 0 ] ) . toBe ( true ) ;
expect ( 'parent_id' in r . items [ 0 ] ) . toBe ( true ) ;
}
{
const r = await api . route ( RequestMethod . GET , 'notes' ) ;
expect ( 'id' in r . items [ 0 ] ) . toBe ( true ) ;
expect ( 'title' in r . items [ 0 ] ) . toBe ( true ) ;
expect ( 'parent_id' in r . items [ 0 ] ) . toBe ( true ) ;
}
{
const r = await api . route ( RequestMethod . GET , ` notes/ ${ note1 . id } /tags ` ) ;
expect ( 'id' in r . items [ 0 ] ) . toBe ( true ) ;
expect ( 'title' in r . items [ 0 ] ) . toBe ( true ) ;
}
{
const r = await api . route ( RequestMethod . GET , ` tags/ ${ tag . id } ` ) ;
expect ( 'id' in r ) . toBe ( true ) ;
expect ( 'title' in r ) . toBe ( true ) ;
}
} ) ) ;
2020-11-07 18:45:02 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should return the notes associated with a resource' , ( async ( ) = > {
2020-11-07 18:45:02 +02:00
const note = await Note . save ( { } ) ;
2021-05-21 15:17:21 +02:00
await shim . attachFileToNote ( note , ` ${ supportDir } /photo.jpg ` ) ;
2020-11-07 18:45:02 +02:00
const resource = ( await Resource . all ( ) ) [ 0 ] ;
const resourceService = new ResourceService ( ) ;
await resourceService . indexNoteResources ( ) ;
const r = await api . route ( RequestMethod . GET , ` resources/ ${ resource . id } /notes ` ) ;
expect ( r . items . length ) . toBe ( 1 ) ;
2020-11-13 23:45:25 +02:00
expect ( r . items [ 0 ] . id ) . toBe ( note . id ) ;
} ) ) ;
2020-12-01 20:05:24 +02:00
it ( 'should return the resources associated with a note' , ( async ( ) = > {
2020-11-13 23:45:25 +02:00
const note = await Note . save ( { } ) ;
2021-05-21 15:17:21 +02:00
await shim . attachFileToNote ( note , ` ${ supportDir } /photo.jpg ` ) ;
2020-11-13 23:45:25 +02:00
const resource = ( await Resource . all ( ) ) [ 0 ] ;
const r = await api . route ( RequestMethod . GET , ` notes/ ${ note . id } /resources ` ) ;
expect ( r . items . length ) . toBe ( 1 ) ;
expect ( r . items [ 0 ] . id ) . toBe ( resource . id ) ;
2020-11-07 18:45:02 +02:00
} ) ) ;
2020-11-11 13:52:47 +02:00
2020-12-01 20:05:24 +02:00
it ( 'should return search results' , ( async ( ) = > {
2020-11-11 13:52:47 +02:00
SearchEngine . instance ( ) . setDb ( db ( ) ) ;
for ( let i = 0 ; i < 10 ; i ++ ) {
await Note . save ( { title : 'a' } ) ;
}
await SearchEngine . instance ( ) . syncTables ( ) ;
// Mostly testing pagination below
const r1 = await api . route ( RequestMethod . GET , 'search' , { query : 'a' , limit : 4 } ) ;
expect ( r1 . items . length ) . toBe ( 4 ) ;
expect ( r1 . has_more ) . toBe ( true ) ;
const r2 = await api . route ( RequestMethod . GET , 'search' , { query : 'a' , limit : 4 , page : 2 } ) ;
expect ( r2 . items . length ) . toBe ( 4 ) ;
expect ( r2 . has_more ) . toBe ( true ) ;
const r3 = await api . route ( RequestMethod . GET , 'search' , { query : 'a' , limit : 4 , page : 3 } ) ;
expect ( r3 . items . length ) . toBe ( 2 ) ;
expect ( ! ! r3 . has_more ) . toBe ( false ) ;
await SearchEngine . instance ( ) . destroy ( ) ;
} ) ) ;
2019-06-28 14:46:55 +02:00
} ) ;