test(trip-cover): cover-strip + retina-cap regression; bump user pin
- trip-header/trips-list specs now assert the cropZoom wide-strip aspect and the all-or-nothing retina rule (1x-only for sub-2w sources), and a new regression on us-canada-mex-2024 covers the reported portrait-blur - remove the orphaned AE4 test (no-photos-demo fixture was deleted) - backlog: full-res pixelfed reimport (luxury quality item) - plan: record the cover-quality follow-up + AE4 fixture removal - bump user pin -> 536ca20 (trip-description-hero cover fix) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RDS6t8wcpbwKvvrxykVQ5K
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
const TRIP_URL = '/trips/italy-2026-demo';
|
||||
const NO_PHOTOS_URL = '/trips/no-photos-demo'; // no cover_image, one image-less entry
|
||||
|
||||
const topOf = async (locator) => (await locator.boundingBox()).y;
|
||||
|
||||
@@ -62,21 +61,38 @@ test('U4/R9/AE3: banner falls back to the first journal entry image', async ({ p
|
||||
await expect(img).toBeVisible();
|
||||
const srcset = await img.getAttribute('srcset');
|
||||
expect(srcset).toContain('720w');
|
||||
expect(srcset).toContain('1440w');
|
||||
// The 1200px landscape source can't supply a non-upscaled 2x (needs ≥1440),
|
||||
// so the retina descriptor is omitted entirely — 1x only, no blurry upscale
|
||||
// and no odd intermediate width.
|
||||
expect(srcset).not.toContain('1440w');
|
||||
expect(srcset).not.toContain('1200w');
|
||||
// cropZoom hands over a wide cover strip (~3.27:1); the old cropResize gave
|
||||
// a fit-inside image the object-fit:cover box then upscaled into a blur.
|
||||
const ratio = await img.evaluate((el) => new Promise((res) => {
|
||||
const done = () => res(el.naturalWidth / el.naturalHeight);
|
||||
el.complete && el.naturalWidth ? done() : el.addEventListener('load', done, { once: true });
|
||||
}));
|
||||
expect(ratio).toBeGreaterThan(3);
|
||||
await expect(img).toHaveAttribute('alt', 'Tuscany 2026');
|
||||
});
|
||||
|
||||
// ── R9/AE4: no cover_image and no entry images → text-only header, no banner ───
|
||||
test('U4/R9/AE4: trip with no cover and no entry images renders no banner strip', async ({ page }) => {
|
||||
await page.goto(NO_PHOTOS_URL);
|
||||
// The text extras still render (the header is not blank)...
|
||||
await expect(page.locator('.home-trip-name')).toHaveText('Notes from the Road 2027');
|
||||
await expect(page.locator('.home-trip-tagline')).toBeVisible();
|
||||
// ...and there is a journal entry, so the empty-cover path is the macro's
|
||||
// fallback loop finding no image — not simply an empty trip.
|
||||
await expect(page.locator('.feed .journal-post')).toHaveCount(1);
|
||||
// With no resolvable cover, the banner strip is omitted entirely (AE4).
|
||||
await expect(page.locator('.trip-header-banner')).toHaveCount(0);
|
||||
// ── Regression: a portrait fallback source (the reported us-canada-mex-2024
|
||||
// banner) must render a sharp wide cover strip, not a blurry upscaled sliver ─
|
||||
test('U4/R9: a portrait fallback source renders a wide cover strip, not a sliver', async ({ page }) => {
|
||||
await page.goto('/trips/us-canada-mex-2024');
|
||||
const img = page.locator('.trip-header-banner img');
|
||||
await expect(img).toBeVisible();
|
||||
const srcset = await img.getAttribute('srcset');
|
||||
expect(srcset).toContain('720w');
|
||||
// 1013px portrait source — nowhere near ≥1440 — so no upscaled 2x candidate.
|
||||
expect(srcset).not.toContain('1440w');
|
||||
// cropZoom crops the tall portrait into a wide cover strip (~3.27:1); the old
|
||||
// cropResize fit it inside as a ~165px sliver the box then upscaled to a blur.
|
||||
const ratio = await img.evaluate((el) => new Promise((res) => {
|
||||
const done = () => res(el.naturalWidth / el.naturalHeight);
|
||||
el.complete && el.naturalWidth ? done() : el.addEventListener('load', done, { once: true });
|
||||
}));
|
||||
expect(ratio).toBeGreaterThan(3);
|
||||
});
|
||||
|
||||
// ── R10/AE6: the map+journal split is intact with no header above it ───────────
|
||||
|
||||
@@ -33,13 +33,22 @@ test('U3/R5/AE1: card without a tagline renders no one-liner element', async ({
|
||||
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 }) => {
|
||||
// ── R6/AE5: card cover exposes a 1x srcset; 2x only when the source is ≥2×w ────
|
||||
test('U3/R6/AE5: card cover img carries a 720w srcset, 2x omitted for a narrow source', 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');
|
||||
// The 1200px source can't supply a non-upscaled 2x (needs ≥1440), so the
|
||||
// retina descriptor is omitted — 1x only, no upscale, no intermediate width.
|
||||
expect(srcset).not.toContain('1440w');
|
||||
expect(srcset).not.toContain('1200w');
|
||||
// cropZoom cover strip (~3:1), not a cropResize fit-inside sliver.
|
||||
const ratio = await img.evaluate((el) => new Promise((res) => {
|
||||
const done = () => res(el.naturalWidth / el.naturalHeight);
|
||||
el.complete && el.naturalWidth ? done() : el.addEventListener('load', done, { once: true });
|
||||
}));
|
||||
expect(ratio).toBeGreaterThan(2.5);
|
||||
});
|
||||
|
||||
// ── R7/AE3: with no cover_image set, the card falls back to a journal image ────
|
||||
|
||||
Reference in New Issue
Block a user