Sternboard: free retro board, no signup (initial)
CI/CD Pipeline / test (push) Successful in 26s
CI/CD Pipeline / build-and-push (push) Successful in 44s

Servidor Fastify + Socket.IO + Drizzle/Postgres; front Vite+React (EN/ES, tema claro/oscuro).
Tableros por columnas con plantillas, notas privadas/públicas, agrupación, votos
configurables (multivoto), timer compartido con alarma, fases, action items,
export Markdown/JSON e import, autodestrucción, gestión de columnas.
Imagen única (front servido por el servidor) y CI que la construye y publica.
This commit is contained in:
Millaguie
2026-06-16 10:27:33 +02:00
commit f11ea58c2c
64 changed files with 12359 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { startTestServer, createBoard, type TestServer } from "./helpers.js";
let server: TestServer;
beforeAll(async () => {
server = await startTestServer();
});
afterAll(async () => {
await server.close();
});
describe("REST", () => {
it("lista plantillas predefinidas", async () => {
const res = await fetch(`${server.url}/api/templates`);
const templates = await res.json();
expect(Array.isArray(templates)).toBe(true);
expect(templates.find((t: any) => t.id === "mad-sad-glad")).toBeTruthy();
});
it("crea un board desde plantilla y devuelve token de moderador", async () => {
const board = await createBoard(server.url, { title: "Sprint 1" });
expect(board.boardId).toHaveLength(12);
expect(board.moderatorToken.length).toBeGreaterThan(10);
const meta = await (await fetch(`${server.url}/api/boards/${board.boardId}`)).json();
expect(meta.title).toBe("Sprint 1");
});
it("crea un board con columnas libres", async () => {
const board = await createBoard(server.url, {
templateId: undefined,
columns: ["Bien", "Mal", "Acciones"],
});
const md = await (await fetch(`${server.url}/api/boards/${board.boardId}/export`)).text();
expect(md).toContain("## Bien");
expect(md).toContain("## Mal");
});
it("fija expiresAt cuando se pasa ttlHours", async () => {
const board = await createBoard(server.url, { ttlHours: 2 });
expect(board.expiresAt).toBeTruthy();
expect(new Date(board.expiresAt!).getTime()).toBeGreaterThan(Date.now());
});
it("devuelve 404 para board inexistente", async () => {
const res = await fetch(`${server.url}/api/boards/noexiste123`);
expect(res.status).toBe(404);
});
it("rechaza plantilla inexistente con 400", async () => {
const res = await fetch(`${server.url}/api/boards`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ templateId: "nope" }),
});
expect(res.status).toBe(400);
});
});