import { expect, test } from '@playwright/test'; test('Tabla y Tarjetas cambian a la vez álbumes y canciones', async ({ page }) => { await page.goto('/musica'); await page.waitForSelector('html[data-hidratado]'); const albumes = page.getByRole('region', { name: 'Álbumes' }); const canciones = page.getByRole('region', { name: 'Canciones', exact: true }); const cantidadAlbumes = await albumes.locator('.tarjeta').count(); const cantidadCanciones = await canciones.locator('.tarjeta').count(); expect(cantidadAlbumes).toBeGreaterThan(0); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); await expect(albumes.getByRole('table')).toBeVisible(); await expect(albumes.locator('tbody tr')).toHaveCount(cantidadAlbumes); await expect(canciones.locator('tbody tr')).toHaveCount(cantidadCanciones); await expect(page.locator('.tarjeta')).toHaveCount(0); const bordes = await page.evaluate(() => { const filas = [...document.querySelectorAll('section.albumes tbody tr')]; return { filas: filas.map((fila) => getComputedStyle(fila.querySelector('th, td')!).borderBottomWidth), cancionero: getComputedStyle(document.querySelector('section.canciones')!).borderTopWidth }; }); expect(bordes.filas.slice(0, -1).every((borde) => borde === '1px')).toBe(true); expect(bordes.filas.at(-1)).toBe('0px'); expect(bordes.cancionero).toBe('0px'); await page .getByRole('navigation', { name: 'Ver catálogo' }) .getByRole('link', { name: 'Todos los álbumes' }) .click(); await expect(albumes.getByRole('table')).toBeVisible(); await expect(canciones).toHaveCount(0); await page.getByRole('button', { name: 'Tarjetas', exact: true }).click(); await expect(albumes.locator('.tarjeta')).toHaveCount(cantidadAlbumes); await expect(albumes.getByRole('table')).toHaveCount(0); await page .getByRole('navigation', { name: 'Ver catálogo' }) .getByRole('link', { name: 'Todo el catálogo' }) .click(); await expect(canciones.locator('.tarjeta')).toHaveCount(cantidadCanciones); }); test('Todos los álbumes permite elegir tabla, filtrar y abrir la ficha', async ({ page }) => { await page.goto('/musica?vista=albumes&estilo=baladas-romanticas'); await page.waitForSelector('html[data-hidratado]'); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); await page.getByLabel('Buscar en el catálogo').fill('cupido'); const tabla = page.getByRole('table', { name: 'Álbumes' }); await expect(tabla.locator('tbody tr')).toHaveCount(1); await expect(tabla.getByRole('link', { name: 'Cupido sin flechas', exact: true })).toBeVisible(); await page.getByLabel('Buscar en el catálogo').fill('zzzinexistentezzz'); await expect(page.getByText('No hay álbumes que coincidan.')).toBeVisible(); await page.getByLabel('Buscar en el catálogo').fill('cupido'); await page.getByRole('button', { name: 'Tarjetas', exact: true }).click(); await expect(page.locator('section.albumes .tarjeta')).toHaveCount(1); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); await tabla.getByRole('link', { name: 'Cupido sin flechas', exact: true }).click(); await expect(page).toHaveURL('/albumes/cupido-sin-flechas'); }); test('el álbum mantiene su reproducción al alternar tabla y tarjetas', async ({ page }) => { await page.goto('/musica?vista=albumes'); await page.waitForSelector('html[data-hidratado]'); await page .locator('audio') .evaluateAll((audios) => audios.forEach((audio) => (audio.muted = true))); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); const fila = page.getByRole('row').filter({ hasText: 'Cupido sin flechas' }); await fila.getByRole('button', { name: 'Reproducir todo' }).click(); await expect(fila.getByRole('button', { name: 'Pausar', exact: true })).toBeVisible(); const barra = page.getByRole('region', { name: 'Reproductor', exact: true }); await expect(barra).toBeVisible(); await expect .poll(async () => Number(await page.getByLabel('Posición de reproducción').inputValue())) .toBeGreaterThan(0); const tema = await page .getByRole('group', { name: 'Sonando ahora' }) .locator('a') .first() .getAttribute('href'); await page.getByRole('button', { name: 'Tarjetas', exact: true }).click(); const tarjeta = page .locator('section.albumes .tarjeta') .filter({ hasText: 'Cupido sin flechas' }); await expect(tarjeta.getByRole('button', { name: 'Pausar', exact: true })).toBeVisible(); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); await expect(fila.getByRole('button', { name: 'Pausar', exact: true })).toBeVisible(); await expect( page.getByRole('group', { name: 'Sonando ahora' }).locator('a').first() ).toHaveAttribute('href', tema!); await fila.getByRole('button', { name: 'Pausar', exact: true }).click(); await expect(barra.getByRole('button', { name: 'Reproducir', exact: true })).toBeVisible(); }); test('las tablas comparten ancho sin partir los títulos ni alterar la jerarquía tipográfica', async ({ page }) => { await page.setViewportSize({ width: 1536, height: 1000 }); await page.goto('/musica'); await page.waitForSelector('html[data-hidratado]'); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); const tablaAlbumes = page.getByRole('table', { name: 'Álbumes' }); const tablaCanciones = page.getByRole('table', { name: 'Los temas. Cada encabezado ordena por su columna.' }); const titulo = tablaCanciones.getByRole('link', { name: 'Ámame esta noche, nada más', exact: true }); const fila = tablaCanciones.getByRole('row', { name: /Ámame esta noche, nada más/ }); await expect(tablaCanciones.getByRole('columnheader', { name: 'Año' })).toBeVisible(); const aspecto = await page.evaluate(() => { const albumes = document.querySelector('section.albumes table')!; const canciones = document.querySelector('section.canciones table')!; const enlaceTituloAlbum = albumes.querySelector('a.titulo')!; const enlaceTitulo = [...canciones.querySelectorAll('a.titulo')].find( (enlace) => enlace.textContent?.trim() === 'Ámame esta noche, nada más' )!; const celdaTitulo = enlaceTitulo.closest('th')!; const enlaceAlbum = celdaTitulo.parentElement!.querySelector('td.columna-album a')!; return { anchos: [albumes.getBoundingClientRect().width, canciones.getBoundingClientRect().width], album: { tamano: getComputedStyle(enlaceTituloAlbum).fontSize, peso: getComputedStyle(enlaceTituloAlbum).fontWeight }, titulo: { alto: enlaceTitulo.getBoundingClientRect().height, linea: Number.parseFloat(getComputedStyle(enlaceTitulo).lineHeight), tamano: getComputedStyle(enlaceTitulo).fontSize, whiteSpace: getComputedStyle(enlaceTitulo).whiteSpace, vertical: getComputedStyle(celdaTitulo).verticalAlign }, pesoAlbum: getComputedStyle(enlaceAlbum).fontWeight, marco: { overflow: getComputedStyle(canciones.closest('.tabla-catalogo-marco')!).overflowX, cabecera: getComputedStyle(canciones.querySelector('thead th')!).position } }; }); expect(Math.abs(aspecto.anchos[0] - aspecto.anchos[1])).toBeLessThanOrEqual(1); expect(aspecto.album).toEqual({ tamano: '16px', peso: '400' }); expect(aspecto.titulo.alto).toBeLessThanOrEqual(aspecto.titulo.linea + 1); expect(aspecto.titulo.tamano).toBe('16px'); expect(aspecto.titulo.whiteSpace).toBe('nowrap'); expect(aspecto.titulo.vertical).toBe('top'); expect(aspecto.pesoAlbum).toBe('400'); expect(aspecto.marco).toEqual({ overflow: 'auto', cabecera: 'static' }); await expect(titulo).toBeVisible(); await expect(fila).toBeVisible(); const catalogo = page .getByRole('navigation', { name: 'Ver catálogo' }) .getByRole('link', { name: 'Todo el catálogo' }); const idiomas = page.getByRole('navigation', { name: 'Idiomas' }); await expect(catalogo).toHaveAttribute('aria-current', 'page'); await expect(idiomas.getByRole('link', { name: 'Todos los idiomas' })).toHaveCount(0); await expect(idiomas.locator('[aria-current]')).toHaveCount(0); await page.screenshot({ path: 'test-results/catalogo-tablas-1536.png', fullPage: true }); }); for (const tema of ['claro', 'oscuro']) { test(`la tabla de álbumes se adapta a escritorio y móvil en ${tema}`, async ({ page }) => { await page.addInitScript((valor) => localStorage.setItem('senzapaura:tema', valor), tema); for (const ancho of [1920, 768, 390, 320]) { await page.setViewportSize({ width: ancho, height: 1000 }); await page.goto('/musica?vista=albumes'); await page.waitForSelector('html[data-hidratado]'); await page.getByRole('button', { name: 'Tabla', exact: true }).click(); const tabla = page.getByRole('table', { name: 'Álbumes' }); await expect(tabla).toBeVisible(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe( true ); const medidas = await tabla.evaluate((el) => ({ izquierda: el.getBoundingClientRect().left, derecha: el.getBoundingClientRect().right, ancho: innerWidth })); expect(medidas.izquierda).toBeGreaterThanOrEqual(0); expect(medidas.derecha).toBeLessThanOrEqual(medidas.ancho); const portada = tabla.locator('img').first(); await portada.scrollIntoViewIfNeeded(); await expect .poll(() => portada.evaluate((img: HTMLImageElement) => img.complete && img.naturalWidth > 0) ) .toBe(true); await page.evaluate(() => { const seccion = document.querySelector('section.albumes')!.getBoundingClientRect(); const altoMenu = document.querySelector('.cabecera')!.getBoundingClientRect().height; const altoBuscador = document .querySelector('.controles-catalogo')! .getBoundingClientRect().height; window.scrollTo(0, scrollY + seccion.top - altoMenu - altoBuscador - 16); }); await page.screenshot({ path: `test-results/albumes-tabla-${tema}-${ancho}.png` }); } }); }