// @ts-check // Tests: U3 — trip-list card one-liner + retina cover (R5, R6, R7, R11, R14) const { test, expect } = require('@playwright/test'); const DEMO_HREF = '/trips/italy-2026-demo'; // has a tagline, no cover_image (entry-image fallback) const NO_TAGLINE_HREF = '/trips/slovenia-2024'; // a real trip with no tagline const demoCard = (page) => page.locator(`.trip-card[href="${DEMO_HREF}"]`); // ── R5: one-liner renders between the title and the meta line ────────────────── test('U3/R5: card with a tagline shows a one-liner between title and meta', async ({ page }) => { await page.goto('/trips'); const card = demoCard(page); const tagline = card.locator('.trip-card-tagline'); await expect(tagline).toBeVisible(); await expect(tagline).toHaveText(/southern Tuscany by bike/); const order = await card.evaluate((el) => Array.from(el.children).map((c) => c.className.split(' ')[0]) ); expect(order.indexOf('trip-card-title')).toBeLessThan(order.indexOf('trip-card-tagline')); expect(order.indexOf('trip-card-tagline')).toBeLessThan(order.indexOf('trip-card-meta')); }); // ── R5/AE1: a card with no tagline renders no one-liner element ──────────────── test('U3/R5/AE1: card without a tagline renders no one-liner element', async ({ page }) => { await page.goto('/trips'); const card = page.locator(`.trip-card[href="${NO_TAGLINE_HREF}"]`); await expect(card).toBeVisible(); await expect(card.locator('.trip-card-tagline')).toHaveCount(0); }); // ── R6/AE5: card cover exposes a retina srcset (720w + 1440w candidates) ─────── test('U3/R6/AE5: card cover img carries a 720w/1440w srcset', async ({ page }) => { await page.goto('/trips'); const img = demoCard(page).locator('.trip-card-cover img'); const srcset = await img.getAttribute('srcset'); expect(srcset).toContain('720w'); expect(srcset).toContain('1440w'); }); // ── R7/AE3: with no cover_image set, the card falls back to a journal image ──── test('U3/R7/AE3: card with no cover_image uses the first journal entry image', async ({ page }) => { await page.goto('/trips'); // The demo trip sets cover_image: '' so the cover comes from the fallback. const img = demoCard(page).locator('.trip-card-cover img'); await expect(img).toBeVisible(); const src = await img.getAttribute('src'); expect(src).toMatch(/\/images\/.+\.(jpg|jpeg|png|webp)/i); }); // ── R14: cover alt text equals the trip title ───────────────────────────────── test('U3/R14: card cover alt equals the trip title', async ({ page }) => { await page.goto('/trips'); const img = demoCard(page).locator('.trip-card-cover img'); await expect(img).toHaveAttribute('alt', 'Tuscany 2026'); });