From 20eb73d4aa822c414eba3bd70b3a0b3ae14c49d0 Mon Sep 17 00:00:00 2001 From: Uriel Jareth Date: Thu, 30 Jul 2026 00:02:17 -0600 Subject: [PATCH] Pruebas: apuntar a cualquier despliegue con BASE y no fijar el orden del tabulador playwright.config.mjs toma BASE del entorno, y cuando no es local no arranca ningun servidor. Asi la misma suite verifica el portal ya desplegado. La prueba de teclado esperaba que el segundo Tab cayera en una tarjeta de acceso; contra un servidor remoto las tarjetas todavia no estaban pintadas y el foco caia en otra cosa. Ahora espera a que existan, tabula hasta alcanzarlas y comprueba ademas que el foco se vea. Co-Authored-By: Claude Opus 5 (1M context) --- playwright.config.mjs | 27 ++++++++++++++++++--------- tests/portal.spec.mjs | 23 +++++++++++++++++++---- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/playwright.config.mjs b/playwright.config.mjs index 51fee49..fd19e36 100644 --- a/playwright.config.mjs +++ b/playwright.config.mjs @@ -1,7 +1,12 @@ import { defineConfig, devices } from '@playwright/test'; -// La demo se verifica en WebKit, en escritorio y en un iPhone real de perfil. -// Un solo worker: las pruebas comparten la base de la demo y algunas escriben. +// Por omisión se prueba el portal local. Con BASE apuntando a otra dirección +// se prueba ese despliegue y no se arranca ningún servidor: +// $env:BASE="https://instademo.urieljareth.org"; npx playwright test +const BASE = process.env.BASE ?? 'http://localhost:4180'; +const esLocal = BASE.includes('localhost') || BASE.includes('127.0.0.1'); + +// Un solo worker: las pruebas comparten la base y algunas escriben. export default defineConfig({ testDir: './tests', fullyParallel: false, @@ -9,7 +14,7 @@ export default defineConfig({ retries: 0, reporter: [['list'], ['html', { open: 'never', outputFolder: 'tests/reporte' }]], use: { - baseURL: 'http://localhost:4180', + baseURL: BASE, locale: 'es-MX', timezoneId: 'America/Mexico_City', screenshot: 'only-on-failure', @@ -19,10 +24,14 @@ export default defineConfig({ { name: 'webkit', use: { ...devices['Desktop Safari'], viewport: { width: 1440, height: 900 } } }, { name: 'webkit-movil', use: { ...devices['iPhone 13'] } }, ], - webServer: { - command: 'node server/index.mjs', - url: 'http://localhost:4180/api/auth/demo', - reuseExistingServer: true, - timeout: 30_000, - }, + ...(esLocal + ? { + webServer: { + command: 'node server/index.mjs', + url: `${BASE}/salud`, + reuseExistingServer: true, + timeout: 30_000, + }, + } + : {}), }); diff --git a/tests/portal.spec.mjs b/tests/portal.spec.mjs index c05ca93..b4d290c 100644 --- a/tests/portal.spec.mjs +++ b/tests/portal.spec.mjs @@ -503,12 +503,27 @@ test.describe('Legibilidad y responsividad', () => { test('se puede navegar con el teclado desde la entrada', async ({ page }) => { await page.goto('/'); - await page.keyboard.press('Tab'); - await page.keyboard.press('Tab'); - const enfocado = await page.evaluate(() => document.activeElement?.className ?? ''); - expect(enfocado).toContain('tarjeta-rol'); + // Hay que esperar a que las tarjetas existan: se pintan cuando responde + // la API, y tabular antes deja el foco en cualquier otra cosa. + await expect(page.locator('.tarjeta-rol').first()).toBeVisible(); + + // Se tabula hasta llegar a una tarjeta de acceso, sin fijar cuántos + // saltos hacen falta: lo que se prueba es que sea alcanzable, no la + // posición exacta en el orden. + let enTarjeta = false; + for (let i = 0; i < 8 && !enTarjeta; i++) { + await page.keyboard.press('Tab'); + enTarjeta = await page.evaluate(() => Boolean(document.activeElement?.closest?.('.tarjeta-rol'))); + } + expect(enTarjeta, 'las tarjetas de acceso deben alcanzarse con el tabulador').toBeTruthy(); + + // Y el foco tiene que verse. + const contorno = await page.evaluate(() => getComputedStyle(document.activeElement).outlineStyle); + expect(contorno).not.toBe('none'); + await page.keyboard.press('Enter'); await page.waitForURL('**/portal'); + await expect(page.locator('.barra__nav .nav-item').first()).toBeVisible(); }); test('Escape cierra la ventana de edición sin guardar', async ({ page }) => {