Files
sternboard/server/test/reveal-votes.test.ts
T
Millaguie f11ea58c2c
CI/CD Pipeline / test (push) Successful in 26s
CI/CD Pipeline / build-and-push (push) Successful in 44s
Sternboard: free retro board, no signup (initial)
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.
2026-06-16 10:27:33 +02:00

74 lines
2.9 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { startTestServer, createBoard, join, type TestServer } from "./helpers.js";
let server: TestServer;
beforeAll(async () => {
server = await startTestServer();
});
afterAll(async () => {
await server.close();
});
describe("Revelado granular", () => {
it("el autor revela solo su propia nota", async () => {
const board = await createBoard(server.url);
const alice = await join(server.url, board.boardId, "alice", "Alice");
const bob = await join(server.url, board.boardId, "bob", "Bob");
const colId = alice.last!.columns[0].id;
alice.emit("note:add", { columnId: colId, text: "mía" });
let bobState = await bob.waitFor((s) => s.notes.length === 1);
expect(bobState.notes[0].text).toBe(""); // oculta
const noteId = (await alice.waitFor((s) => s.notes.length === 1)).notes[0].id;
alice.emit("note:reveal", { noteId, revealed: true });
bobState = await bob.waitFor((s) => s.notes[0]?.text === "mía");
expect(bobState.notes[0].text).toBe("mía");
alice.close();
bob.close();
});
it("los totales de votos se ocultan hasta que el moderador los revela", async () => {
const board = await createBoard(server.url);
const alice = await join(server.url, board.boardId, "alice", "Alice");
const bob = await join(server.url, board.boardId, "bob", "Bob");
const colId = alice.last!.columns[0].id;
alice.emit("note:add", { columnId: colId, text: "vota esto" });
const noteId = (await alice.waitFor((s) => s.notes.length === 1)).notes[0].id;
await bob.waitFor((s) => s.notes.length === 1);
// Bob vota; Alice NO debe ver el voto de Bob (totales ocultos)
bob.emit("vote:toggle", { targetType: "note", targetId: noteId });
await bob.waitFor((s) => s.votes.some((v) => v.targetId === noteId)); // Bob ve el suyo
const aliceView = alice.last!;
expect(aliceView.votes.filter((v) => v.targetId === noteId)).toHaveLength(0);
// El moderador revela los votos => Alice ve el de Bob
alice.emit("board:revealVotes", { revealed: true, moderatorToken: board.moderatorToken });
const revealed = await alice.waitFor((s) => s.votesRevealed && s.votes.length === 1);
expect(revealed.votes[0].participantId).toBe("bob");
alice.close();
bob.close();
});
it("cambiar los ajustes del board requiere token de moderador", async () => {
const board = await createBoard(server.url, { votesPerUser: 3 });
const alice = await join(server.url, board.boardId, "alice", "Alice");
// sin token: ignorado
alice.emit("board:update", { title: "Hackeado", votesPerUser: 99 });
// con token: aplica
alice.emit("board:update", { title: "Renombrado", votesPerUser: 7, moderatorToken: board.moderatorToken });
const updated = await alice.waitFor((s) => s.title === "Renombrado");
expect(updated.votesPerUser).toBe(7);
alice.close();
});
});