100 lines
4.1 KiB
TypeScript
100 lines
4.1 KiB
TypeScript
import { test, expect, type Page, type Locator } from "@playwright/test";
|
|||
|
|
|
||
|
|
async function createBoard(page: Page, title: string) {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.getByTestId("board-title").fill(title);
|
||
|
|
await page.getByTestId("template").selectOption("mad-sad-glad");
|
||
|
|
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 page.getByTestId("name").fill(name);
|
||
|
|
await page.getByTestId("join").click();
|
||
|
|
await expect(page.getByTestId("column").first()).toBeVisible();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Escribe una nota privada y la publica (queda en el área pública).
|
||
|
|
// Esperamos el conteo de notas privadas para evitar clics sobre elementos que re-renderizan.
|
||
|
|
async function addPublicNote(col: Locator, text: string) {
|
||
|
|
await col.getByTestId("note-input").fill(text);
|
||
|
|
await col.getByTestId("note-input").press("Enter");
|
||
|
|
await expect(col.getByTestId("private-note")).toHaveCount(1);
|
||
|
|
await col.getByTestId("private-note").getByTestId("publish").click();
|
||
|
|
await expect(col.getByTestId("private-note")).toHaveCount(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Arrastra una nota (desde su tirador) sobre el centro de otra (gesto de agrupar).
|
||
|
|
async function dragOnto(page: Page, sourceNote: Locator, target: Locator) {
|
||
|
|
const handle = await sourceNote.getByTestId("note-handle").boundingBox();
|
||
|
|
const t = await target.boundingBox();
|
||
|
|
if (!handle || !t) throw new Error("sin boundingBox");
|
||
|
|
await page.mouse.move(handle.x + handle.width / 2, handle.y + handle.height / 2);
|
||
|
|
await page.mouse.down();
|
||
|
|
await page.mouse.move(handle.x + handle.width / 2, handle.y + handle.height / 2 + 8); // supera el umbral
|
||
|
|
await page.mouse.move(t.x + t.width / 2, t.y + t.height / 2, { steps: 12 });
|
||
|
|
await page.mouse.up();
|
||
|
|
}
|
||
|
|
|
||
|
|
test("agrupar dos notas arrastrando una sobre otra", async ({ page }) => {
|
||
|
|
const url = await createBoard(page, "Retro grupos");
|
||
|
|
await joinAs(page, url, "Ana");
|
||
|
|
|
||
|
|
const col = page.getByTestId("column").first();
|
||
|
|
await addPublicNote(col, "primera");
|
||
|
|
await addPublicNote(col, "segunda");
|
||
|
|
await expect(col.getByTestId("note")).toHaveCount(2);
|
||
|
|
|
||
|
|
const notes = col.getByTestId("note");
|
||
|
|
await dragOnto(page, notes.nth(1), notes.nth(0));
|
||
|
|
|
||
|
|
// aparece un grupo con dos notas dentro
|
||
|
|
await expect(page.getByTestId("group")).toHaveCount(1);
|
||
|
|
await expect(page.getByTestId("group").getByTestId("note")).toHaveCount(2);
|
||
|
|
|
||
|
|
// votar el grupo como unidad
|
||
|
|
await page.getByTestId("group").getByTestId("vote").click();
|
||
|
|
await expect(page.getByTestId("group").getByTestId("vote")).toHaveClass(/voted/);
|
||
|
|
|
||
|
|
// y nombrarlo
|
||
|
|
await page.getByTestId("group-title").fill("Tema común");
|
||
|
|
await page.getByTestId("group-title").blur();
|
||
|
|
await expect(page.getByTestId("group-title")).toHaveValue("Tema común");
|
||
|
|
});
|
||
|
|
|
||
|
|
test("multivoto: apilar varios votos en el mismo ítem y quitar", async ({ page }) => {
|
||
|
|
const url = await createBoard(page, "Retro multivoto");
|
||
|
|
await joinAs(page, url, "Ana");
|
||
|
|
|
||
|
|
const col = page.getByTestId("column").first();
|
||
|
|
await addPublicNote(col, "favorita");
|
||
|
|
await expect(col.getByTestId("note")).toHaveCount(1);
|
||
|
|
|
||
|
|
// dos votos al mismo ítem (multivoto activo por defecto)
|
||
|
|
await page.getByTestId("vote").click();
|
||
|
|
await page.getByTestId("vote").click();
|
||
|
|
|
||
|
|
// el moderador revela los totales -> debe verse 2
|
||
|
|
await page.getByTestId("reveal-votes").click();
|
||
|
|
await expect(page.getByTestId("vote")).toContainText("2");
|
||
|
|
|
||
|
|
// quitar uno -> 1
|
||
|
|
await page.getByTestId("vote-remove").click();
|
||
|
|
await expect(page.getByTestId("vote")).toContainText("1");
|
||
|
|
});
|
||
|
|
|
||
|
|
test("el moderador cambia los ajustes en caliente (título y votos)", async ({ page }) => {
|
||
|
|
const url = await createBoard(page, "Original");
|
||
|
|
await joinAs(page, url, "Mod");
|
||
|
|
|
||
|
|
await page.getByTestId("settings").click();
|
||
|
|
await page.getByTestId("settings-title").fill("Renombrada en vivo");
|
||
|
|
await page.getByTestId("settings-votes").fill("9");
|
||
|
|
await page.getByTestId("settings-save").click();
|
||
|
|
|
||
|
|
await expect(page.locator("header h1")).toHaveText("Renombrada en vivo");
|
||
|
|
await expect(page.locator(".votes-pill")).toContainText("9");
|
||
|
|
});
|