arblant
panel-gateway / test / bot.test.js
bot.test.js95 lines · 3.5 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
/* Bot tests with stubbed Telegram + gateway (no network). Run: node --test test/bot.test.js */
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { parseCommand, findUser, handleUpdate } from '../src/bot.js';

test('parseCommand', () => {
  assert.deepEqual(parseCommand('/newuser مامان 20 30'), { cmd: 'newuser', args: ['مامان', '20', '30'] });
  assert.deepEqual(parseCommand('/users@mybot'), { cmd: 'users', args: [] });
  assert.equal(parseCommand('hello'), null);
});

test('findUser', () => {
  const users = [
    { uuid: 'a1b2c3d4-0000-0000-0000-000000000001', name: 'مامان' },
    { uuid: 'a1b2c3d4-0000-0000-0000-000000000002', name: 'بابا' },
  ];
  assert.equal(findUser(users, 'مامان').length, 1);
  assert.equal(findUser(users, 'a1b2c3d4-0000').length, 2);
  assert.equal(findUser(users, 'xyz').length, 0);
});

function stubDeps(over = {}) {
  const sent = [], docs = [];
  const users = [{ uuid: '11111111-2222-3333-4444-555555555555', name: 'مامان', quotaBytes: 21474836480, used_up: 0, used_down: 0, usedUp: 100, usedDown: 200, usedTotal: 300, expiresAt: 0, revoked: false }];
  const deps = {
    env: { ADMIN_CHAT_ID: '123', GATEWAY_URL: 'https://gw.example.com', ...(over.env || {}) },
    send: async (chatId, text) => { sent.push({ chatId, text }); },
    tg: async (method, body) => { docs.push({ method, body }); return {}; },
    gw: async (path, method, body) => {
      if (path === '/admin/users' && method === 'POST') return { ...users[0], uuid: '99999999-2222-3333-4444-555555555555', name: body.name };
      if (path === '/admin/users') return users;
      if (path === '/admin/backup') return { users };
      return {};
    },
    ...over.deps,
  };
  return { deps, sent, docs };
}
const upd = (text, chat = 123) => ({ message: { chat: { id: chat }, text } });

test('rejects non-admin chat', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('/users', 999), deps);
  assert.match(sent[0].text, /خصوصیه/);
  assert.match(sent[0].text, /999/);
});

test('no ADMIN_CHAT_ID → setup hint', async () => {
  const { deps, sent } = stubDeps({ env: { ADMIN_CHAT_ID: '' } });
  await handleUpdate(upd('/start', 777), deps);
  assert.match(sent[0].text, /ADMIN_CHAT_ID/);
});

test('/newuser creates and replies link', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('/newuser مامان 20 30'), deps);
  assert.match(sent[0].text, /ساخته شد/);
  assert.match(sent[0].text, /vless:\/\/99999999-2222-3333-4444-555555555555@gw\.example\.com/);
});

test('/users lists', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('/users'), deps);
  assert.match(sent[0].text, /مامان/);
});

test('/usage shows detail', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('/usage مامان'), deps);
  assert.match(sent[0].text, /مصرف/);
});

test('/health', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('/health'), deps);
  assert.match(sent[0].text, /گیت‌وی: ✅/);
});

test('/backup sends document', async () => {
  const { deps, docs } = stubDeps();
  await handleUpdate(upd('/backup'), deps);
  assert.equal(docs[0].method, 'sendDocument');
});

test('unknown command', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('/blah'), deps);
  assert.match(sent[0].text, /نفهمیدم/);
});

test('non-command ignored', async () => {
  const { deps, sent } = stubDeps();
  await handleUpdate(upd('سلام'), deps);
  assert.equal(sent.length, 0);
});