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.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
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, url: string, name: string) {
|
||||
await page.goto(url);
|
||||
await page.getByTestId("name").fill(name);
|
||||
await page.getByTestId("join").click();
|
||||
await expect(page.getByTestId("column").first()).toBeVisible();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
test("participantes: presencia, editar nombre y mostrar autores", async ({ page }) => {
|
||||
const url = await createBoard(page, "Retro panel");
|
||||
await joinAs(page, url, "Ana");
|
||||
const col = page.getByTestId("column").first();
|
||||
await addPublicNote(col, "hola");
|
||||
await expect(col.locator(".note .author")).toHaveText("Ana");
|
||||
|
||||
await page.getByTestId("open-participants").click();
|
||||
const people = page.locator(".people");
|
||||
await expect(people).toContainText("Ana");
|
||||
|
||||
// editar mi nombre
|
||||
await page.getByTestId("edit-name").click();
|
||||
await page.getByTestId("name-input").fill("Anita");
|
||||
await page.getByTestId("name-save").click();
|
||||
await expect(people).toContainText("Anita");
|
||||
|
||||
// ocultar autores de las tarjetas (checkbox controlado por el servidor -> click)
|
||||
await page.getByTestId("show-creators").click();
|
||||
await page.mouse.click(20, 400); // cerrar el drawer pulsando en el backdrop
|
||||
await expect(col.locator(".note .author")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("action points: añadir y mover a Done", async ({ page }) => {
|
||||
const url = await createBoard(page, "Retro acciones");
|
||||
await joinAs(page, url, "Ana");
|
||||
|
||||
await page.getByTestId("open-actions").click();
|
||||
await page.getByTestId("action-input").fill("documentar el deploy");
|
||||
await page.getByTestId("action-add").click();
|
||||
|
||||
await expect(page.getByTestId("todo-list").getByTestId("action-row")).toHaveCount(1);
|
||||
|
||||
// marcar como hecho -> la fila se mueve a Done (la casilla se desmonta del To-do)
|
||||
await page.getByTestId("todo-list").getByTestId("action-done").first().click();
|
||||
await expect(page.getByTestId("todo-list").getByTestId("action-row")).toHaveCount(0);
|
||||
await expect(page.getByTestId("done-list").getByTestId("action-row")).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("export modal: previsualización con opciones", async ({ page }) => {
|
||||
const url = await createBoard(page, "Retro export");
|
||||
await joinAs(page, url, "Ana");
|
||||
const col = page.getByTestId("column").first();
|
||||
await addPublicNote(col, "algo");
|
||||
|
||||
await page.getByTestId("settings").click();
|
||||
await page.getByTestId("open-export").click();
|
||||
const preview = page.getByTestId("export-preview");
|
||||
await expect(preview).toContainText("Retro export");
|
||||
await expect(preview).toContainText("algo");
|
||||
|
||||
// desactivar autores -> desaparece el nombre del preview
|
||||
await expect(preview).toContainText("_Ana_");
|
||||
await page.getByTestId("opt-authors").uncheck();
|
||||
await expect(preview).not.toContainText("_Ana_");
|
||||
});
|
||||
|
||||
test("opciones: bloquear deja el board en solo lectura", async ({ page }) => {
|
||||
const url = await createBoard(page, "Retro lock");
|
||||
await joinAs(page, url, "Ana");
|
||||
|
||||
await page.getByTestId("settings").click();
|
||||
await page.getByTestId("opt-lock").click();
|
||||
await page.mouse.click(20, 400); // cerrar el panel
|
||||
|
||||
await expect(page.locator(".locked-banner")).toBeVisible();
|
||||
await expect(page.getByTestId("private-section")).toHaveCount(0); // sin sección privada al bloquear
|
||||
});
|
||||
Reference in New Issue
Block a user