mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop, Cli: Resolves #3884: Allow setting note geolocation attributes via API
This commit is contained in:
parent
dc51781976
commit
fa7bd2cfab
@ -68,6 +68,7 @@ CliClient/tests/models_Setting.js
|
|||||||
CliClient/tests/services_CommandService.js
|
CliClient/tests/services_CommandService.js
|
||||||
CliClient/tests/services_InteropService.js
|
CliClient/tests/services_InteropService.js
|
||||||
CliClient/tests/services_PluginService.js
|
CliClient/tests/services_PluginService.js
|
||||||
|
CliClient/tests/services_rest_Api.js
|
||||||
CliClient/tests/services/plugins/sandboxProxy.js
|
CliClient/tests/services/plugins/sandboxProxy.js
|
||||||
CliClient/tests/synchronizer_LockHandler.js
|
CliClient/tests/synchronizer_LockHandler.js
|
||||||
CliClient/tests/synchronizer_MigrationHandler.js
|
CliClient/tests/synchronizer_MigrationHandler.js
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -62,6 +62,7 @@ CliClient/tests/models_Setting.js
|
|||||||
CliClient/tests/services_CommandService.js
|
CliClient/tests/services_CommandService.js
|
||||||
CliClient/tests/services_InteropService.js
|
CliClient/tests/services_InteropService.js
|
||||||
CliClient/tests/services_PluginService.js
|
CliClient/tests/services_PluginService.js
|
||||||
|
CliClient/tests/services_rest_Api.js
|
||||||
CliClient/tests/services/plugins/sandboxProxy.js
|
CliClient/tests/services/plugins/sandboxProxy.js
|
||||||
CliClient/tests/synchronizer_LockHandler.js
|
CliClient/tests/synchronizer_LockHandler.js
|
||||||
CliClient/tests/synchronizer_MigrationHandler.js
|
CliClient/tests/synchronizer_MigrationHandler.js
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
import Api from 'lib/services/rest/Api';
|
||||||
|
import shim from 'lib/shim';
|
||||||
require('app-module-path').addPath(__dirname);
|
|
||||||
|
|
||||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('test-utils.js');
|
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('test-utils.js');
|
||||||
const Api = require('lib/services/rest/Api').default;
|
|
||||||
const Folder = require('lib/models/Folder');
|
const Folder = require('lib/models/Folder');
|
||||||
const Resource = require('lib/models/Resource');
|
const Resource = require('lib/models/Resource');
|
||||||
const Note = require('lib/models/Note');
|
const Note = require('lib/models/Note');
|
||||||
const Tag = require('lib/models/Tag');
|
const Tag = require('lib/models/Tag');
|
||||||
const NoteTag = require('lib/models/NoteTag');
|
const NoteTag = require('lib/models/NoteTag');
|
||||||
const shim = require('lib/shim').default;
|
|
||||||
|
|
||||||
process.on('unhandledRejection', (reason, p) => {
|
process.on('unhandledRejection', (reason, p) => {
|
||||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
let api = null;
|
let api:Api = null;
|
||||||
|
|
||||||
describe('services_rest_Api', function() {
|
describe('services_rest_Api', function() {
|
||||||
|
|
||||||
@ -28,21 +25,23 @@ describe('services_rest_Api', function() {
|
|||||||
|
|
||||||
it('should ping', asyncTest(async () => {
|
it('should ping', asyncTest(async () => {
|
||||||
const response = await api.route('GET', 'ping');
|
const response = await api.route('GET', 'ping');
|
||||||
|
expect(response).toBe('JoplinClipperServer');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should handle Not Found errors', asyncTest(async () => {
|
it('should handle Not Found errors', asyncTest(async () => {
|
||||||
const hasThrown = await checkThrowAsync(async () => await api.route('GET', 'pong'));
|
const hasThrown = await checkThrowAsync(async () => await api.route('GET', 'pong'));
|
||||||
|
expect(hasThrown).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should get folders', asyncTest(async () => {
|
it('should get folders', asyncTest(async () => {
|
||||||
const f1 = await Folder.save({ title: 'mon carnet' });
|
await Folder.save({ title: 'mon carnet' });
|
||||||
const response = await api.route('GET', 'folders');
|
const response = await api.route('GET', 'folders');
|
||||||
expect(response.length).toBe(1);
|
expect(response.length).toBe(1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should update folders', asyncTest(async () => {
|
it('should update folders', asyncTest(async () => {
|
||||||
const f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
const response = await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({
|
await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({
|
||||||
title: 'modifié',
|
title: 'modifié',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -84,8 +83,8 @@ describe('services_rest_Api', function() {
|
|||||||
const response2 = await api.route('GET', `folders/${f1.id}/notes`);
|
const response2 = await api.route('GET', `folders/${f1.id}/notes`);
|
||||||
expect(response2.length).toBe(0);
|
expect(response2.length).toBe(0);
|
||||||
|
|
||||||
const n1 = await Note.save({ title: 'un', parent_id: f1.id });
|
await Note.save({ title: 'un', parent_id: f1.id });
|
||||||
const n2 = await Note.save({ title: 'deux', parent_id: f1.id });
|
await Note.save({ title: 'deux', parent_id: f1.id });
|
||||||
const response = await api.route('GET', `folders/${f1.id}/notes`);
|
const response = await api.route('GET', `folders/${f1.id}/notes`);
|
||||||
expect(response.length).toBe(2);
|
expect(response.length).toBe(2);
|
||||||
}));
|
}));
|
||||||
@ -100,7 +99,7 @@ describe('services_rest_Api', function() {
|
|||||||
const f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
const f2 = await Folder.save({ title: 'mon deuxième carnet' });
|
const f2 = await Folder.save({ title: 'mon deuxième carnet' });
|
||||||
const n1 = await Note.save({ title: 'un', parent_id: f1.id });
|
const n1 = await Note.save({ title: 'un', parent_id: f1.id });
|
||||||
const n2 = await Note.save({ title: 'deux', parent_id: f1.id });
|
await Note.save({ title: 'deux', parent_id: f1.id });
|
||||||
const n3 = await Note.save({ title: 'trois', parent_id: f2.id });
|
const n3 = await Note.save({ title: 'trois', parent_id: f2.id });
|
||||||
|
|
||||||
response = await api.route('GET', 'notes');
|
response = await api.route('GET', 'notes');
|
||||||
@ -134,6 +133,41 @@ describe('services_rest_Api', function() {
|
|||||||
expect(!!response.id).toBe(true);
|
expect(!!response.id).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should allow setting note properties', asyncTest(async () => {
|
||||||
|
let response:any = null;
|
||||||
|
const f = await Folder.save({ title: 'mon carnet' });
|
||||||
|
|
||||||
|
response = await api.route('POST', 'notes', null, JSON.stringify({
|
||||||
|
title: 'testing',
|
||||||
|
parent_id: f.id,
|
||||||
|
latitude: '48.732071',
|
||||||
|
longitude: '-3.458700',
|
||||||
|
altitude: '21',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const noteId = response.id;
|
||||||
|
|
||||||
|
{
|
||||||
|
const note = await Note.load(noteId);
|
||||||
|
expect(note.latitude).toBe('48.73207100');
|
||||||
|
expect(note.longitude).toBe('-3.45870000');
|
||||||
|
expect(note.altitude).toBe('21.0000');
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.route('PUT', 'notes/' + noteId, null, JSON.stringify({
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
it('should preserve user timestamps when creating notes', asyncTest(async () => {
|
it('should preserve user timestamps when creating notes', asyncTest(async () => {
|
||||||
let response = null;
|
let response = null;
|
||||||
const f = await Folder.save({ title: 'mon carnet' });
|
const f = await Folder.save({ title: 'mon carnet' });
|
||||||
@ -221,10 +255,9 @@ describe('services_rest_Api', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete resources', asyncTest(async () => {
|
it('should delete resources', asyncTest(async () => {
|
||||||
let response = null;
|
|
||||||
const f = await Folder.save({ title: 'mon carnet' });
|
const f = await Folder.save({ title: 'mon carnet' });
|
||||||
|
|
||||||
response = await api.route('POST', 'notes', null, JSON.stringify({
|
await api.route('POST', 'notes', null, JSON.stringify({
|
||||||
title: 'testing image',
|
title: 'testing image',
|
||||||
parent_id: f.id,
|
parent_id: f.id,
|
||||||
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=',
|
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=',
|
||||||
@ -286,7 +319,7 @@ describe('services_rest_Api', function() {
|
|||||||
const tag = await Tag.save({ title: 'mon étiquette' });
|
const tag = await Tag.save({ title: 'mon étiquette' });
|
||||||
const note = await Note.save({ title: 'ma note' });
|
const note = await Note.save({ title: 'ma note' });
|
||||||
|
|
||||||
const response = await api.route('POST', `tags/${tag.id}/notes`, null, JSON.stringify({
|
await api.route('POST', `tags/${tag.id}/notes`, null, JSON.stringify({
|
||||||
id: note.id,
|
id: note.id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -299,7 +332,7 @@ describe('services_rest_Api', function() {
|
|||||||
const note = await Note.save({ title: 'ma note' });
|
const note = await Note.save({ title: 'ma note' });
|
||||||
await Tag.addNote(tag.id, note.id);
|
await Tag.addNote(tag.id, note.id);
|
||||||
|
|
||||||
const response = await api.route('DELETE', `tags/${tag.id}/notes/${note.id}`);
|
await api.route('DELETE', `tags/${tag.id}/notes/${note.id}`);
|
||||||
|
|
||||||
const noteIds = await Tag.noteIds(tag.id);
|
const noteIds = await Tag.noteIds(tag.id);
|
||||||
expect(noteIds.length).toBe(0);
|
expect(noteIds.length).toBe(0);
|
@ -58,7 +58,8 @@ export default class Api {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async route(method:string, path:string, query:any = null, body:any = null, files:string[] = null) {
|
// Response can be any valid JSON object, so a string, and array or an object (key/value pairs).
|
||||||
|
async route(method:string, path:string, query:any = null, body:any = null, files:string[] = null):Promise<any> {
|
||||||
if (!files) files = [];
|
if (!files) files = [];
|
||||||
if (!query) query = {};
|
if (!query) query = {};
|
||||||
|
|
||||||
@ -548,6 +549,9 @@ export default class Api {
|
|||||||
if ('user_created_time' in requestNote) output.user_created_time = Database.formatValue(Database.TYPE_INT, requestNote.user_created_time);
|
if ('user_created_time' in requestNote) output.user_created_time = Database.formatValue(Database.TYPE_INT, requestNote.user_created_time);
|
||||||
if ('is_todo' in requestNote) output.is_todo = Database.formatValue(Database.TYPE_INT, requestNote.is_todo);
|
if ('is_todo' in requestNote) output.is_todo = Database.formatValue(Database.TYPE_INT, requestNote.is_todo);
|
||||||
if ('markup_language' in requestNote) output.markup_language = Database.formatValue(Database.TYPE_INT, requestNote.markup_language);
|
if ('markup_language' in requestNote) output.markup_language = Database.formatValue(Database.TYPE_INT, requestNote.markup_language);
|
||||||
|
if ('longitude' in requestNote) output.longitude = requestNote.longitude;
|
||||||
|
if ('latitude' in requestNote) output.latitude = requestNote.latitude;
|
||||||
|
if ('altitude' in requestNote) output.altitude = requestNote.altitude;
|
||||||
|
|
||||||
if (!output.markup_language) output.markup_language = MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN;
|
if (!output.markup_language) output.markup_language = MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN;
|
||||||
|
|
||||||
|
@ -696,7 +696,8 @@
|
|||||||
"ReactNativeClient/lib/errorUtils.js": true,
|
"ReactNativeClient/lib/errorUtils.js": true,
|
||||||
"ReactNativeClient/lib/markdownUtils.js": true,
|
"ReactNativeClient/lib/markdownUtils.js": true,
|
||||||
"ReactNativeClient/lib/services/plugins/api/types.js": true,
|
"ReactNativeClient/lib/services/plugins/api/types.js": true,
|
||||||
"ReactNativeClient/lib/services/rest/Api.js": true
|
"ReactNativeClient/lib/services/rest/Api.js": true,
|
||||||
|
"CliClient/tests/services_rest_Api.js": true
|
||||||
},
|
},
|
||||||
"spellright.language": [
|
"spellright.language": [
|
||||||
"en"
|
"en"
|
||||||
|
Loading…
Reference in New Issue
Block a user