ts6-botflow/studio.test.mjs
Bxio 1be8a45dde
All checks were successful
Testar e publicar imagem Docker / publish (push) Successful in 44s
Expand flow editor with TeamSpeak events, permissions and execution controls
2026-10-10 20:38:31 +01:00

58 lines
4.3 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, interpolate } from './studio.mjs';
test('templates subtract numeric Query counts without executing expressions', () => {
const context = { server: { virtualserver_clientsonline:'6', virtualserver_queryclientsonline:'2' }, text:'Título' };
const formula = '{{server.virtualserver_clientsonline - server.virtualserver_queryclientsonline}}';
assert.equal(interpolate(`Online: ${formula} · {{text}}`, context), 'Online: 4 · Título');
context.server.virtualserver_queryclientsonline = 0;
assert.equal(interpolate(formula, context), '6');
context.server.virtualserver_queryclientsonline = 'invalid';
assert.throws(() => interpolate(formula, context), /valor numérico/);
delete context.server.virtualserver_queryclientsonline;
assert.throws(() => interpolate(formula, context), /valor numérico/);
assert.throws(() => interpolate('{{process.exit()}}', context), /não suportada/);
assert.equal(interpolate('{{server.constructor}}', context), '');
});
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:'3',virtualserver_queryclientsonline:'2',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.match(simulation.data.output, /Online: 3 \/ 32/);
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/);
assert.match(calls.at(-1).params.channel_description, /Online: 1 \/ 32/);
const modified=structuredClone(bot.graph);modified.edges.push({from:'n6',to:'n0',port:'out'});
assert.throws(()=>validateGraph(modified),/inválida|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});}
});