You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			176 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			176 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			TypeScript
		
	
| import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
 | |
| import { Database } from 'bun:sqlite';
 | |
| import { initializeDatabase, ensureUserExists } from '../../../src/db';
 | |
| import { TaskService } from '../../../src/tasks/service';
 | |
| 
 | |
| let memDb: Database;
 | |
| 
 | |
| beforeEach(() => {
 | |
|   memDb = new Database(':memory:');
 | |
|   initializeDatabase(memDb);
 | |
|   TaskService.dbInstance = memDb;
 | |
| });
 | |
| 
 | |
| afterEach(() => {
 | |
|   try {
 | |
|     memDb.close();
 | |
|   } catch {}
 | |
| });
 | |
| 
 | |
| describe('TaskService.createTask', () => {
 | |
|   it('crea una tarea mínima con created_by y sin due_date ni group_id', () => {
 | |
|     const creatorRaw = '555111222@s.whatsapp.net';
 | |
|     const createdBy = ensureUserExists(creatorRaw, memDb);
 | |
|     expect(createdBy).toBeTruthy();
 | |
| 
 | |
|     const id = TaskService.createTask(
 | |
|       {
 | |
|         description: 'Comprar agua',
 | |
|         created_by: createdBy!,
 | |
|         due_date: null,
 | |
|         group_id: null,
 | |
|       },
 | |
|       [] // sin asignaciones
 | |
|     );
 | |
| 
 | |
|     expect(typeof id).toBe('number');
 | |
| 
 | |
|     const task = memDb
 | |
|       .prepare(
 | |
|         `SELECT id, description, due_date, group_id, created_by, completed 
 | |
|          FROM tasks WHERE id = ?`
 | |
|       )
 | |
|       .get(id) as any;
 | |
| 
 | |
|     expect(task).toBeTruthy();
 | |
|     expect(task.description).toBe('Comprar agua');
 | |
|     expect(task.due_date).toBeNull();
 | |
|     expect(task.group_id).toBeNull();
 | |
|     expect(task.created_by).toBe(createdBy);
 | |
|     expect(task.completed).toBe(0); // BOOLEAN en SQLite como 0/1
 | |
|   });
 | |
| 
 | |
|   it('guarda due_date como cadena YYYY-MM-DD y group_id como JID completo', () => {
 | |
|     const creatorRaw = '555333444@s.whatsapp.net';
 | |
|     const createdBy = ensureUserExists(creatorRaw, memDb)!;
 | |
| 
 | |
|     const due = '2025-09-10';
 | |
|     const groupId = '12345@g.us';
 | |
| 
 | |
|     // Sembrar el grupo para satisfacer la FK de tasks.group_id -> groups.id
 | |
|     memDb
 | |
|       .prepare(`INSERT INTO groups (id, community_id, name, active) VALUES (?, ?, ?, TRUE)`)
 | |
|       .run(groupId, 'test-community', 'Grupo de prueba');
 | |
| 
 | |
|     const id = TaskService.createTask(
 | |
|       {
 | |
|         description: 'Pagar servicios',
 | |
|         created_by: createdBy,
 | |
|         due_date: due,
 | |
|         group_id: groupId,
 | |
|       },
 | |
|       []
 | |
|     );
 | |
| 
 | |
|     const row = memDb
 | |
|       .prepare(
 | |
|         `SELECT description, due_date, group_id, created_by 
 | |
|          FROM tasks WHERE id = ?`
 | |
|       )
 | |
|       .get(id) as any;
 | |
| 
 | |
|     expect(row.due_date).toBe(due);
 | |
|     expect(row.group_id).toBe(groupId);
 | |
|     expect(row.created_by).toBe(createdBy);
 | |
|   });
 | |
| 
 | |
|   it('inserta asignaciones y evita duplicados por usuario', () => {
 | |
|     const creator = ensureUserExists('555000001@s.whatsapp.net', memDb)!;
 | |
|     const assigneeA = ensureUserExists('555000002@s.whatsapp.net', memDb)!;
 | |
|     const assigneeB = ensureUserExists('555000003@s.whatsapp.net', memDb)!;
 | |
| 
 | |
|     const id = TaskService.createTask(
 | |
|       {
 | |
|         description: 'Organizar reunión',
 | |
|         created_by: creator,
 | |
|         due_date: null,
 | |
|         group_id: null,
 | |
|       },
 | |
|       [
 | |
|         { user_id: assigneeA, assigned_by: creator },
 | |
|         { user_id: assigneeA, assigned_by: creator }, // duplicado
 | |
|         { user_id: assigneeB, assigned_by: creator },
 | |
|       ]
 | |
|     );
 | |
| 
 | |
|     const count = memDb
 | |
|       .prepare(
 | |
|         `SELECT COUNT(*) AS c FROM task_assignments WHERE task_id = ?`
 | |
|       )
 | |
|       .get(id) as any;
 | |
| 
 | |
|     expect(count.c).toBe(2);
 | |
| 
 | |
|     const users = memDb
 | |
|       .prepare(
 | |
|         `SELECT user_id FROM task_assignments WHERE task_id = ? ORDER BY user_id`
 | |
|       )
 | |
|       .all(id) as any[];
 | |
| 
 | |
|     expect(users.map(u => u.user_id)).toEqual([assigneeA, assigneeB].sort());
 | |
|   });
 | |
| 
 | |
|   it('hace rollback si una asignación viola FK (usuario inexistente)', () => {
 | |
|     const creator = ensureUserExists('555010101@s.whatsapp.net', memDb)!;
 | |
| 
 | |
|     expect(() =>
 | |
|       TaskService.createTask(
 | |
|         {
 | |
|           description: 'Tarea con fallo',
 | |
|           created_by: creator,
 | |
|           due_date: null,
 | |
|           group_id: null,
 | |
|         },
 | |
|         [
 | |
|           // Usuario no existente: no llamamos ensureUserExists
 | |
|           { user_id: '555099999', assigned_by: creator },
 | |
|         ]
 | |
|       )
 | |
|     ).toThrow();
 | |
| 
 | |
|     const counts = memDb
 | |
|       .prepare(
 | |
|         `SELECT 
 | |
|            (SELECT COUNT(*) FROM tasks) AS tasks_count,
 | |
|            (SELECT COUNT(*) FROM task_assignments) AS assigns_count`
 | |
|       )
 | |
|       .get() as any;
 | |
| 
 | |
|     expect(counts.tasks_count).toBe(0);
 | |
|     expect(counts.assigns_count).toBe(0);
 | |
|   });
 | |
| 
 | |
|   it('lanza error si created_by no existe (FK) y no inserta la tarea', () => {
 | |
|     // No llamamos a ensureUserExists para este created_by
 | |
|     const nonExisting = '555123123';
 | |
| 
 | |
|     expect(() =>
 | |
|       TaskService.createTask(
 | |
|         {
 | |
|           description: 'No debería insertarse',
 | |
|           created_by: nonExisting,
 | |
|           due_date: null,
 | |
|           group_id: null,
 | |
|         },
 | |
|         []
 | |
|       )
 | |
|     ).toThrow();
 | |
| 
 | |
|     const count = memDb
 | |
|       .prepare(`SELECT COUNT(*) AS c FROM tasks`)
 | |
|       .get() as any;
 | |
| 
 | |
|     expect(count.c).toBe(0);
 | |
|   });
 | |
| });
 |