124 lines
4.5 KiB
TypeScript
124 lines
4.5 KiB
TypeScript
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();
|
||
|
|
});
|