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.
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import { describe, it, beforeAll, afterAll, expect } from 'bun:test';
|
|
import { createTempDb } from './helpers/db';
|
|
import { startWebServer, type RunningServer } from './helpers/server';
|
|
|
|
describe('API Web - carreras en complete con auto-asignación', () => {
|
|
const U1 = '34600123456';
|
|
const U2 = '34600123457';
|
|
const GROUP = 'g-3@g.us';
|
|
|
|
let dbHandle: any;
|
|
let cleanupDb: () => void;
|
|
let serverA: RunningServer;
|
|
let serverB: RunningServer;
|
|
let baseA: string;
|
|
let baseB: string;
|
|
let taskId: number;
|
|
|
|
beforeAll(async () => {
|
|
const tmp = createTempDb();
|
|
dbHandle = tmp.db;
|
|
cleanupDb = tmp.cleanup;
|
|
|
|
// Semilla mínima
|
|
dbHandle.prepare(`INSERT INTO users (id) VALUES (?) ON CONFLICT(id) DO NOTHING`).run(U1);
|
|
dbHandle.prepare(`INSERT INTO users (id) VALUES (?) ON CONFLICT(id) DO NOTHING`).run(U2);
|
|
dbHandle
|
|
.prepare(`INSERT INTO groups (id, community_id, name, active) VALUES (?, 'comm-1', 'G3', 1)`)
|
|
.run(GROUP);
|
|
dbHandle.prepare(`INSERT INTO allowed_groups (group_id, status) VALUES (?, 'allowed')`).run(GROUP);
|
|
dbHandle
|
|
.prepare(`INSERT INTO group_members (group_id, user_id, is_admin, is_active) VALUES (?, ?, 0, 1)`)
|
|
.run(GROUP, U1);
|
|
dbHandle
|
|
.prepare(`INSERT INTO group_members (group_id, user_id, is_admin, is_active) VALUES (?, ?, 0, 1)`)
|
|
.run(GROUP, U2);
|
|
|
|
const ins = dbHandle
|
|
.prepare(`INSERT INTO tasks (description, group_id, created_by) VALUES ('Carrera complete', ?, ?)`)
|
|
.run(GROUP, U1);
|
|
taskId = Number(ins.lastInsertRowid);
|
|
|
|
// Iniciar dos servidores contra la misma DB
|
|
serverA = await startWebServer({
|
|
port: 19111,
|
|
env: { DB_PATH: tmp.path, DEV_DEFAULT_USER: U1, TZ: 'UTC' }
|
|
});
|
|
baseA = serverA.baseUrl;
|
|
serverB = await startWebServer({
|
|
port: 19112,
|
|
env: { DB_PATH: tmp.path, DEV_DEFAULT_USER: U2, TZ: 'UTC' }
|
|
});
|
|
baseB = serverB.baseUrl;
|
|
});
|
|
|
|
afterAll(async () => {
|
|
try {
|
|
await serverA.stop();
|
|
} catch {}
|
|
try {
|
|
await serverB.stop();
|
|
} catch {}
|
|
try {
|
|
cleanupDb?.();
|
|
} catch {}
|
|
});
|
|
|
|
it('solo una actualización de completed; la asignación incluye al menos al completador', async () => {
|
|
const [r1, r2] = await Promise.all([
|
|
fetch(`${baseA}/api/tasks/${taskId}/complete`, { method: 'POST' }),
|
|
fetch(`${baseB}/api/tasks/${taskId}/complete`, { method: 'POST' })
|
|
]);
|
|
expect([200, 200]).toContain(r1.status);
|
|
expect([200, 200]).toContain(r2.status);
|
|
|
|
const row = dbHandle
|
|
.prepare(`SELECT COALESCE(completed,0) as completed, completed_by FROM tasks WHERE id = ?`)
|
|
.get(taskId) as any;
|
|
expect(Number(row?.completed || 0)).toBe(1);
|
|
const completedBy = String(row?.completed_by || '');
|
|
|
|
const assigns = dbHandle
|
|
.prepare(`SELECT user_id FROM task_assignments WHERE task_id = ? ORDER BY assigned_at ASC`)
|
|
.all(taskId) as any[];
|
|
|
|
// Debe existir al menos una asignación y contener al que completó
|
|
expect(assigns.length >= 1 && assigns.length <= 2).toBe(true);
|
|
const assignedUsers = assigns.map((r) => String(r.user_id));
|
|
expect([U1, U2]).toContain(completedBy);
|
|
expect(assignedUsers).toContain(completedBy);
|
|
});
|
|
});
|