diff --git a/e2e/taller.e2e.ts b/e2e/taller.e2e.ts index 2ac584b..127b881 100644 --- a/e2e/taller.e2e.ts +++ b/e2e/taller.e2e.ts @@ -65,7 +65,7 @@ test.describe('Taller de letras', () => { await page.goto('/taller/bolero'); const datos = (await page.locator('.datos').boundingBox())!; - const texto = (await page.locator('.texto').boundingBox())!; + const texto = (await page.locator('.lectura .texto').boundingBox())!; expect(datos.width).toBeGreaterThan(texto.width * 1.4); expect(Math.abs(datos.x - texto.x)).toBeLessThan(2); @@ -122,10 +122,82 @@ test.describe('Taller de letras', () => { }); test('un principio no enseña ficha de creación', async ({ page }) => { - // La ficha es de los estilos; en un principio sería un panel vacío. + // La ficha es de los estilos; en un principio serían bloques vacíos. await page.goto('/taller/el-estribillo'); - await expect(page.getByRole('heading', { level: 2, name: 'De un vistazo' })).toHaveCount(0); + await expect(page.locator('.datos')).toHaveCount(0); + await expect(page.locator('.instrumentos')).toHaveCount(0); + await expect(page.getByRole('heading', { level: 2, name: 'Linaje' })).toHaveCount(0); + }); + + /* + * Lo que sigue solo existe desde que el taller lee de la base: en un archivo + * de Markdown no cabía la instrumentación con el peso de cada instrumento, + * ni los letristas con sus fechas, ni de qué géneros viene este. + */ + + test('la ficha dice qué país es la cuna y cuáles lo adoptaron', async ({ page }) => { + await page.goto('/taller/bolero'); + + const paises = page.locator('.paises li'); + await expect(paises).toHaveCount(6); + // La cuna va primero aunque alfabéticamente no le toque. + await expect(paises.first()).toContainText('Cuba'); + await expect(paises.first()).toContainText('cuna'); + await expect(paises.filter({ hasText: 'México' })).not.toContainText('cuna'); + }); + + test('la instrumentación distingue lo esencial de lo ocasional', async ({ page }) => { + await page.goto('/taller/bolero'); + + const filas = page.locator('.instrumentos li'); + await expect(filas.filter({ hasText: 'Guitarra' })).toContainText('esencial'); + await expect(filas.filter({ hasText: 'Piano' })).toContainText('ocasional'); + // El papel es lo que hace útil el dato: no basta con enumerar instrumentos. + await expect(filas.filter({ hasText: 'Requinto' })).toContainText('adornos'); + }); + + test('los letristas traen país, años y papel', async ({ page }) => { + await page.goto('/taller/tango'); + + const gardel = page.locator('.personas li').filter({ hasText: 'Carlos Gardel' }); + await expect(gardel).toContainText('Argentina · 1890–1935'); + // «interprete» se guarda sin tilde, pero se lee con ella. + await expect(gardel).toContainText('intérprete'); + }); + + test('las obras de referencia se fechan y se acreditan', async ({ page }) => { + await page.goto('/taller/bolero'); + + const primera = page.locator('.obras li').first(); + await expect(primera).toContainText('1883'); + await expect(primera).toContainText('Tristezas'); + await expect(primera).toContainText('José «Pepe» Sánchez'); + + // Un fragmento de letra ajena solo se sostiene si se dice por qué está. + await expect(page.locator('.obras')).toHaveCount(1); + await expect(page.getByText('derecho de cita')).toBeVisible(); + }); + + test('el linaje no enlaza a un género sin capítulo', async ({ page }) => { + /* + * El bolero-son existe en la base porque el bolero y el son confluyen en + * él, pero nadie ha escrito su ficha. Enlazarlo mandaba a un 404. + */ + await page.goto('/taller/bolero'); + + const linaje = page.locator('.rama'); + await expect(linaje.getByRole('link', { name: 'Bachata' })).toBeVisible(); + await expect(linaje.getByText('Bolero-son')).toBeVisible(); + await expect(linaje.getByRole('link', { name: 'Bolero-son' })).toHaveCount(0); + }); + + test('se avisa de lo que aún no ha revisado nadie', async ({ page }) => { + // La musicología la reunió un modelo y la ficha se publica con el nombre + // del titular. Callarlo sería lo cómodo. + await page.goto('/taller/bolero'); + + await expect(page.locator('.sin-revisar')).toContainText('pendientes de revisión'); }); test('el taller está en la navegación principal', async ({ page }) => { diff --git a/src/lib/components/BotonesDeProveedor.svelte b/src/lib/components/BotonesDeProveedor.svelte index d9dc959..e659705 100644 --- a/src/lib/components/BotonesDeProveedor.svelte +++ b/src/lib/components/BotonesDeProveedor.svelte @@ -12,6 +12,7 @@ * no se hace; y las dos marcas exigen su color exacto, que no se respeta si * se tiñe un icono genérico. */ + import { resolve } from '$app/paths'; import type { Proveedor } from '$lib/types'; let { @@ -22,15 +23,24 @@ const NOMBRES: Record = { google: 'Google', facebook: 'Facebook' }; - const enlace = (proveedor: Proveedor) => - `/acceso/${proveedor}?volverA=${encodeURIComponent(volverA)}`; + /* + * Por `resolve` y no escrita a mano: si la ruta cambia de nombre, esto deja + * de compilar en vez de llevar a un 404 solo al pulsar. Va en el propio + * atributo porque la regla de lint solo sabe seguir `resolve` cuando lo ve + * ahí; metido en una función, no puede comprobar nada. + */ + const volver = $derived(encodeURIComponent(volverA)); {#if proveedores.length > 0}