mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	etapi test infrastructure plus a basic note creation test
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -11,5 +11,6 @@ cert.crt | ||||
| server-package.json | ||||
| .idea/httpRequests/ | ||||
| data/ | ||||
| data-test/ | ||||
| tmp/ | ||||
| .eslintcache | ||||
							
								
								
									
										18
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										18
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,12 +1,12 @@ | ||||
| { | ||||
|   "name": "trilium", | ||||
|   "version": "0.61.8-beta", | ||||
|   "version": "0.61.10-beta", | ||||
|   "lockfileVersion": 2, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "trilium", | ||||
|       "version": "0.61.8-beta", | ||||
|       "version": "0.61.10-beta", | ||||
|       "hasInstallScript": true, | ||||
|       "license": "AGPL-3.0-only", | ||||
|       "dependencies": { | ||||
| @@ -68,6 +68,7 @@ | ||||
|         "stream-throttle": "0.1.3", | ||||
|         "striptags": "3.2.0", | ||||
|         "tmp": "0.2.1", | ||||
|         "tree-kill": "^1.2.2", | ||||
|         "turndown": "7.1.2", | ||||
|         "unescape": "1.0.1", | ||||
|         "ws": "8.14.2", | ||||
| @@ -12630,6 +12631,14 @@ | ||||
|         "node": ">=14" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/tree-kill": { | ||||
|       "version": "1.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", | ||||
|       "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", | ||||
|       "bin": { | ||||
|         "tree-kill": "cli.js" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/trim-repeated": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", | ||||
| @@ -23061,6 +23070,11 @@ | ||||
|         "punycode": "^2.3.0" | ||||
|       } | ||||
|     }, | ||||
|     "tree-kill": { | ||||
|       "version": "1.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", | ||||
|       "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" | ||||
|     }, | ||||
|     "trim-repeated": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", | ||||
|   | ||||
| @@ -19,13 +19,14 @@ | ||||
|     "start-electron": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .", | ||||
|     "start-electron-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .", | ||||
|     "qstart-electron": "rm -r ./node_modules/better-sqlite3/bin ; mkdir -p ./node_modules/better-sqlite3/build ; cp ./bin/better-sqlite3/linux-desktop-better_sqlite3.node ./node_modules/better-sqlite3/build/better_sqlite3.node && TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .", | ||||
|     "start-test-server": "rm -rf ./data-test; cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data-test TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev TRILIUM_PORT=9999 node ./src/www", | ||||
|     "switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install", | ||||
|     "switch-electron": "./node_modules/.bin/electron-rebuild", | ||||
|     "build-backend-docs": "rm -rf ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js", | ||||
|     "build-frontend-docs": "rm -rf ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js", | ||||
|     "build-docs": "npm run build-backend-docs && npm run build-frontend-docs", | ||||
|     "webpack": "webpack -c webpack.config.js", | ||||
|     "test-jasmine": "jasmine", | ||||
|     "test-jasmine": "TRILIUM_DATA_DIR=~/trilium/data-test jasmine", | ||||
|     "test-es6": "node -r esm spec-es6/attribute_parser.spec.js ", | ||||
|     "test": "npm run test-jasmine && npm run test-es6", | ||||
|     "postinstall": "rimraf ./node_modules/canvas", | ||||
| @@ -91,6 +92,7 @@ | ||||
|     "stream-throttle": "0.1.3", | ||||
|     "striptags": "3.2.0", | ||||
|     "tmp": "0.2.1", | ||||
|     "tree-kill": "^1.2.2", | ||||
|     "turndown": "7.1.2", | ||||
|     "unescape": "1.0.1", | ||||
|     "ws": "8.14.2", | ||||
|   | ||||
							
								
								
									
										27
									
								
								spec/etapi/notes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								spec/etapi/notes.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| const {describeEtapi, postEtapi, getEtapi, getEtapiContent} = require("../support/etapi"); | ||||
|  | ||||
| describeEtapi("notes", () => { | ||||
|     it("create", async () => { | ||||
|         const {note, branch} = await postEtapi('create-note', { | ||||
|             parentNoteId: 'root', | ||||
|             type: 'text', | ||||
|             title: 'Hello World!', | ||||
|             content: 'Content', | ||||
|             prefix: 'Custom prefix' | ||||
|         }); | ||||
|  | ||||
|         expect(note.title).toEqual("Hello World!"); | ||||
|         expect(branch.parentNoteId).toEqual("root"); | ||||
|         expect(branch.prefix).toEqual("Custom prefix"); | ||||
|  | ||||
|         const rNote = await getEtapi(`notes/${note.noteId}`); | ||||
|         expect(rNote.title).toEqual("Hello World!"); | ||||
|  | ||||
|         const rContent = await getEtapiContent(`notes/${note.noteId}/content`); | ||||
|         expect(rContent).toEqual("Content"); | ||||
|  | ||||
|         const rBranch = await getEtapi(`branches/${branch.branchId}`); | ||||
|         expect(rBranch.parentNoteId).toEqual("root"); | ||||
|         expect(rBranch.prefix).toEqual("Custom prefix"); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										125
									
								
								spec/support/etapi.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								spec/support/etapi.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| const {spawn} = require("child_process"); | ||||
| const kill  = require('tree-kill'); | ||||
|  | ||||
| let etapiAuthToken; | ||||
|  | ||||
| const getEtapiAuthorizationHeader = () => "Basic " + Buffer.from(`etapi:${etapiAuthToken}`).toString('base64'); | ||||
|  | ||||
| const PORT = '9999'; | ||||
| const HOST = 'http://localhost:' + PORT; | ||||
|  | ||||
| function describeEtapi(description, specDefinitions) { | ||||
|     describe(description, () => { | ||||
|         let appProcess; | ||||
|  | ||||
|         beforeAll(async () => { | ||||
|             appProcess = spawn('npm', ['run', 'start-test-server']); | ||||
|  | ||||
|             await new Promise(res => { | ||||
|                 appProcess.stdout.on('data', data => { | ||||
|                     console.log("Trilium: " + data.toString().trim()); | ||||
|  | ||||
|                     if (data.toString().includes('Listening on port')) { | ||||
|                         res(); | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             await fetch(HOST + '/api/setup/new-document', { method: 'POST' }); | ||||
|  | ||||
|             const formData = new URLSearchParams(); | ||||
|             formData.append('password1', '1234'); | ||||
|             formData.append('password2', '1234'); | ||||
|  | ||||
|             await fetch(HOST + '/set-password', { method: 'POST', body: formData }); | ||||
|  | ||||
|             etapiAuthToken = (await (await fetch(HOST + '/etapi/auth/login', { | ||||
|                 method: 'POST', | ||||
|                 headers: { | ||||
|                     "Content-Type": "application/json", | ||||
|                 }, | ||||
|                 body: JSON.stringify({ password: '1234' }) | ||||
|             })).json()).authToken; | ||||
|         }); | ||||
|  | ||||
|         afterAll(() => { | ||||
|             console.log("Attempting to kill the Trilium process as part of the cleanup..."); | ||||
|             kill(appProcess.pid, 'SIGKILL', () => { console.log("Trilium process killed.") }); | ||||
|         }); | ||||
|  | ||||
|         specDefinitions(); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| async function getEtapi(url) { | ||||
|     const response = await fetch(`${HOST}/etapi/${url}`, { | ||||
|         method: 'GET', | ||||
|         headers: { | ||||
|             Authorization: getEtapiAuthorizationHeader() | ||||
|         } | ||||
|     }); | ||||
|     return await processEtapiResponse(response); | ||||
| } | ||||
|  | ||||
| async function getEtapiContent(url) { | ||||
|     const response = await fetch(`${HOST}/etapi/${url}`, { | ||||
|         method: 'GET', | ||||
|         headers: { | ||||
|             Authorization: getEtapiAuthorizationHeader() | ||||
|         } | ||||
|     }); | ||||
|     return await response.text(); | ||||
| } | ||||
|  | ||||
| async function postEtapi(url, data = {}) { | ||||
|     const response = await fetch(`${HOST}/etapi/${url}`, { | ||||
|         method: 'POST', | ||||
|         headers: { | ||||
|             "Content-Type": "application/json", | ||||
|             Authorization: getEtapiAuthorizationHeader() | ||||
|         }, | ||||
|         body: JSON.stringify(data) | ||||
|     }); | ||||
|     return await processEtapiResponse(response); | ||||
| } | ||||
|  | ||||
| async function putEtapi(url, data = {}) { | ||||
|     const response = await fetch(`${HOST}/etapi/${url}`, { | ||||
|         method: 'PUT', | ||||
|         headers: { | ||||
|             "Content-Type": "application/json", | ||||
|             Authorization: getEtapiAuthorizationHeader() | ||||
|         }, | ||||
|         body: JSON.stringify(data) | ||||
|     }); | ||||
|     return await processEtapiResponse(response); | ||||
| } | ||||
|  | ||||
| async function deleteEtapi(url) { | ||||
|     const response = await fetch(`${HOST}/etapi/${url}`, { | ||||
|         method: 'DELETE', | ||||
|         headers: { | ||||
|             Authorization: getEtapiAuthorizationHeader() | ||||
|         } | ||||
|     }); | ||||
|     return await processEtapiResponse(response); | ||||
| } | ||||
|  | ||||
| async function processEtapiResponse(response) { | ||||
|     const json = await response.json(); | ||||
|  | ||||
|     if (response.status < 200 || response.status >= 300) { | ||||
|         throw new Error("ETAPI error: " + JSON.stringify(json)); | ||||
|     } | ||||
|  | ||||
|     return json; | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     describeEtapi, | ||||
|     getEtapi, | ||||
|     getEtapiContent, | ||||
|     postEtapi, | ||||
|     putEtapi, | ||||
|     deleteEtapi | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user