Files
intotheeast-com/tests/ui/post.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

140 lines
6.2 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: P1P5 — form submission happy paths
// Replaces post-with-photo.spec.js
const { test, expect } = require('@playwright/test');
const path = require('path');
const fs = require('fs');
const { waitForFilePondUpload, cleanupEntry, findEntry, readEntryMd, TRACKER_DIR } = require('./helpers');
const TEST_PHOTO = path.join(__dirname, '../fixtures/test-photo.jpg');
// Track slugs created per test for cleanup
const created = [];
test.afterAll(() => {
created.forEach(cleanupEntry);
});
// ── P1: Post without photo ─────────────────────────────────────────────────────
test('P1: post text-only entry → created on disk and visible on /dailies', async ({ page }) => {
const tag = `p1-${Date.now()}`;
const title = `UI Test ${tag}`;
await page.goto('/post');
await page.fill('input[name="data[title]"]', title);
await page.fill('textarea[name="data[content]"]', 'Text-only test entry. Safe to delete.');
await page.fill('input[name="data[location_city]"]', 'Testville');
await page.fill('input[name="data[location_country]"]', 'Testland');
await page.locator('.btn-post').evaluate(el => el.click());
await page.waitForSelector('.form-messages, .notices', { timeout: 15_000 });
const entryDir = findEntry(tag);
expect(entryDir, 'Entry folder should exist on disk').toBeTruthy();
created.push(tag);
const md = readEntryMd(entryDir);
expect(md).toContain(tag);
// No photo expected
const photos = fs.readdirSync(entryDir).filter(f => /\.(jpg|jpeg|png|webp|heic)$/i.test(f));
expect(photos.length, 'Text-only entry should have no photos').toBe(0);
await page.goto('/trips/japan-korea-2026/dailies');
await expect(page.locator('body')).toContainText(tag);
});
// ── P2: Post with photo ────────────────────────────────────────────────────────
test('P2: post entry with photo → photo saved in entry folder and visible on /dailies', { retries: 1 }, async ({ page }) => {
test.setTimeout(60_000);
const tag = `p2-${Date.now()}`;
const title = `UI Test ${tag}`;
await page.goto('/post');
await page.fill('input[name="data[title]"]', title);
await page.fill('textarea[name="data[content]"]', 'Photo test entry. Safe to delete.');
await page.fill('input[name="data[location_city]"]', 'Testville');
await page.fill('input[name="data[location_country]"]', 'Testland');
await page.locator('input.filepond--browser').setInputFiles(TEST_PHOTO);
await waitForFilePondUpload(page);
await page.locator('.btn-post').evaluate(el => el.click());
await page.waitForSelector('.form-messages, .notices', { timeout: 15_000 });
const entryDir = findEntry(tag);
expect(entryDir, 'Entry folder should exist on disk').toBeTruthy();
created.push(tag);
const md = readEntryMd(entryDir);
expect(md).toContain(tag);
const photos = fs.readdirSync(entryDir).filter(f => /\.(jpg|jpeg|png|webp|heic)$/i.test(f));
expect(photos.length, 'At least one photo should be saved').toBeGreaterThan(0);
await page.goto('/trips/japan-korea-2026/dailies');
await expect(page.locator('body')).toContainText(tag);
});
// ── P3: Post with city + country ──────────────────────────────────────────────
test('P3: post entry with city/country → frontmatter contains location', async ({ page }) => {
const tag = `p3-${Date.now()}`;
const title = `UI Test ${tag}`;
await page.goto('/post');
await page.fill('input[name="data[title]"]', title);
await page.fill('textarea[name="data[content]"]', 'Location test. Safe to delete.');
await page.fill('input[name="data[location_city]"]', 'Kyoto');
await page.fill('input[name="data[location_country]"]', 'Japan');
await page.locator('.btn-post').evaluate(el => el.click());
await page.waitForSelector('.form-messages, .notices', { timeout: 15_000 });
const entryDir = findEntry(tag);
expect(entryDir, 'Entry folder should exist on disk').toBeTruthy();
created.push(tag);
const md = readEntryMd(entryDir);
expect(md).toContain('Kyoto');
expect(md).toContain('Japan');
});
// ── P4: Post with lat/lng ─────────────────────────────────────────────────────
test('P4: post entry with lat/lng → coordinates saved in frontmatter', async ({ page }) => {
const tag = `p4-${Date.now()}`;
const title = `UI Test ${tag}`;
await page.goto('/post');
await page.fill('input[name="data[title]"]', title);
await page.fill('textarea[name="data[content]"]', 'GPS test. Safe to delete.');
// lat/lng fields are CSS-hidden (designed to be filled by the Get Location button);
// set values directly via JS to simulate what the button would do.
await page.evaluate(() => {
document.querySelector('input[name="data[lat]"]').value = '35.6762';
document.querySelector('input[name="data[lng]"]').value = '139.6503';
});
await page.locator('.btn-post').evaluate(el => el.click());
await page.waitForSelector('.form-messages, .notices', { timeout: 15_000 });
const entryDir = findEntry(tag);
expect(entryDir, 'Entry folder should exist on disk').toBeTruthy();
created.push(tag);
const md = readEntryMd(entryDir);
expect(md).toContain('35.6762');
expect(md).toContain('139.6503');
});
// ── P5: "Get Location" button fills lat/lng (TDD — fails until feature built) ──
test('P5: Get Location button fills lat/lng from browser geolocation', async ({ page, context }) => {
await context.grantPermissions(['geolocation']);
await context.setGeolocation({ latitude: 35.6762, longitude: 139.6503 });
await page.goto('/post');
await page.click('#get-location');
// Allow a moment for the geolocation callback to fire
await page.waitForTimeout(500);
await expect(page.locator('input[name="data[lat]"]')).toHaveValue(/35\.67/);
await expect(page.locator('input[name="data[lng]"]')).toHaveValue(/139\.65/);
});