Files
intotheeast-com/tests/ui/stories/stories.spec.js
m038andClaude Opus 4.8 7407129812 test: re-point suite off retired standalone views
Phase-1 fallout: delete tests for deleted pages, re-point moved-behavior
tests to the trip/home page where the content now lives.

- maps.spec: keep M4/M7/M8 (home+trip maps); drop M1-3,5,6,9-11 (/map,
  /dailies & /stories mini-maps)
- map-ux: re-point MUX4/5 sort toggle to #trip-sort-toggle on trip page
- nav: N1->trip page, N2->home, drop N3 (/stats) + N5 (obsolete skip)
- dailies: T1->trip page; T2->trip page with oldest-first assertion;
  fix T3-T6 stale entry-detail selectors (.entry-* -> .journal-post-*,
  pre-existing failures from an earlier entry redesign)
- stories: S1/S5 -> trip feed story cards ([data-type=story])
- gpx-journey: load MapUtils from the trip page instead of /map
- a11y: A4 photo strips -> trip page; drop AX3 (covered by AX2)
- post/helpers: verify posted entry on the trip page (ACTIVE_TRIP_URL)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 13:58:27 +02:00

88 lines
5.0 KiB
JavaScript
Raw Permalink 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: S1S7 — story mode rendering and navigation
// Requires demo data: run `make demo-load` before this suite.
const { test, expect } = require('@playwright/test');
const TRIP_URL = '/trips/italy-2026-demo'; // stories now surface in the trip feed
const STORY_GALLERY = '/trips/italy-2026-demo/stories/val-dorcia-at-dawn'; // gallery-led: snap-gallery × 2, chapter-break, text-only pull-quote
const STORY_SCROLLY = '/trips/italy-2026-demo/stories/sorano-rock-and-time'; // scrolly-led: scrolly-section × 2, chapter-break, pull-quote with image
const DEMO_STORY = '/trips/italy-2026-demo/stories/val-dorcia-at-dawn'; // used for cross-trip hero sanity check
// ── S1: Trip feed shows story cards ──────────────────────────────────────────
test('S1: trip feed renders at least 3 story cards', async ({ page }) => {
await page.goto(TRIP_URL);
const cards = page.locator('[data-type="story"]');
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 the originating trip page ─────────────────────
test('S5: story back button navigates back to the trip page', async ({ page }) => {
// Establish history: trip page → story → back
await page.goto(TRIP_URL);
await page.locator('[data-type="story"]').first().click();
await expect(page.locator('.story-hero__img')).toBeVisible({ timeout: 8000 });
await page.locator('.story-escape').click();
// story-escape runs history.back() when history exists → back to the trip page
await expect(page).toHaveURL(/\/trips\/italy-2026-demo$/);
await expect(page.locator('.journal-post').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-at-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/);
});