ts6-botflow/studio.test.mjs

42 lines
3.2 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { DatabaseSync } from 'node:sqlite';
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { Readable } from 'node:stream';
import { createStudio, validateGraph } from './studio.mjs';
test('flows persist, simulation does not call TeamSpeak, credentials are hidden and readers cannot modify', async () => {
const directory=mkdtempSync(join(tmpdir(),'botflow-studio-'));
const db=new DatabaseSync(join(directory,'test.sqlite'));
const calls=[];
const studio=createStudio(db,directory,{transport:async (connection,command,params)=>{
assert.equal(connection.apiKey,'secret-api-key'); calls.push({command,params});
return command==='serverinfo'?[{virtualserver_clientsonline:1,virtualserver_maxclients:32,virtualserver_channelsonline:8}]:command==='clientlist'?[{client_type:0,client_nickname:'Client',client_lastconnected:1}]:[];
}});
const invoke=async (path,method='GET',body={},role='Dono',origin='http://localhost:3080')=>{
const req=Readable.from(method==='GET'?[]:[Buffer.from(JSON.stringify(body))]);req.method=method;req.headers={origin};let result;
await studio.route(req,new URL(path,'http://localhost:3080'),{role,name:'Tester'},(status,data)=>result={status,data});return result;
};
try {
const dashboard=(await invoke('/api/dashboard')).data,bot=dashboard.bots[0];
assert.equal(bot.enabled,false); assert.equal(dashboard.executions.length,0);
assert.equal((await invoke('/api/bots','POST',{name:'Test'},'Leitor')).status,403);
assert.equal((await invoke('/api/bots','POST',{name:'Test'},'Dono','http://evil.example')).status,403);
const simulation=await invoke(`/api/bots/${bot.id}/simulate`,'POST');
assert.equal(simulation.data.status,'success');assert.match(simulation.data.output,/Pessoa A/);assert.equal(calls.length,0);
assert.equal((await invoke(`/api/bots/${bot.id}/run`,'POST')).status,400);
const connection=(await invoke('/api/connections','POST',{name:'Test',url:'http://teamspeak6:10080',serverId:1,apiKey:'secret-api-key'})).data;
assert.equal(connection.hasApiKey,true);assert.equal(connection.apiKey,undefined);
assert.ok(!db.prepare('SELECT data FROM studio_connections').get().data.includes('secret-api-key'));
await invoke(`/api/bots/${bot.id}`,'PUT',{connectionId:connection.id,variables:{greeting:'Olá'}});
const execution=await invoke(`/api/bots/${bot.id}/run`,'POST');
assert.equal(execution.data.status,'success');assert.deepEqual(calls.map(c=>c.command),['serverinfo','clientlist','channeledit']);assert.equal(calls.at(-1).params.cid,21);assert.match(calls.at(-1).params.channel_description,/Client/);
const modified=structuredClone(bot.graph);modified.edges.push({from:'n6',to:'n0',port:'out'});
assert.throws(()=>validateGraph(modified),/ciclo/);
assert.equal((await invoke(`/api/bots/${bot.id}`,'PUT',{graph:modified})).status,400);
const final=(await invoke('/api/dashboard')).data;assert.equal(final.executions.length,2);assert.equal(final.bots[0].variables.greeting,'Olá');assert.equal(final.connections[0].apiKey,undefined);
} finally {studio.close();db.close();rmSync(directory,{recursive:true,force:true});}
});