107 lines
4.3 KiB
JavaScript
107 lines
4.3 KiB
JavaScript
// Generated, do not edit. sha256:4b1eef4e0860bce440fbf0875965c32cd7b13b237d0ffc92ef0255b11fe9a950
|
|||
|
|
import { describe, it, before, after } from 'node:test';
|
||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import { spawn } from 'node:child_process';
|
||
|
|
import { mkdtemp, rm, mkdir, writeFile, readdir } from 'node:fs/promises';
|
||
|
|
import { tmpdir } from 'node:os';
|
||
|
|
import { join } from 'node:path';
|
||
|
|
import { fileURLToPath } from 'node:url';
|
||
|
|
import { DatabaseSync } from 'node:sqlite';
|
||
|
|
import { CONFIG } from '../../shared/config.js';
|
||
|
|
|
||
|
|
const WORTEL = join(fileURLToPath(import.meta.url), '..', '..', '..');
|
||
|
|
const STDIO = join(WORTEL, 'server', 'mcp', 'stdio.mjs');
|
||
|
|
|
||
|
|
let dir, proc, buffer = '', wachtenden = [];
|
||
|
|
let volgendeId = 100;
|
||
|
|
|
||
|
|
function stuur(bericht) {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
const klaar = setTimeout(() => reject(new Error('geen antwoord binnen 10s')), 10_000);
|
||
|
|
wachtenden.push((a) => { clearTimeout(klaar); resolve(a); });
|
||
|
|
proc.stdin.write(`${JSON.stringify(bericht)}\n`);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const roep = (naam, args = {}) =>
|
||
|
|
stuur({ jsonrpc: '2.0', id: volgendeId++, method: 'tools/call', params: { name: naam, arguments: args } });
|
||
|
|
|
||
|
|
const wijsNaar = (naam) => writeFile(join(dir, 'active.json'), JSON.stringify({ portfolio: naam }), 'utf-8');
|
||
|
|
|
||
|
|
before(async () => {
|
||
|
|
dir = await mkdtemp(join(tmpdir(), 'assetapp-mcp-wissel-'));
|
||
|
|
proc = spawn(process.execPath, [STDIO], {
|
||
|
|
env: { ...process.env, ASSETAPP_DATA_DIR: dir },
|
||
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||
|
|
});
|
||
|
|
proc.stdout.on('data', (brok) => {
|
||
|
|
buffer += brok.toString();
|
||
|
|
let n;
|
||
|
|
while ((n = buffer.indexOf('\n')) >= 0) {
|
||
|
|
const regel = buffer.slice(0, n).trim();
|
||
|
|
buffer = buffer.slice(n + 1);
|
||
|
|
if (regel) (wachtenden.shift() || (() => {}))(JSON.parse(regel));
|
||
|
|
}
|
||
|
|
});
|
||
|
|
await new Promise((resolve) => proc.stderr.once('data', resolve));
|
||
|
|
});
|
||
|
|
|
||
|
|
after(async () => {
|
||
|
|
proc.stdin.end();
|
||
|
|
await new Promise((resolve) => proc.once('exit', resolve));
|
||
|
|
await rm(dir, { recursive: true, force: true });
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('mcp-stdio: de actieve portefeuille wordt per bericht gelezen', () => {
|
||
|
|
it('werkt in de portefeuille die bij het starten actief was', async () => {
|
||
|
|
const a = await roep('connection_test');
|
||
|
|
assert.equal(a.error, undefined, `geen fout verwacht: ${JSON.stringify(a.error)}`);
|
||
|
|
assert.ok(a.result.content[0].text);
|
||
|
|
assert.ok((await readdir(join(dir, 'MyAssets'))).includes('db.sqlite'));
|
||
|
|
});
|
||
|
|
|
||
|
|
it('WEIGERT leesbaar zodra de wijzer naar een nooit-geopende portefeuille wijst', async () => {
|
||
|
|
await mkdir(join(dir, 'Demo'), { recursive: true });
|
||
|
|
await wijsNaar('Demo');
|
||
|
|
|
||
|
|
const a = await roep('connection_test');
|
||
|
|
|
||
|
|
assert.ok(a.error, 'hier hoort een fout te komen en geen antwoord');
|
||
|
|
assert.match(a.error.message, /Demo/, 'de melding noemt de portefeuille');
|
||
|
|
assert.match(a.error.message, /nog geen ingerichte database/);
|
||
|
|
assert.match(a.error.message, /Portefeuilles/, 'en zegt wat je eraan doet');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('laat initialize en tools/list daar wél door, zodat de verbinding bruikbaar blijft', async () => {
|
||
|
|
const lijst = await stuur({ jsonrpc: '2.0', id: volgendeId++, method: 'tools/list', params: {} });
|
||
|
|
assert.equal(lijst.error, undefined);
|
||
|
|
assert.ok(lijst.result.tools.length > 0);
|
||
|
|
|
||
|
|
const init = await stuur({ jsonrpc: '2.0', id: volgendeId++, method: 'initialize', params: {} });
|
||
|
|
assert.equal(init.error, undefined);
|
||
|
|
assert.ok(init.result.serverInfo.name);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('zegt bij een NIEUWERE database dat de koppeling herstart moet worden', async () => {
|
||
|
|
await mkdir(join(dir, 'Nieuwer'), { recursive: true });
|
||
|
|
const db = new DatabaseSync(join(dir, 'Nieuwer', 'db.sqlite'));
|
||
|
|
db.exec(`CREATE TABLE Schema (version INTEGER NOT NULL) STRICT; INSERT INTO Schema (version) VALUES (${CONFIG.SCHEMA_VERSION + 1})`);
|
||
|
|
db.close();
|
||
|
|
await wijsNaar('Nieuwer');
|
||
|
|
|
||
|
|
const a = await roep('connection_test');
|
||
|
|
|
||
|
|
assert.ok(a.error, 'hier hoort een fout te komen en geen antwoord');
|
||
|
|
assert.match(a.error.message, /Nieuwer/);
|
||
|
|
assert.match(a.error.message, /herstart dan de AI-koppeling/);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('leest weer gewoon zodra de wijzer terugwijst naar een bruikbare portefeuille', async () => {
|
||
|
|
await wijsNaar('MyAssets');
|
||
|
|
|
||
|
|
const a = await roep('connection_test');
|
||
|
|
|
||
|
|
assert.equal(a.error, undefined, `geen fout verwacht: ${JSON.stringify(a.error)}`);
|
||
|
|
assert.ok(a.result.content[0].text);
|
||
|
|
});
|
||
|
|
});
|