/** * Command logging and date‑handling tests. * * Covers tarea command logging, date parsing edge cases, XSS/SQL * injection resilience, and sender ID normalization. */ import { describe, test, expect } from 'bun:test'; import { WebhookServer } from '../../src/server'; import { SimulatedResponseQueue } from '../helpers/queue'; import { createTestRequest, getFutureDate, registerServerTestLifecycle } from '../helpers/server-test-harness'; const testDb = registerServerTestLifecycle(); // ── Tests ────────────────────────────────────────────────────────────── describe('tarea command logging', () => { test('should log basic tarea command', async () => { const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'user123@s.whatsapp.net', }, message: { conversation: 'tarea test' }, }, }; await WebhookServer.handleRequest(createTestRequest(payload)); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should log command with due date', async () => { const futureDate = getFutureDate(3); const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'user123@s.whatsapp.net', }, message: { conversation: `tarea nueva Finish project @user2 ${futureDate}`, contextInfo: { mentionedJid: ['user2@s.whatsapp.net'], }, }, }, }; await WebhookServer.handleRequest(createTestRequest(payload)); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); }); describe('WebhookServer — Date handling & edge cases', () => { test('should handle XSS/SQL injection attempts', async () => { const maliciousMessage = `tarea nueva '; DROP TABLE tasks; --`; const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'sender-id@s.whatsapp.net', }, message: { conversation: maliciousMessage }, }, }; const request = createTestRequest(payload); const response = await WebhookServer.handleRequest(request); expect(response.status).toBe(200); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should handle multiple dates in command (use last one as due date)', async () => { const futureDate1 = getFutureDate(3); const futureDate2 = getFutureDate(5); const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'sender-id@s.whatsapp.net', }, message: { conversation: `tarea nueva Test task ${futureDate1} some text ${futureDate2}` }, }, }; await WebhookServer.handleRequest(createTestRequest(payload)); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should ignore past dates as due dates', async () => { const pastDate = '2020-01-01'; const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'sender-id@s.whatsapp.net', }, message: { conversation: `tarea nueva Old task ${pastDate}` }, }, }; await WebhookServer.handleRequest(createTestRequest(payload)); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should handle multiple past dates correctly', async () => { const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'sender-id@s.whatsapp.net', }, message: { conversation: 'tarea nueva Test 2020-01-01 2020-02-01' }, }, }; await WebhookServer.handleRequest(createTestRequest(payload)); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should handle mixed valid and invalid date formats', async () => { const futureDate = getFutureDate(3); const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'sender-id@s.whatsapp.net', }, message: { conversation: `tarea nueva Test invalid-date ${futureDate} another-bad` }, }, }; await WebhookServer.handleRequest(createTestRequest(payload)); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should normalize sender ID before processing', async () => { const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'sender-id:12@s.whatsapp.net', }, message: { conversation: 'tarea nueva Test' }, }, }; const request = createTestRequest(payload); const response = await WebhookServer.handleRequest(request); expect(response.status).toBe(200); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); }); test('should ignore messages with invalid sender ID', async () => { const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'invalid!@#$', }, message: { conversation: 'tarea nueva Test' }, }, }; const request = createTestRequest(payload); const response = await WebhookServer.handleRequest(request); expect(response.status).toBe(200); expect(SimulatedResponseQueue.get().length).toBe(0); }); test('should ensure user exists and use normalized ID', async () => { const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: '1234567890@s.whatsapp.net', }, message: { conversation: 'tarea nueva Test user' }, }, }; const request = createTestRequest(payload); const response = await WebhookServer.handleRequest(request); expect(response.status).toBe(200); expect(SimulatedResponseQueue.get().length).toBeGreaterThan(0); const user = testDb.query('SELECT * FROM users WHERE id = ?').get('1234567890'); expect(user).toBeDefined(); expect((user as any).id).toBe('1234567890'); }); test('should ignore messages if user creation fails', async () => { const payload = { event: 'messages.upsert', instance: 'test-instance', data: { key: { remoteJid: 'group-id@g.us', participant: 'invalid!user@s.whatsapp.net', }, message: { conversation: 'tarea nueva Test' }, }, }; const request = createTestRequest(payload); const response = await WebhookServer.handleRequest(request); expect(response.status).toBe(200); expect(SimulatedResponseQueue.get().length).toBe(0); const userCount = testDb.query('SELECT COUNT(*) as count FROM users').get(); expect((userCount as any).count).toBe(0); }); });