You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-11-23 22:36:32 +02:00
Chore: Cli: Fix CLI app integration tests (#13089)
This commit is contained in:
@@ -96,6 +96,7 @@ packages/onenote-converter/pkg/onenote_converter.js
|
|||||||
packages/app-cli/app/LinkSelector.js
|
packages/app-cli/app/LinkSelector.js
|
||||||
packages/app-cli/app/app.js
|
packages/app-cli/app/app.js
|
||||||
packages/app-cli/app/base-command.js
|
packages/app-cli/app/base-command.js
|
||||||
|
packages/app-cli/app/cli-integration-tests.js
|
||||||
packages/app-cli/app/command-apidoc.js
|
packages/app-cli/app/command-apidoc.js
|
||||||
packages/app-cli/app/command-attach.js
|
packages/app-cli/app/command-attach.js
|
||||||
packages/app-cli/app/command-batch.js
|
packages/app-cli/app/command-batch.js
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -69,6 +69,7 @@ docs/**/*.mustache
|
|||||||
packages/app-cli/app/LinkSelector.js
|
packages/app-cli/app/LinkSelector.js
|
||||||
packages/app-cli/app/app.js
|
packages/app-cli/app/app.js
|
||||||
packages/app-cli/app/base-command.js
|
packages/app-cli/app/base-command.js
|
||||||
|
packages/app-cli/app/cli-integration-tests.js
|
||||||
packages/app-cli/app/command-apidoc.js
|
packages/app-cli/app/command-apidoc.js
|
||||||
packages/app-cli/app/command-attach.js
|
packages/app-cli/app/command-attach.js
|
||||||
packages/app-cli/app/command-batch.js
|
packages/app-cli/app/command-batch.js
|
||||||
|
|||||||
@@ -2,33 +2,44 @@
|
|||||||
|
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
import * as fs from 'fs-extra';
|
||||||
const Logger = require('@joplin/utils/Logger').default;
|
import Logger, { TargetType } from '@joplin/utils/Logger';
|
||||||
const { dirname } = require('@joplin/lib/path-utils');
|
import { dirname } from '@joplin/lib/path-utils';
|
||||||
const { DatabaseDriverNode } = require('@joplin/lib/database-driver-node.js');
|
const { DatabaseDriverNode } = require('@joplin/lib/database-driver-node.js');
|
||||||
const JoplinDatabase = require('@joplin/lib/JoplinDatabase').default;
|
import JoplinDatabase from '@joplin/lib/JoplinDatabase';
|
||||||
const BaseModel = require('@joplin/lib/BaseModel').default;
|
import BaseModel from '@joplin/lib/BaseModel';
|
||||||
const Folder = require('@joplin/lib/models/Folder').default;
|
import Folder from '@joplin/lib/models/Folder';
|
||||||
const Note = require('@joplin/lib/models/Note').default;
|
import Note from '@joplin/lib/models/Note';
|
||||||
const Setting = require('@joplin/lib/models/Setting').default;
|
import Setting from '@joplin/lib/models/Setting';
|
||||||
const { sprintf } = require('sprintf-js');
|
const { sprintf } = require('sprintf-js');
|
||||||
const exec = require('child_process').exec;
|
const exec = require('child_process').exec;
|
||||||
|
const nodeSqlite = require('sqlite3');
|
||||||
|
const { loadKeychainServiceAndSettings } = require('@joplin/lib/services/SettingUtils');
|
||||||
|
const { default: shimInitCli } = require('./utils/shimInitCli');
|
||||||
|
|
||||||
const baseDir = `${dirname(__dirname)}/tests/cli-integration`;
|
const baseDir = `${dirname(__dirname)}/tests/cli-integration`;
|
||||||
const joplinAppPath = `${__dirname}/main.js`;
|
const joplinAppPath = `${__dirname}/main.js`;
|
||||||
|
|
||||||
|
shimInitCli({ nodeSqlite, appVersion: () => require('../package.json').version, keytar: null });
|
||||||
|
require('@joplin/lib/testing/test-utils');
|
||||||
|
|
||||||
const logger = new Logger();
|
const logger = new Logger();
|
||||||
logger.addTarget('console');
|
logger.addTarget(TargetType.Console);
|
||||||
logger.setLevel(Logger.LEVEL_ERROR);
|
logger.setLevel(Logger.LEVEL_ERROR);
|
||||||
|
|
||||||
const dbLogger = new Logger();
|
const dbLogger = new Logger();
|
||||||
dbLogger.addTarget('console');
|
dbLogger.addTarget(TargetType.Console);
|
||||||
dbLogger.setLevel(Logger.LEVEL_INFO);
|
dbLogger.setLevel(Logger.LEVEL_INFO);
|
||||||
|
|
||||||
const db = new JoplinDatabase(new DatabaseDriverNode());
|
const db = new JoplinDatabase(new DatabaseDriverNode());
|
||||||
db.setLogger(dbLogger);
|
db.setLogger(dbLogger);
|
||||||
|
|
||||||
function createClient(id) {
|
interface Client {
|
||||||
|
id: number;
|
||||||
|
profileDir: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createClient(id: number): Client {
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
profileDir: `${baseDir}/client${id}`,
|
profileDir: `${baseDir}/client${id}`,
|
||||||
@@ -37,13 +48,13 @@ function createClient(id) {
|
|||||||
|
|
||||||
const client = createClient(1);
|
const client = createClient(1);
|
||||||
|
|
||||||
function execCommand(client, command) {
|
function execCommand(client: Client, command: string) {
|
||||||
const exePath = `node ${joplinAppPath}`;
|
const exePath = `node ${joplinAppPath}`;
|
||||||
const cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
|
const cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
|
||||||
logger.info(`${client.id}: ${command}`);
|
logger.info(`${client.id}: ${command}`);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
exec(cmd, (error, stdout, stderr) => {
|
exec(cmd, (error: string, stdout: string, stderr: string) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error(stderr);
|
logger.error(stderr);
|
||||||
reject(error);
|
reject(error);
|
||||||
@@ -54,17 +65,17 @@ function execCommand(client, command) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertTrue(v) {
|
function assertTrue(v: unknown) {
|
||||||
if (!v) throw new Error(sprintf('Expected "true", got "%s"."', v));
|
if (!v) throw new Error(sprintf('Expected "true", got "%s"."', v));
|
||||||
process.stdout.write('.');
|
process.stdout.write('.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertFalse(v) {
|
function assertFalse(v: unknown) {
|
||||||
if (v) throw new Error(sprintf('Expected "false", got "%s"."', v));
|
if (v) throw new Error(sprintf('Expected "false", got "%s"."', v));
|
||||||
process.stdout.write('.');
|
process.stdout.write('.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertEquals(expected, real) {
|
function assertEquals(expected: unknown, real: unknown) {
|
||||||
if (expected !== real) throw new Error(sprintf('Expecting "%s", got "%s"', expected, real));
|
if (expected !== real) throw new Error(sprintf('Expecting "%s", got "%s"', expected, real));
|
||||||
process.stdout.write('.');
|
process.stdout.write('.');
|
||||||
}
|
}
|
||||||
@@ -73,7 +84,7 @@ async function clearDatabase() {
|
|||||||
await db.transactionExecBatch(['DELETE FROM folders', 'DELETE FROM notes', 'DELETE FROM tags', 'DELETE FROM note_tags', 'DELETE FROM resources', 'DELETE FROM deleted_items']);
|
await db.transactionExecBatch(['DELETE FROM folders', 'DELETE FROM notes', 'DELETE FROM tags', 'DELETE FROM note_tags', 'DELETE FROM resources', 'DELETE FROM deleted_items']);
|
||||||
}
|
}
|
||||||
|
|
||||||
const testUnits = {};
|
const testUnits: Record<string, ()=> Promise<void>> = {};
|
||||||
|
|
||||||
testUnits.testFolders = async () => {
|
testUnits.testFolders = async () => {
|
||||||
await execCommand(client, 'mkbook nb1');
|
await execCommand(client, 'mkbook nb1');
|
||||||
@@ -85,10 +96,16 @@ testUnits.testFolders = async () => {
|
|||||||
await execCommand(client, 'mkbook nb1');
|
await execCommand(client, 'mkbook nb1');
|
||||||
|
|
||||||
folders = await Folder.all();
|
folders = await Folder.all();
|
||||||
assertEquals(1, folders.length);
|
assertEquals(2, folders.length);
|
||||||
assertEquals('nb1', folders[0].title);
|
assertEquals('nb1', folders[0].title);
|
||||||
|
assertEquals('nb1', folders[1].title);
|
||||||
|
|
||||||
await execCommand(client, 'rm -r -f nb1');
|
await execCommand(client, 'rmbook -p -f nb1');
|
||||||
|
|
||||||
|
folders = await Folder.all();
|
||||||
|
assertEquals(1, folders.length);
|
||||||
|
|
||||||
|
await execCommand(client, 'rmbook -p -f nb1');
|
||||||
|
|
||||||
folders = await Folder.all();
|
folders = await Folder.all();
|
||||||
assertEquals(0, folders.length);
|
assertEquals(0, folders.length);
|
||||||
@@ -102,7 +119,7 @@ testUnits.testNotes = async () => {
|
|||||||
assertEquals(1, notes.length);
|
assertEquals(1, notes.length);
|
||||||
assertEquals('n1', notes[0].title);
|
assertEquals('n1', notes[0].title);
|
||||||
|
|
||||||
await execCommand(client, 'rm -f n1');
|
await execCommand(client, 'rmnote -p -f n1');
|
||||||
notes = await Note.all();
|
notes = await Note.all();
|
||||||
assertEquals(0, notes.length);
|
assertEquals(0, notes.length);
|
||||||
|
|
||||||
@@ -112,12 +129,19 @@ testUnits.testNotes = async () => {
|
|||||||
notes = await Note.all();
|
notes = await Note.all();
|
||||||
assertEquals(2, notes.length);
|
assertEquals(2, notes.length);
|
||||||
|
|
||||||
await execCommand(client, 'rm -f \'blabla*\'');
|
// Should fail to delete a non-existent note
|
||||||
|
let failed = false;
|
||||||
|
try {
|
||||||
|
await execCommand(client, 'rmnote -f \'blabla*\'');
|
||||||
|
} catch (error) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assertEquals(failed, true);
|
||||||
|
|
||||||
notes = await Note.all();
|
notes = await Note.all();
|
||||||
assertEquals(2, notes.length);
|
assertEquals(2, notes.length);
|
||||||
|
|
||||||
await execCommand(client, 'rm -f \'n*\'');
|
await execCommand(client, 'rmnote -f -p \'n*\'');
|
||||||
|
|
||||||
notes = await Note.all();
|
notes = await Note.all();
|
||||||
assertEquals(0, notes.length);
|
assertEquals(0, notes.length);
|
||||||
@@ -140,10 +164,12 @@ testUnits.testCat = async () => {
|
|||||||
|
|
||||||
testUnits.testConfig = async () => {
|
testUnits.testConfig = async () => {
|
||||||
await execCommand(client, 'config editor vim');
|
await execCommand(client, 'config editor vim');
|
||||||
|
await Setting.reset();
|
||||||
await Setting.load();
|
await Setting.load();
|
||||||
assertEquals('vim', Setting.value('editor'));
|
assertEquals('vim', Setting.value('editor'));
|
||||||
|
|
||||||
await execCommand(client, 'config editor subl');
|
await execCommand(client, 'config editor subl');
|
||||||
|
await Setting.reset();
|
||||||
await Setting.load();
|
await Setting.load();
|
||||||
assertEquals('subl', Setting.value('editor'));
|
assertEquals('subl', Setting.value('editor'));
|
||||||
|
|
||||||
@@ -201,15 +227,47 @@ testUnits.testMv = async () => {
|
|||||||
await execCommand(client, 'mknote note2');
|
await execCommand(client, 'mknote note2');
|
||||||
await execCommand(client, 'mknote note3');
|
await execCommand(client, 'mknote note3');
|
||||||
await execCommand(client, 'mknote blabla');
|
await execCommand(client, 'mknote blabla');
|
||||||
await execCommand(client, 'mv \'note*\' nb2');
|
|
||||||
|
|
||||||
notes1 = await Note.previews(f1.id);
|
notes1 = await Note.previews(f1.id);
|
||||||
notes2 = await Note.previews(f2.id);
|
notes2 = await Note.previews(f2.id);
|
||||||
|
|
||||||
|
assertEquals(4, notes1.length);
|
||||||
|
assertEquals(1, notes2.length);
|
||||||
|
|
||||||
|
await execCommand(client, 'mv \'note*\' nb2');
|
||||||
|
|
||||||
|
notes2 = await Note.previews(f2.id);
|
||||||
|
notes1 = await Note.previews(f1.id);
|
||||||
|
|
||||||
assertEquals(1, notes1.length);
|
assertEquals(1, notes1.length);
|
||||||
assertEquals(4, notes2.length);
|
assertEquals(4, notes2.length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
testUnits.testUse = async () => {
|
||||||
|
await execCommand(client, 'mkbook nb1');
|
||||||
|
await execCommand(client, 'mkbook nb2');
|
||||||
|
await execCommand(client, 'mknote n1');
|
||||||
|
await execCommand(client, 'mknote n2');
|
||||||
|
|
||||||
|
const f1 = await Folder.loadByTitle('nb1');
|
||||||
|
const f2 = await Folder.loadByTitle('nb2');
|
||||||
|
let notes1 = await Note.previews(f1.id);
|
||||||
|
let notes2 = await Note.previews(f2.id);
|
||||||
|
|
||||||
|
assertEquals(0, notes1.length);
|
||||||
|
assertEquals(2, notes2.length);
|
||||||
|
|
||||||
|
await execCommand(client, 'use nb1');
|
||||||
|
await execCommand(client, 'mknote note2');
|
||||||
|
await execCommand(client, 'mknote note3');
|
||||||
|
|
||||||
|
notes1 = await Note.previews(f1.id);
|
||||||
|
notes2 = await Note.previews(f2.id);
|
||||||
|
|
||||||
|
assertEquals(2, notes1.length);
|
||||||
|
assertEquals(2, notes2.length);
|
||||||
|
};
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await fs.remove(baseDir);
|
await fs.remove(baseDir);
|
||||||
|
|
||||||
@@ -217,7 +275,9 @@ async function main() {
|
|||||||
|
|
||||||
await db.open({ name: `${client.profileDir}/database.sqlite` });
|
await db.open({ name: `${client.profileDir}/database.sqlite` });
|
||||||
BaseModel.setDb(db);
|
BaseModel.setDb(db);
|
||||||
await Setting.load();
|
Setting.setConstant('rootProfileDir', client.profileDir);
|
||||||
|
Setting.setConstant('profileDir', client.profileDir);
|
||||||
|
await loadKeychainServiceAndSettings([]);
|
||||||
|
|
||||||
let onlyThisTest = 'testMv';
|
let onlyThisTest = 'testMv';
|
||||||
onlyThisTest = '';
|
onlyThisTest = '';
|
||||||
@@ -234,7 +294,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main(process.argv).catch(error => {
|
main().catch(error => {
|
||||||
console.info('');
|
console.info('');
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
});
|
});
|
||||||
@@ -891,6 +891,10 @@ export default class BaseApplication {
|
|||||||
if (!currentFolder) currentFolder = await Folder.defaultFolder();
|
if (!currentFolder) currentFolder = await Folder.defaultFolder();
|
||||||
Setting.setValue('activeFolderId', currentFolder ? currentFolder.id : '');
|
Setting.setValue('activeFolderId', currentFolder ? currentFolder.id : '');
|
||||||
|
|
||||||
|
if (currentFolder && !this.hasGui()) {
|
||||||
|
this.currentFolder_ = currentFolder;
|
||||||
|
}
|
||||||
|
|
||||||
await setupAutoDeletion();
|
await setupAutoDeletion();
|
||||||
|
|
||||||
await MigrationService.instance().run();
|
await MigrationService.instance().run();
|
||||||
|
|||||||
Reference in New Issue
Block a user