tools.test.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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-tools');
  6. const { createApp } = await import('../../src/http/app.js');
  7. const { disconnectDb } = await import('../../src/store/db.js');
  8. let running: RunningServer;
  9. const TOOL_PATHS = [
  10. '/tools/get_order_data',
  11. '/tools/get_product_data',
  12. '/tools/get_shipping_data',
  13. '/tools/check_shipping_eligibility',
  14. '/tools/get_payment_methods',
  15. '/tools/get_product_compatibility',
  16. '/tools/get_car_data',
  17. '/tools/new_ticket',
  18. ];
  19. before(async () => {
  20. applyTestConfig({ DATABASE_URL: dbUrl });
  21. running = await startServer(createApp());
  22. });
  23. after(async () => {
  24. await running.close();
  25. await disconnectDb();
  26. });
  27. async function post(path: string, body: unknown, auth?: string) {
  28. const headers: Record<string, string> = { 'Content-Type': 'application/json' };
  29. if (auth !== undefined) headers.Authorization = auth;
  30. const res = await fetch(`${running.baseUrl}${path}`, {
  31. method: 'POST',
  32. headers,
  33. body: JSON.stringify(body),
  34. });
  35. return { status: res.status, body: (await res.json()) as Record<string, unknown> };
  36. }
  37. test('every tool endpoint exists and rejects an unauthenticated call', async () => {
  38. for (const path of TOOL_PATHS) {
  39. const res = await post(path, {});
  40. assert.equal(res.status, 401, `${path} must require auth`);
  41. assert.equal(res.body.code, 'UNAUTHORIZED');
  42. }
  43. });
  44. test('a wrong bearer token is rejected', async () => {
  45. for (const path of TOOL_PATHS) {
  46. const res = await post(path, {}, 'Bearer wrong-secret');
  47. assert.equal(res.status, 401, `${path} must reject a wrong secret`);
  48. }
  49. });
  50. test('a token of the same length but different value is still rejected', async () => {
  51. const res = await post('/tools/new_ticket', { conversationId: 1 }, 'Bearer test-shared-secreT');
  52. assert.equal(res.status, 401);
  53. });
  54. test('an authenticated call with missing parameters returns 400, not 401', async () => {
  55. const res = await post('/tools/new_ticket', {}, 'Bearer test-shared-secret');
  56. assert.equal(res.status, 400);
  57. assert.equal(res.body.code, 'MISSING_PARAMS');
  58. });
  59. test('get_order_data requires an e-mail for ownership verification', async () => {
  60. const res = await post('/tools/get_order_data', { orderNumber: '123' }, 'Bearer test-shared-secret');
  61. assert.equal(res.status, 400);
  62. assert.equal(res.body.code, 'INVALID_PARAMS');
  63. });
  64. test('get_product_data requires at least one selector', async () => {
  65. const res = await post('/tools/get_product_data', {}, 'Bearer test-shared-secret');
  66. assert.equal(res.status, 400);
  67. assert.equal(res.body.code, 'MISSING_PARAMS');
  68. });
  69. test('admin endpoints require the admin token, not the tool secret', async () => {
  70. const noAuth = await fetch(`${running.baseUrl}/admin/events`);
  71. assert.equal(noAuth.status, 401);
  72. const toolSecret = await fetch(`${running.baseUrl}/admin/events`, {
  73. headers: { Authorization: 'Bearer test-shared-secret' },
  74. });
  75. assert.equal(toolSecret.status, 401);
  76. const admin = await fetch(`${running.baseUrl}/admin/events`, {
  77. headers: { Authorization: 'Bearer test-admin-token' },
  78. });
  79. assert.equal(admin.status, 200);
  80. const body = (await admin.json()) as Record<string, unknown>;
  81. assert.equal(body.ok, true);
  82. assert.ok(Array.isArray(body.events));
  83. });
  84. test('an unknown route returns a JSON 404', async () => {
  85. const res = await fetch(`${running.baseUrl}/tools/does_not_exist`, {
  86. method: 'POST',
  87. headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-shared-secret' },
  88. body: '{}',
  89. });
  90. assert.equal(res.status, 404);
  91. const body = (await res.json()) as Record<string, unknown>;
  92. assert.equal(body.code, 'NOT_FOUND');
  93. });