92 lines
3.7 KiB
JavaScript
92 lines
3.7 KiB
JavaScript
// Generated, do not edit. sha256:7bb4b4b51bf14bf2fa32107d316282a41f1c7586c33fc94c43098199bfa75953
|
|
import { describe, it, before, after } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { spawn } from 'node:child_process';
|
|
import { DatabaseSync } from 'node:sqlite';
|
|
import { mkdtemp, rm } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const WORTEL = join(fileURLToPath(import.meta.url), '..', '..', '..');
|
|
const STDIO = join(WORTEL, 'server', 'mcp', 'stdio.mjs');
|
|
|
|
let dir, proc, buffer = '', wachtenden = [];
|
|
|
|
function stuur(bericht) {
|
|
return new Promise((resolve, reject) => {
|
|
wachtenden.push(resolve);
|
|
const klaar = setTimeout(() => reject(new Error('geen antwoord binnen 10s')), 10_000);
|
|
wachtenden[wachtenden.length - 1] = (a) => { clearTimeout(klaar); resolve(a); };
|
|
proc.stdin.write(`${JSON.stringify(bericht)}\n`);
|
|
});
|
|
}
|
|
|
|
before(async () => {
|
|
dir = await mkdtemp(join(tmpdir(), 'assetapp-mcp-stdio-'));
|
|
proc = spawn(process.execPath, [STDIO], {
|
|
env: { ...process.env, ASSETAPP_DATA_DIR: dir, ASSETAPP_DB_FILE: join(dir, 'db.sqlite') },
|
|
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: het proces beantwoordt bericht na bericht', () => {
|
|
it('antwoordt op initialize', async () => {
|
|
const a = await stuur({ jsonrpc: '2.0', id: 1, method: 'initialize', params: {} });
|
|
assert.equal(a.id, 1);
|
|
assert.ok(a.result.serverInfo.name, 'er hoort een servernaam in te staan');
|
|
});
|
|
|
|
it('geeft de toollijst, en doet dat twee keer achter elkaar', async () => {
|
|
const een = await stuur({ jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} });
|
|
assert.ok(een.result.tools.length > 0, 'er hoort minstens één tool te zijn');
|
|
|
|
const twee = await stuur({ jsonrpc: '2.0', id: 3, method: 'tools/list', params: {} });
|
|
assert.deepEqual(twee.result.tools.map(t => t.name), een.result.tools.map(t => t.name));
|
|
});
|
|
|
|
it('voert een tool uit en legt hem vast in het auditlog', async () => {
|
|
const a = await stuur({
|
|
jsonrpc: '2.0', id: 4, method: 'tools/call',
|
|
params: { name: 'connection_test', arguments: {} },
|
|
});
|
|
assert.equal(a.id, 4);
|
|
assert.equal(a.error, undefined, `geen fout verwacht: ${JSON.stringify(a.error)}`);
|
|
assert.ok(a.result.content[0].text, 'er hoort een antwoord in te staan');
|
|
});
|
|
});
|
|
|
|
describe('mcp-stdio: de schuif "Actief" zet dit proces uit', () => {
|
|
it('stopt bij het eerstvolgende bericht zodra de schuif uit gaat', async () => {
|
|
const db = new DatabaseSync(join(dir, 'db.sqlite'));
|
|
db.exec(`PRAGMA busy_timeout = 5000`);
|
|
db.exec(`INSERT INTO Preference (scope, key, value) VALUES ('ai', 'enabled', '0')
|
|
ON CONFLICT (scope, key) DO UPDATE SET value = '0'`);
|
|
db.close();
|
|
|
|
const antwoord = await stuur({ jsonrpc: '2.0', id: 99, method: 'tools/list', params: {} });
|
|
|
|
assert.ok(antwoord.error, 'het laatste bericht hoort nog een antwoord te krijgen');
|
|
assert.match(antwoord.error.message, /Actief/, 'en dat antwoord wijst de juiste schuif aan');
|
|
|
|
const code = await new Promise((klaar) => proc.once('exit', klaar));
|
|
assert.equal(code, 0, 'een uitgezette koppeling is een keuze en geen storing');
|
|
});
|
|
});
|