import { expect, test, type Page } from '@playwright/test'; /** * Abre el formulario y espera a que la página sea interactiva. * * La espera no es adorno. `page.goto` vuelve cuando la página ha cargado, no * cuando Svelte ha tomado el control, y al tomarlo reescribe el valor de cada * `input` con el del componente, que está vacío: lo que se teclee antes de ese * instante desaparece. Fallaba solo con la máquina cargada, así que se caía en * la tanda completa y pasaba al repetir la prueba a solas. * * Un reintento no lo arregla —comprobar que el texto está puesto no impide que * lo borren un instante después—, así que el layout marca el momento con * `data-hidratado` y aquí se espera a él. */ async function abrirFormulario(page: Page) { await page.goto('/contacto'); await page.locator('html[data-hidratado]').waitFor(); } /** Rellena el formulario con datos válidos, salvo lo que se sobrescriba. */ async function rellenar( page: Page, campos: Partial<{ nombre: string; email: string; motivo: string; mensaje: string }> = {} ) { await page.getByLabel('Nombre').fill(campos.nombre ?? 'Ana Ruiz'); await page.getByLabel('Correo electrónico').fill(campos.email ?? 'ana@example.com'); await page.getByLabel('Motivo').selectOption(campos.motivo ?? 'colaboracion'); await page .getByLabel('Mensaje') .fill(campos.mensaje ?? 'Me gustaría hablar contigo sobre una colaboración para un disco.'); } test.describe('Formulario de contacto', () => { test('la validación del servidor devuelve los errores por campo', async ({ page }) => { await abrirFormulario(page); // "A" y "Hola" pasan la validación del navegador y fallan en el servidor, // que es justo lo que interesa comprobar aquí. await rellenar(page, { nombre: 'A', mensaje: 'Hola' }); await page.getByRole('button', { name: 'Enviar mensaje' }).click(); await expect(page.getByText('Indica tu nombre.')).toBeVisible(); await expect(page.getByText(/Cuenta un poco más/)).toBeVisible(); }); test('lo escrito no se pierde cuando la validación falla', async ({ page }) => { await abrirFormulario(page); await rellenar(page, { nombre: 'A' }); await page.getByRole('button', { name: 'Enviar mensaje' }).click(); await expect(page.getByText('Indica tu nombre.')).toBeVisible(); await expect(page.getByLabel('Correo electrónico')).toHaveValue('ana@example.com'); await expect(page.getByLabel('Motivo')).toHaveValue('colaboracion'); await expect(page.getByLabel('Mensaje')).not.toBeEmpty(); }); test('el campo trampa descarta los envíos automáticos', async ({ page }) => { await abrirFormulario(page); await rellenar(page); // Solo un cliente automático rellena este campo: está fuera de la vista // y fuera del recorrido de tabulación. await page.evaluate(() => { const trampa = document.querySelector('#companiaWeb'); if (trampa instanceof HTMLInputElement) trampa.value = 'https://spam.example'; }); await page.getByRole('button', { name: 'Enviar mensaje' }).click(); await expect(page.getByText('No se ha podido enviar el mensaje.')).toBeVisible(); }); test('un envío válido no muestra errores de campo', async ({ page }) => { await abrirFormulario(page); await rellenar(page); await page.getByRole('button', { name: 'Enviar mensaje' }).click(); // El resultado final depende de si hay proveedor de correo configurado // (ver src/lib/server/correo.ts), así que solo se comprueba que la // validación ha quedado atrás. await expect(page.getByText('Indica tu nombre.')).toHaveCount(0); await expect(page.getByText(/Cuenta un poco más/)).toHaveCount(0); await expect(page.getByText('Ese correo no parece válido.')).toHaveCount(0); }); });