import { test, expect, type Page, type Locator } from "@playwright/test"; async function createBoard(page: Page, title: string, template = "mad-sad-glad") { await page.goto("/"); await page.getByTestId("board-title").fill(title); await page.getByTestId("template").selectOption(template); await page.getByTestId("create").click(); await page.waitForURL(/\/b\/.+/); return page.url(); } async function joinAs(page: Page, boardUrl: string, name: string) { await page.goto(boardUrl); await expect(page.getByTestId("name")).toBeVisible(); await page.getByTestId("name").fill(name); await page.getByTestId("join").click(); await expect(page.getByTestId("column").first()).toBeVisible(); } // Escribe una nota en la sección privada de una columna (se guarda con Enter). async function writeNote(col: Locator, text: string) { await col.getByTestId("note-input").fill(text); await col.getByTestId("note-input").press("Enter"); await expect(col.getByTestId("private-note").last()).toBeVisible(); } test("crea un board, pide nombre obligatorio y muestra columnas", async ({ page }) => { await createBoard(page, "Sprint 42"); await expect(page.getByTestId("name")).toBeVisible(); await expect(page.getByTestId("column")).toHaveCount(0); await page.getByTestId("name").fill("Fede"); await page.getByTestId("join").click(); await expect(page.getByTestId("column")).toHaveCount(3); }); test("una nota privada no la ve nadie hasta publicarla", async ({ browser }) => { const ctxA = await browser.newContext(); const ctxB = await browser.newContext(); const alice = await ctxA.newPage(); const bob = await ctxB.newPage(); const url = await createBoard(alice, "Retro privada"); await joinAs(alice, url, "Alice"); await joinAs(bob, url, "Bob"); const aliceCol = alice.getByTestId("column").first(); await writeNote(aliceCol, "algo privado"); // Bob no ve nada: ni nota pública ni la privada de Alice await expect(bob.getByTestId("note")).toHaveCount(0); await expect(bob.getByTestId("private-note")).toHaveCount(0); // Alice publica su nota await aliceCol.getByTestId("publish").first().click(); // ahora es pública para Bob (la ve como párrafo de solo lectura) await expect(bob.getByTestId("note")).toHaveCount(1); await expect(bob.getByTestId("note-text")).toHaveText("algo privado"); await ctxA.close(); await ctxB.close(); }); test("Publish all publica todas mis notas de la columna", async ({ page }) => { const url = await createBoard(page, "Retro publish all"); await joinAs(page, url, "Vera"); const col = page.getByTestId("column").first(); await writeNote(col, "una"); await writeNote(col, "dos"); await expect(col.getByTestId("private-note")).toHaveCount(2); await col.getByTestId("publish-all").click(); await expect(col.getByTestId("private-note")).toHaveCount(0); await expect(col.getByTestId("note")).toHaveCount(2); }); test("votar una nota publicada y exportar markdown con el conteo", async ({ page, request }) => { const url = await createBoard(page, "Retro votos"); const boardId = url.split("/b/")[1]; await joinAs(page, url, "Vera"); const col = page.getByTestId("column").first(); await writeNote(col, "idea top"); await col.getByTestId("publish").first().click(); await expect(page.getByTestId("note")).toHaveCount(1); // votar: con totales ocultos el botón marca "✓" (mi voto), no el total await page.getByTestId("vote").first().click(); await expect(page.getByTestId("vote").first()).toHaveClass(/voted/); // el moderador revela los votos -> ahora se ve el total await page.getByTestId("reveal-votes").click(); await expect(page.getByTestId("vote").first()).toContainText("1"); const res = await request.get(`http://localhost:3001/api/boards/${boardId}/export`); expect(res.status()).toBe(200); const md = await res.text(); expect(md).toContain("# Retro votos"); expect(md).toContain("idea top — _Vera_ (1 👍)"); }); test("el timer compartido arranca para todos los participantes", async ({ browser }) => { const ctxA = await browser.newContext(); const ctxB = await browser.newContext(); const alice = await ctxA.newPage(); const bob = await ctxB.newPage(); const url = await createBoard(alice, "Retro timer"); await joinAs(alice, url, "Alice"); await joinAs(bob, url, "Bob"); await alice.getByRole("button", { name: /5\s*min/i }).click(); await expect(alice.locator(".timer .clock")).toHaveText(/0[0-4]:\d{2}/); await expect(bob.locator(".timer .clock")).toHaveText(/0[0-4]:\d{2}/); await ctxA.close(); await ctxB.close(); });