agentTools.test.ts 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { after, before, test } from 'node:test';
  2. import assert from 'node:assert/strict';
  3. import { prepareTestDatabase, startServer, type RunningServer } from '../helpers/testServer.js';
  4. import { applyTestConfig } from '../helpers/testConfig.js';
  5. const dbUrl = prepareTestDatabase('test-agent-tools');
  6. const { createApp } = await import('../../src/http/app.js');
  7. const { disconnectDb } = await import('../../src/store/db.js');
  8. let running: RunningServer;
  9. let originalFetch: typeof globalThis.fetch;
  10. let flowiseCalls = 0;
  11. before(async () => {
  12. applyTestConfig({
  13. DATABASE_URL: dbUrl,
  14. AGENT_UI_TOKEN: 'test-agent-token',
  15. CHATWOOT_BASE_URL: 'https://eksupport.easyklima.com',
  16. FLOWISE_TRANSLATION_PREDICT_URL: 'https://flowise.test/api/v1/prediction/translation',
  17. });
  18. originalFetch = globalThis.fetch;
  19. globalThis.fetch = (async (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {
  20. const url = String(input);
  21. if (url.includes('flowise.test')) {
  22. flowiseCalls += 1;
  23. const body = JSON.parse(String(init?.body ?? '{}')) as Record<string, unknown>;
  24. assert.match(String(body.question), /Translate this/);
  25. return new Response(JSON.stringify({ text: 'Dzień dobry' }), {
  26. status: 200,
  27. headers: { 'Content-Type': 'application/json' },
  28. });
  29. }
  30. return originalFetch(input, init);
  31. }) as typeof globalThis.fetch;
  32. running = await startServer(createApp());
  33. });
  34. after(async () => {
  35. globalThis.fetch = originalFetch;
  36. await running.close();
  37. await disconnectDb();
  38. });
  39. test('serves the Chatwoot injection asset without secrets', async () => {
  40. const res = await fetch(`${running.baseUrl}/chatwoot-ai-tools.js`);
  41. const text = await res.text();
  42. assert.equal(res.status, 200);
  43. assert.match(res.headers.get('content-type') ?? '', /application\/javascript/);
  44. assert.match(text, /AI tłumacz/);
  45. assert.ok(!text.includes('test-agent-token'));
  46. });
  47. test('agent translation endpoints require the agent UI token', async () => {
  48. const res = await fetch(`${running.baseUrl}/agent-tools/translate-message`, {
  49. method: 'POST',
  50. headers: { 'Content-Type': 'application/json' },
  51. body: JSON.stringify({ sourceText: 'Hello', targetLanguage: 'pl' }),
  52. });
  53. assert.equal(res.status, 401);
  54. });
  55. test('translates message text through Flowise and caches repeated requests', async () => {
  56. const payload = { sourceText: 'Good morning', targetLanguage: 'pl', conversationId: 42, messageId: 'm-1' };
  57. const first = await postTranslate('/agent-tools/translate-message', payload);
  58. const second = await postTranslate('/agent-tools/translate-message', payload);
  59. assert.equal(first.status, 200);
  60. assert.equal(second.status, 200);
  61. assert.equal(first.body.translatedText, 'Dzień dobry');
  62. assert.equal(first.body.cached, false);
  63. assert.equal(second.body.cached, true);
  64. assert.equal(flowiseCalls, 1);
  65. });
  66. test('translates draft text through the draft endpoint', async () => {
  67. const res = await postTranslate('/agent-tools/translate-draft', {
  68. draftText: 'Proszę podać numer zamówienia.',
  69. targetLanguage: 'de',
  70. conversationId: 42,
  71. });
  72. assert.equal(res.status, 200);
  73. assert.equal(res.body.ok, true);
  74. assert.equal(res.body.provider, 'flowise');
  75. });
  76. async function postTranslate(path: string, body: Record<string, unknown>) {
  77. const res = await fetch(`${running.baseUrl}${path}`, {
  78. method: 'POST',
  79. headers: {
  80. 'Content-Type': 'application/json',
  81. Authorization: 'Bearer test-agent-token',
  82. Origin: 'https://eksupport.easyklima.com',
  83. },
  84. body: JSON.stringify(body),
  85. });
  86. return { status: res.status, body: (await res.json()) as Record<string, unknown> };
  87. }