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.
159 lines
5.7 KiB
159 lines
5.7 KiB
import { expect, test } from '@playwright/test';
|
|
|
|
test.describe('Blog', () => {
|
|
test('está en la navegación principal', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page
|
|
.getByRole('navigation', { name: 'Principal' })
|
|
.getByRole('link', { name: 'Blog' })
|
|
.click();
|
|
|
|
await expect(page).toHaveURL('/blog');
|
|
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Blog');
|
|
});
|
|
|
|
test('las entradas van de la más reciente a la más antigua', async ({ page }) => {
|
|
await page.goto('/blog');
|
|
|
|
const fechas = await page
|
|
.locator('time')
|
|
.evaluateAll((ts) => ts.map((t) => t.getAttribute('datetime') ?? ''));
|
|
expect(fechas.length).toBeGreaterThan(1);
|
|
expect(fechas).toEqual([...fechas].sort().reverse());
|
|
});
|
|
|
|
test('una entrada se lee entera y encadena con la anterior', async ({ page }) => {
|
|
await page.goto('/blog');
|
|
await page.getByRole('link', { name: 'Escribir en un estilo que no es el tuyo' }).click();
|
|
|
|
await expect(page).toHaveURL('/blog/escribir-en-un-estilo-ajeno');
|
|
await expect(
|
|
page.getByRole('heading', { level: 2, name: 'No es el ritmo, es el registro' })
|
|
).toBeVisible();
|
|
|
|
await page.getByRole('link', { name: /Anterior/ }).click();
|
|
await expect(page.getByRole('heading', { level: 1 })).toHaveText(
|
|
'Lo que no cabe en una canción'
|
|
);
|
|
});
|
|
|
|
test('una entrada enlaza los temas de los que habla', async ({ page }) => {
|
|
await page.goto('/blog/lo-que-no-cabe-en-una-cancion');
|
|
|
|
await expect(page.getByRole('heading', { name: 'De lo que habla' })).toBeVisible();
|
|
await expect(page.getByRole('heading', { name: 'Como si nada' })).toBeVisible();
|
|
});
|
|
|
|
test('las etiquetas de una entrada llevan al mismo sitio que las de un tema', async ({
|
|
page
|
|
}) => {
|
|
await page.goto('/blog/lo-que-no-cabe-en-una-cancion');
|
|
await page.getByRole('link', { name: 'Desamor', exact: true }).click();
|
|
|
|
await expect(page).toHaveURL('/etiquetas/desamor');
|
|
});
|
|
|
|
test('una entrada que no existe da 404', async ({ page }) => {
|
|
const respuesta = await page.goto('/blog/no-existe');
|
|
expect(respuesta?.status()).toBe(404);
|
|
});
|
|
});
|
|
|
|
test.describe('Valoraciones', () => {
|
|
test('quien no ha entrado ve la media y una invitación', async ({ page }) => {
|
|
await page.goto('/canciones/como-si-nada');
|
|
|
|
const bloque = page.getByRole('region', { name: 'Valoración' });
|
|
await expect(bloque).toBeVisible();
|
|
await expect(bloque.getByRole('link', { name: 'Entra con tu cuenta' })).toBeVisible();
|
|
// Sin sesión no se puede votar: no hay estrellas que pulsar.
|
|
await expect(bloque.getByRole('radio')).toHaveCount(0);
|
|
});
|
|
|
|
test('la invitación vuelve al tema tras entrar', async ({ page }) => {
|
|
await page.goto('/canciones/como-si-nada');
|
|
|
|
await expect(
|
|
page
|
|
.getByRole('region', { name: 'Valoración' })
|
|
.getByRole('link', { name: 'Entra con tu cuenta' })
|
|
).toHaveAttribute('href', /volverA=%2Fcanciones%2Fcomo-si-nada/);
|
|
});
|
|
|
|
test('un POST sin origen lo para el CSRF, antes de llegar a la acción', async ({ request }) => {
|
|
const respuesta = await request.post('/canciones/como-si-nada?/valorar', {
|
|
form: { puntuacion: '5' }
|
|
});
|
|
|
|
expect(respuesta.status()).toBe(403);
|
|
});
|
|
|
|
test('sin sesión, la acción de valorar se rechaza', async ({ request, baseURL }) => {
|
|
// Con el origen correcto la petición llega a la acción, así que lo que se
|
|
// comprueba aquí es su guardia y no la del framework. La interfaz no
|
|
// enseña estrellas sin sesión, pero el formulario se puede enviar a mano.
|
|
//
|
|
// La respuesta es el resultado de la acción en JSON, no la página: el
|
|
// código de `fail` viaja dentro, y el de la respuesta HTTP es 200.
|
|
const respuesta = await request.post('/canciones/como-si-nada?/valorar', {
|
|
headers: { origin: baseURL ?? '' },
|
|
form: { puntuacion: '5' }
|
|
});
|
|
|
|
const resultado = JSON.parse(await respuesta.text());
|
|
expect(resultado.type).toBe('failure');
|
|
expect(resultado.status).toBe(401);
|
|
});
|
|
|
|
test('una puntuación fuera de rango tampoco pasa', async ({ request, baseURL }) => {
|
|
// Sin sesión gana la guardia de la cuenta; que el rango se comprueba está
|
|
// cubierto aparte, en las pruebas de `aPuntuacion`.
|
|
const respuesta = await request.post('/canciones/como-si-nada?/valorar', {
|
|
headers: { origin: baseURL ?? '' },
|
|
form: { puntuacion: '9' }
|
|
});
|
|
|
|
expect(JSON.parse(await respuesta.text()).type).toBe('failure');
|
|
});
|
|
});
|
|
|
|
test.describe('Favoritos', () => {
|
|
test('quien no ha entrado ve el corazón, pero lleva a entrar', async ({ page }) => {
|
|
await page.goto('/canciones/como-si-nada');
|
|
|
|
// No se esconde: la interfaz no cambia de forma según quién mira.
|
|
const enlace = page.getByRole('link', {
|
|
name: 'Entra con tu cuenta para guardar en favoritos'
|
|
});
|
|
await expect(enlace).toBeVisible();
|
|
await expect(enlace).toHaveAttribute('href', /volverA=%2Fcanciones%2Fcomo-si-nada/);
|
|
});
|
|
|
|
test('la lista invita a entrar si no hay sesión', async ({ page }) => {
|
|
await page.goto('/favoritos');
|
|
|
|
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Favoritos');
|
|
await expect(page.getByRole('link', { name: 'Entra con tu cuenta' })).toBeVisible();
|
|
});
|
|
|
|
test('sin sesión, marcar un favorito se rechaza', async ({ request, baseURL }) => {
|
|
const respuesta = await request.post('/favoritos?/marcar', {
|
|
headers: { origin: baseURL ?? '' },
|
|
form: { cancion: 'como-si-nada', volverA: '/favoritos' }
|
|
});
|
|
|
|
const resultado = JSON.parse(await respuesta.text());
|
|
expect(resultado.type).toBe('failure');
|
|
expect(resultado.status).toBe(401);
|
|
});
|
|
|
|
test('un tema inventado no se puede guardar', async ({ request, baseURL }) => {
|
|
const respuesta = await request.post('/favoritos?/marcar', {
|
|
headers: { origin: baseURL ?? '' },
|
|
form: { cancion: 'no-existe', volverA: '/favoritos' }
|
|
});
|
|
|
|
expect(JSON.parse(await respuesta.text()).type).toBe('failure');
|
|
});
|
|
});
|