test(post-form): assert 1–6 photo rule

Add a test for the ≥1-photo requirement (submit blocked with a photo-section
error) and the max of 6 (FilePond maxFiles). Rework AE4: a corrupt HEIC is the
only "photo", so fail-closed now means submit is blocked rather than posting a
text-only entry. Give the success-CTA test a photo so it can post under the new
rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 20:59:01 +02:00
co-authored by Claude Opus 4.8
parent edb1c7659c
commit 45c2d54d2b
+29 -10
View File
@@ -49,11 +49,10 @@ test('AE1: a HEIC photo is converted to JPEG client-side and posted', async ({ p
expect(files.some(f => /\.heic$/i.test(f)), 'the original HEIC must NOT be posted').toBe(false); expect(files.some(f => /\.heic$/i.test(f)), 'the original HEIC must NOT be posted').toBe(false);
}); });
// ── AE4: corrupt HEIC fails closed; Submit + other photos stay usable ───────── // ── AE4: corrupt HEIC fails closed — it is the only "photo", so submit blocks ──
test('AE4: a corrupt HEIC is blocked (fail-closed) and never posted', async ({ page }) => { test('AE4: a corrupt HEIC is blocked (fail-closed) and cannot be posted alone', async ({ page }) => {
const tag = `heicfail-${Date.now()}`;
await page.goto('/post'); await page.goto('/post');
await page.fill('input[name="data[title]"]', `UI Test ${tag}`); await page.fill('input[name="data[title]"]', `UI Test heicfail-${Date.now()}`);
await fillEditor(page, 'HEIC failure test. Safe to delete.'); await fillEditor(page, 'HEIC failure test. Safe to delete.');
await page.locator('input.filepond--browser').setInputFiles(TEST_CORRUPT_HEIC); await page.locator('input.filepond--browser').setInputFiles(TEST_CORRUPT_HEIC);
@@ -61,14 +60,31 @@ test('AE4: a corrupt HEIC is blocked (fail-closed) and never posted', async ({ p
await expect(page.locator('.photo-convert-status.form-status--err')).toBeVisible({ timeout: 15_000 }); await expect(page.locator('.photo-convert-status.form-status--err')).toBeVisible({ timeout: 15_000 });
await expect(page.locator('.btn-post')).toBeEnabled(); // Submit still usable await expect(page.locator('.btn-post')).toBeEnabled(); // Submit still usable
// The corrupt file was never added, so there are zero photos — the ≥1-photo
// requirement blocks submit, which is exactly what keeps the corrupt HEIC
// (fail-closed) from ever being posted. No entry is created.
await page.locator('.btn-post').evaluate(el => el.click()); await page.locator('.btn-post').evaluate(el => el.click());
await expect(page.locator('.notices')).toContainText('Entry posted successfully!', { timeout: 15_000 }); await expect(page.locator('.photos-collapse .field-error')).toBeVisible();
created.push(tag); await expect(page.locator('.notices.success, .notices.green')).toHaveCount(0);
});
const dir = findEntry(tag); // ── Photo count: at least one is required; the picker caps at 6 ────────────────
expect(dir).toBeTruthy(); test('a post requires at least one photo and the picker allows at most 6', async ({ page }) => {
const files = fs.readdirSync(dir); await page.goto('/post');
expect(files.some(f => /\.heic$/i.test(f)), 'the corrupt HEIC must never be posted').toBe(false);
// FilePond is configured from the blueprint limit (6).
await page.waitForFunction(
() => window.GravFilePond && window.GravFilePond.getInstances().length > 0,
{ timeout: 10_000 });
expect(await page.evaluate(() => window.GravFilePond.getInstances()[0].maxFiles)).toBe(6);
// Title + content filled, date prefilled, but no photo → submit is blocked
// with an error on the photo section and no success notice.
await page.fill('input[name="data[title]"]', `UI photoreq-${Date.now()}`);
await fillEditor(page, 'photo-required test');
await page.locator('.btn-post').evaluate(el => el.click());
await expect(page.locator('.photos-collapse .field-error')).toContainText('at least one photo');
await expect(page.locator('.notices.success, .notices.green')).toHaveCount(0);
}); });
// ── Photo section collapses to a summary after upload, re-expands on tap ────── // ── Photo section collapses to a summary after upload, re-expands on tap ──────
@@ -179,6 +195,9 @@ test('post success shows a confirmation with a working "View your journal" link'
await page.goto('/post'); await page.goto('/post');
await page.fill('input[name="data[title]"]', `UI Test ${tag}`); await page.fill('input[name="data[title]"]', `UI Test ${tag}`);
await fillEditor(page, `success cta test ${tag}`); await fillEditor(page, `success cta test ${tag}`);
// A photo is required to post.
await page.locator('input.filepond--browser').setInputFiles(TEST_JPG);
await waitForPhotoUpload(page, 1);
await page.locator('.btn-post').evaluate(el => el.click()); await page.locator('.btn-post').evaluate(el => el.click());
await expect(page.locator('.notices')).toContainText('Entry posted successfully!', { timeout: 15_000 }); await expect(page.locator('.notices')).toContainText('Entry posted successfully!', { timeout: 15_000 });
created.push(tag); created.push(tag);