// Responsive: ventanas estrechas de escritorio (pestañas Editor / Vista previa, // menú «⋯») y un iPhone real (proyecto «iphone», specs @movil). import { test, expect, estado, filasChat, filaChat, anadirTipo, irA } from "./fixtures.mjs"; async function sinScrollHorizontal(page) { const { sw, cw } = await page.evaluate(() => ({ sw: document.documentElement.scrollWidth, cw: document.documentElement.clientWidth })); expect(sw, "scroll horizontal de la página").toBeLessThanOrEqual(cw + 1); } async function dentroDeVentana(page, loc) { const caja = await loc.boundingBox(); const vw = page.viewportSize().width; expect(caja.x).toBeGreaterThanOrEqual(-1); expect(caja.x + caja.width).toBeLessThanOrEqual(vw + 1); } test.describe("Escritorio ancho", () => { test("dos columnas: editor a la izquierda y teléfono a la derecha, sin pestañas", async ({ app }) => { await expect(app.locator("#tabs-movil")).toBeHidden(); const ed = await app.locator("#panel-editor").boundingBox(); const mv = await app.locator("#panel-movil").boundingBox(); expect(ed.x + ed.width).toBeLessThanOrEqual(mv.x + 1); await expect(app.locator("#btn-exportar")).toBeVisible(); await sinScrollHorizontal(app); }); }); for (const ancho of [1024, 900, 700]) { test.describe(`Ventana de ${ancho}px`, () => { test.use({ viewport: { width: ancho, height: 800 } }); test("sin scroll horizontal y el iPhone cabe entero", async ({ app }) => { await sinScrollHorizontal(app); if (ancho <= 900) await app.locator("#tab-vista").click(); await dentroDeVentana(app, app.locator("#iphone")); await expect(app.locator("#composer-input")).toBeVisible(); }); if (ancho <= 900) { test("pestañas Editor / Vista previa y menú «⋯»", async ({ app }) => { await expect(app.locator("#tabs-movil")).toBeVisible(); await app.locator("#tab-editor").click(); await expect(app.locator("#tab-editor")).toHaveAttribute("aria-selected", "true"); await expect(app.locator("#panel-editor")).toBeVisible(); await expect(app.locator("#panel-movil")).toBeHidden(); const id = await anadirTipo(app, "text"); await app.locator("#btn-ver-telefono").click(); await expect(app.locator("#tab-vista")).toHaveAttribute("aria-selected", "true"); await expect(app.locator("#panel-movil")).toBeVisible(); await expect(filaChat(app, id)).toBeVisible(); // la pestaña elegida se recuerda await app.locator("#tab-editor").click(); await app.reload(); await expect(app.locator("#tab-editor")).toHaveAttribute("aria-selected", "true"); // menú «⋯» con las acciones secundarias await app.locator("#btn-mas").click(); await expect(app.locator("#btn-mas")).toHaveAttribute("aria-expanded", "true"); await expect(app.locator("#btn-exportar")).toBeVisible(); await app.keyboard.press("Escape"); await expect(app.locator("#btn-mas")).toHaveAttribute("aria-expanded", "false"); }); } }); } test.describe("iPhone @movil", () => { test("carga sin scroll horizontal con la vista previa por defecto @movil", async ({ app }) => { await expect(app.locator("#tabs-movil")).toBeVisible(); await expect(app.locator("#tab-vista")).toHaveAttribute("aria-selected", "true"); await sinScrollHorizontal(app); await dentroDeVentana(app, app.locator("#iphone")); const n = (await estado(app)).mensajes.length; await expect(filasChat(app)).toHaveCount(n); }); test("tocar un quick reply y una fila de la lista funciona con el dedo @movil", async ({ app }) => { await app.evaluate(() => WAM.setVelocidad(2)); const e = await estado(app); const btns = e.mensajes.find((m) => m.tipo === "buttons"); const b = filaChat(app, btns.id).locator("button.qr-btn").first(); await b.scrollIntoViewIfNeeded(); await b.tap(); await expect(app.locator('#chat-cuerpo li.out[data-id^="s"]').last()).toContainText("Horarios"); await expect(app.locator('#chat-cuerpo li.in[data-id^="s"]').last()).toContainText("lunes a viernes", { timeout: 6000 }); const lista = e.mensajes.find((m) => m.tipo === "list"); const bl = filaChat(app, lista.id).locator("button.qr-btn"); await bl.scrollIntoViewIfNeeded(); await bl.tap(); await expect(app.locator("#sheet")).toBeVisible(); await dentroDeVentana(app, app.locator("#sheet .sheet-panel")); await app.locator("#sheet .sheet-fila").first().tap(); await expect(app.locator('#chat-cuerpo li.out[data-id^="s"]').last()).toContainText("Espresso double"); }); test("composer desde el teclado del móvil @movil", async ({ app }) => { await app.locator("#composer-input").tap(); await app.locator("#composer-input").fill("Hola desde el iPhone"); await app.locator("#composer-enviar").tap(); await expect(app.locator('#chat-cuerpo li.out[data-id^="s"]').last()).toContainText("Hola desde el iPhone"); }); test("editar en la pestaña Editor y ver el resultado en Vista previa @movil", async ({ app }) => { await app.locator("#tab-editor").tap(); await expect(app.locator("#panel-editor")).toBeVisible(); await sinScrollHorizontal(app); const id = await anadirTipo(app, "location"); await app.locator('#lista-mensajes [data-ruta$=".nombre"]').last().fill("Local móvil"); await app.locator("#tab-vista").tap(); await expect(filaChat(app, id).locator(".loc-nombre")).toHaveText("Local móvil"); }); test("menú «⋯», tema y presentación en el móvil @movil", async ({ app }) => { await app.locator("#btn-tema").tap(); await expect(app.locator("body")).toHaveAttribute("data-tema", "oscuro"); await app.locator("#btn-mas").tap(); await expect(app.locator("#btn-demos")).toBeVisible(); await app.locator("#btn-demos").tap(); await expect(app.locator("#dlg-demos")).toBeVisible(); await dentroDeVentana(app, app.locator("#dlg-demos")); await app.locator("#dlg-demos .wam-dlg-cerrar").tap(); await app.locator("#btn-presentacion").tap(); await expect(app.locator("body")).toHaveClass(/presentacion/); await dentroDeVentana(app, app.locator("#iphone")); await app.locator("#btn-presentacion").tap(); await expect(app.locator("body")).not.toHaveClass(/presentacion/); }); test("por file:// también funciona en el móvil @movil", async ({ page }) => { const { URL_FILE } = await import("./fixtures.mjs"); await irA(page, URL_FILE); await expect(page.locator("#chat-nombre")).toHaveText("Café Aurora"); }); });