Files
intotheeast-com/tests/ui/stories.spec.js
T
m038 0729e4ea1d fix: update tests for demo reorganisation (italy-2026-demo, central-asia ordering, japan real entry)
- dailies T2: switch ordering test to central-asia-2023 (pixelfed-1 oldest, pixelfed-22 newest)
- dailies T3-T6: update KNOWN_SLUG/TITLE/CITY/COUNTRY to the real japan entry (2026-06-17)
- stories S1-S7: update all italy-2025 URLs to italy-2026-demo
- stories S5/S6: fix URL regex and use val-dorcia-dawn for hero sanity check
- maps M5/M6: point Italy GPX map tests to italy-2026-demo (has markers + GPX)
- global-setup: run make demo-load before tests so italy-2026-demo always exists
- post P2: add retries:1 + test.setTimeout(60s) for intermittent FilePond upload
- user: story template hero fallback for media.types config override (see user commit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 16:31:37 +02:00

88 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// @ts-check
// Tests: S1S6 — story mode rendering and navigation
// Requires demo data: run `make demo-load` before this suite.
const { test, expect } = require('@playwright/test');
const STORIES_URL = '/trips/italy-2026-demo/stories';
const STORY_GALLERY = '/trips/italy-2026-demo/stories/val-dorcia-dawn'; // gallery-led: snap-gallery × 2, chapter-break, text-only pull-quote
const STORY_SCROLLY = '/trips/italy-2026-demo/stories/long-climb-montalcino'; // scrolly-led: scrolly-section × 2, chapter-break, pull-quote with image
const DEMO_STORY = '/trips/italy-2026-demo/stories/val-dorcia-dawn'; // used for cross-trip hero sanity check
// ── S1: Stories listing shows cards ──────────────────────────────────────────
test('S1: stories listing renders at least 3 story cards', async ({ page }) => {
await page.goto(STORIES_URL);
const cards = page.locator('.story-card');
await expect(cards.first()).toBeVisible({ timeout: 5000 });
const count = await cards.count();
expect(count, 'At least 3 story cards').toBeGreaterThanOrEqual(3);
});
// ── S2: Gallery-led story — hero image + snap-gallery + chapter-break + text-only pull-quote ──
test('S2: gallery-led story renders hero, snap-gallery, chapter-break, text-only pull-quote', async ({ page }) => {
await page.goto(STORY_GALLERY);
// Hero: real image rendered, no placeholder
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
await expect(page.locator('.story-hero__img-placeholder')).toHaveCount(0);
// Snap-gallery (there are two in this story)
const galleries = page.locator('.pgallery');
await expect(galleries.first()).toBeVisible();
expect(await galleries.count(), 'Two snap-galleries').toBe(2);
// Chapter-break
await expect(page.locator('.chapter-break')).toBeVisible();
// Text-only pull-quote (no background image variant)
await expect(page.locator('.pull-quote__inner--no-image')).toBeVisible();
});
// ── S3: Scrolly-led story — two scrolly-sections + pull-quote with image ─────
test('S3: scrolly-led story renders two scrolly-sections and pull-quote with background image', async ({ page }) => {
await page.goto(STORY_SCROLLY);
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
// Two scrolly-sections
const scrollySections = page.locator('.scrolly');
await expect(scrollySections.first()).toBeVisible();
expect(await scrollySections.count(), 'Two scrolly-sections').toBe(2);
// Pull-quote with background image
await expect(page.locator('.pull-quote__bg')).toBeVisible();
});
// ── S4: Scrolly story loads without JS errors (Scrollama CDN) ────────────────
test('S4: scrolly story page loads without JS errors', async ({ page }) => {
const errors = [];
page.on('pageerror', e => errors.push(e.message));
await page.goto(STORY_SCROLLY);
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
await page.waitForTimeout(1000);
expect(errors, 'No JS errors on story page').toHaveLength(0);
});
// ── S5: Back button returns to stories listing ────────────────────────────────
test('S5: back button navigates back to stories listing', async ({ page }) => {
// Establish history: listing → story → back
await page.goto(STORIES_URL);
await page.locator('.story-card').first().click();
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
await page.locator('.story-escape').click();
// After history.back(), URL should be the stories listing
await expect(page).toHaveURL(/italy-2026-demo\/stories$/);
await expect(page.locator('.story-card').first()).toBeVisible();
});
// ── S6: Demo story — hero image sanity check ─────────────────────────────────
test('S6: demo story renders hero image without placeholder', async ({ page }) => {
await page.goto(DEMO_STORY);
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
await expect(page.locator('.story-hero__img-placeholder')).toHaveCount(0);
});
// ── S7: Story body back link is styled as a back-pill ────────────────────────
test('S7: story body back link has back-pill class', async ({ page }) => {
await page.goto('/trips/italy-2026-demo/stories/val-dorcia-dawn');
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
// Scroll past the hero to reveal the story body
await page.evaluate(() => window.scrollBy(0, window.innerHeight * 1.5));
await page.waitForTimeout(300);
const bodyBack = page.locator('.story-footer .back-pill');
await expect(bodyBack).toBeAttached();
await expect(bodyBack).toHaveText(/← Back/);
});