You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
8.2 KiB
210 lines
8.2 KiB
import { expect, test } from '@playwright/test';
|
|
|
|
test.describe('Fichas de contenido', () => {
|
|
test('la ficha de un tema publica la letra y sus datos', async ({ page }) => {
|
|
await page.goto('/canciones/prometiste');
|
|
|
|
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Prometiste');
|
|
await expect(page.getByRole('tab', { name: 'Letra' })).toHaveAttribute('aria-selected', 'true');
|
|
await expect(page.getByRole('tabpanel', { name: 'Letra' }).locator('p').first()).toContainText(
|
|
'Me prometiste besos'
|
|
);
|
|
await expect(page.getByRole('heading', { level: 2, name: 'Ficha' })).toBeVisible();
|
|
await expect(page.getByText('Acceso de escucha')).toBeVisible();
|
|
});
|
|
|
|
test('los versos conservan sus saltos de línea', async ({ page }) => {
|
|
// Sin remark-breaks, Markdown juntaría la estrofa en un único párrafo.
|
|
await page.goto('/canciones/prometiste');
|
|
|
|
const saltos = await page.locator('.texto br').count();
|
|
expect(saltos).toBeGreaterThan(5);
|
|
});
|
|
|
|
test('la letra bloquea selección, copia y menú contextual', async ({ page }) => {
|
|
await page.goto('/canciones/cuando-tus-manos-me-tocan');
|
|
|
|
const letra = page.locator('.letra.protegida');
|
|
await expect(letra).toBeVisible();
|
|
expect(await letra.evaluate((elemento) => getComputedStyle(elemento).userSelect)).toBe('none');
|
|
|
|
const eventosCancelados = await letra.evaluate((elemento) =>
|
|
['copy', 'cut', 'contextmenu', 'selectstart', 'dragstart'].map(
|
|
(tipo) => !elemento.dispatchEvent(new Event(tipo, { bubbles: true, cancelable: true }))
|
|
)
|
|
);
|
|
expect(eventosCancelados).toEqual([true, true, true, true, true]);
|
|
});
|
|
|
|
test('la bio se publica desde el Markdown de contenido', async ({ page }) => {
|
|
await page.goto('/bio');
|
|
|
|
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Biografía');
|
|
await expect(page.getByRole('heading', { level: 2, name: 'Las baladas' })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Tarjetas de canción', () => {
|
|
test('la tarjeta sitúa el tema: disco, año y estilo', async ({ page }) => {
|
|
await page.goto('/musica/baladas-romanticas');
|
|
|
|
const tarjeta = page
|
|
.locator('article')
|
|
.filter({ has: page.locator('a[href="/canciones/prometiste"]') });
|
|
await expect(tarjeta.getByRole('heading', { name: 'Prometiste' })).toBeVisible();
|
|
await expect(tarjeta.getByText(/Cupido sin flechas/)).toBeVisible();
|
|
await expect(tarjeta.getByText(/2026/)).toBeVisible();
|
|
await expect(tarjeta.getByText(/Baladas románticas/)).toBeVisible();
|
|
});
|
|
|
|
test('la tarjeta no enseña la letra', async ({ page }) => {
|
|
await page.goto('/musica/baladas-romanticas');
|
|
|
|
await expect(page.getByText('Me prometiste besos')).toHaveCount(0);
|
|
});
|
|
|
|
test('la portada no cambia de tamaño al interactuar con la tarjeta', async ({ page }) => {
|
|
await page.goto('/musica/baladas-romanticas');
|
|
|
|
const tarjeta = page
|
|
.locator('article')
|
|
.filter({ has: page.locator('a[href="/canciones/prometiste"]') });
|
|
const portada = tarjeta.locator('.tarjeta__medio img');
|
|
await expect(portada).toBeVisible();
|
|
expect(
|
|
await portada.evaluate((imagen) => ({
|
|
transformacion: getComputedStyle(imagen).transform,
|
|
transiciones: getComputedStyle(imagen).transitionProperty
|
|
}))
|
|
).toEqual({ transformacion: 'none', transiciones: 'filter' });
|
|
|
|
await tarjeta.hover();
|
|
expect(await portada.evaluate((imagen) => getComputedStyle(imagen).transform)).toBe('none');
|
|
});
|
|
|
|
test('desde la tarjeta se llega a la letra completa', async ({ page }) => {
|
|
await page.goto('/musica/baladas-romanticas');
|
|
|
|
const tarjeta = page
|
|
.locator('article')
|
|
.filter({ has: page.locator('a[href="/canciones/prometiste"]') });
|
|
await tarjeta.getByRole('link').first().click();
|
|
|
|
await expect(page).toHaveURL(/\/canciones\/prometiste$/);
|
|
await expect(page.getByRole('tab', { name: 'Letra' })).toHaveAttribute('aria-selected', 'true');
|
|
});
|
|
|
|
test('la tarjeta permite añadir la canción a una lista de reproducción', async ({ page }) => {
|
|
await page.goto('/musica/baladas-romanticas');
|
|
|
|
const tarjeta = page
|
|
.locator('article')
|
|
.filter({ has: page.locator('a[href="/canciones/prometiste"]') });
|
|
await tarjeta
|
|
.getByRole('link', { name: 'Entra con tu cuenta para añadir a una lista de reproducción' })
|
|
.click();
|
|
|
|
await expect(page.getByRole('dialog', { name: 'Entrar o crear cuenta' })).toBeVisible();
|
|
await expect(page).toHaveURL(/\/musica\/baladas-romanticas$/);
|
|
});
|
|
|
|
test('la tarjeta muestra la nota de valoración', async ({ page }) => {
|
|
await page.goto('/musica/baladas-romanticas');
|
|
|
|
const tarjeta = page
|
|
.locator('article')
|
|
.filter({ has: page.locator('a[href="/canciones/prometiste"]') });
|
|
await expect(tarjeta.getByLabel('Sin valoraciones')).toContainText('Sin valorar');
|
|
});
|
|
});
|
|
|
|
test.describe('Pestañas de la ficha', () => {
|
|
test('la letra se abre por defecto', async ({ page }) => {
|
|
await page.goto('/canciones/dorina');
|
|
|
|
await expect(page.getByRole('tab', { name: 'Letra' })).toHaveAttribute('aria-selected', 'true');
|
|
await expect(page.getByRole('tabpanel', { name: 'Letra' })).toBeVisible();
|
|
await expect(page.getByRole('tabpanel', { name: 'Vídeo' })).toBeHidden();
|
|
});
|
|
|
|
test('al pulsar una pestaña se cambia de panel', async ({ page }) => {
|
|
await page.goto('/canciones/dorina');
|
|
await page.getByRole('tab', { name: 'Vídeo' }).click();
|
|
|
|
await expect(page.getByRole('tabpanel', { name: 'Vídeo' })).toBeVisible();
|
|
await expect(page.getByRole('tabpanel', { name: 'Letra' })).toBeHidden();
|
|
await expect(page.getByText(/El vídeo se carga solo al pulsarlo/)).toBeVisible();
|
|
});
|
|
|
|
test('las flechas mueven entre pestañas', async ({ page }) => {
|
|
await page.goto('/canciones/dorina');
|
|
await page.getByRole('tab', { name: 'Letra' }).focus();
|
|
await page.keyboard.press('ArrowRight');
|
|
|
|
await expect(page.getByRole('tab', { name: 'Versiones' })).toBeFocused();
|
|
await expect(page.getByRole('tabpanel', { name: 'Versiones' })).toBeVisible();
|
|
await page.keyboard.press('ArrowRight');
|
|
await expect(page.getByRole('tab', { name: 'Vídeo' })).toBeFocused();
|
|
|
|
const pestanas = page.getByRole('tab');
|
|
await page.keyboard.press('End');
|
|
await expect(pestanas.last()).toBeFocused();
|
|
await page.keyboard.press('ArrowRight');
|
|
await expect(pestanas.first()).toBeFocused();
|
|
});
|
|
|
|
test('versiones siempre incluye la principal y el vídeo solo aparece cuando existe', async ({
|
|
page
|
|
}) => {
|
|
await page.goto('/canciones/prometiste');
|
|
|
|
await expect(page.getByRole('tab', { name: 'Versiones' })).toBeVisible();
|
|
await expect(page.getByRole('tab', { name: 'Vídeo' })).toHaveCount(0);
|
|
await expect(page.getByRole('tab', { name: 'Letra' })).toBeVisible();
|
|
});
|
|
|
|
test('se puede enlazar una pestaña concreta', async ({ page }) => {
|
|
await page.goto('/canciones/dorina#panel-videos');
|
|
|
|
await expect(page.getByRole('tab', { name: 'Vídeo' })).toHaveAttribute('aria-selected', 'true');
|
|
await expect(page.getByRole('tabpanel', { name: 'Vídeo' })).toBeVisible();
|
|
});
|
|
|
|
test('un ancla que no existe deja la pestaña de siempre', async ({ page }) => {
|
|
await page.goto('/canciones/dorina#panel-inventado');
|
|
|
|
await expect(page.getByRole('tab', { name: 'Letra' })).toHaveAttribute('aria-selected', 'true');
|
|
});
|
|
|
|
test('el contenido de las pestañas cerradas está en el HTML', async ({ page }) => {
|
|
await page.goto('/canciones/dorina');
|
|
|
|
await expect(page.getByRole('tabpanel', { name: 'Vídeo' })).toBeHidden();
|
|
await expect(page.getByText(/El vídeo se carga solo al pulsarlo/)).toBeAttached();
|
|
});
|
|
});
|
|
|
|
test.describe('Idioma de la letra', () => {
|
|
test('una letra francesa declara su idioma', async ({ page }) => {
|
|
await page.goto('/canciones/ton-silence-me-libere');
|
|
|
|
await expect(page.locator('.letra > .texto')).toHaveAttribute('lang', 'fr');
|
|
await expect(page.getByText('francés', { exact: true })).toBeVisible();
|
|
await expect(page.getByText('Traducción al español')).toHaveCount(0);
|
|
});
|
|
|
|
test('la letra francesa conserva el corte de los versos', async ({ page }) => {
|
|
await page.goto('/canciones/ton-silence-me-libere');
|
|
|
|
const saltos = await page.locator('.letra > .texto br').count();
|
|
expect(saltos).toBeGreaterThan(4);
|
|
});
|
|
|
|
test('un tema en español se queda en una sola columna', async ({ page }) => {
|
|
await page.goto('/canciones/prometiste');
|
|
|
|
await expect(page.locator('.letra.pareada')).toHaveCount(0);
|
|
await expect(page.getByText('Traducción al español')).toHaveCount(0);
|
|
});
|
|
});
|