test(post-form): realign photo specs to FilePond after U4 rework

waitForPhotoUpload waits on FilePond processing-complete; AE1/AE4 use
input.filepond--browser + the .photo-convert-status error status; V3/V4 back
to FilePond limit + non-image rejection; reauth hint -> .photo-reauth-hint;
test-form-config asserts type:filepond. Verified against a live server via a
browser smoke run (HEIC->JPEG attach, corrupt fail-closed, draft restore).
This commit is contained in:
2026-07-04 17:52:09 +02:00
parent 421c21345e
commit 27a35a1db8
5 changed files with 42 additions and 31 deletions
+23 -17
View File
@@ -2,7 +2,7 @@
// Tests: V1V4 — form validation and input constraints
const { test, expect } = require('@playwright/test');
const path = require('path');
const { fillEditor, waitForPhotoUpload } = require('../helpers');
const { fillEditor } = require('../helpers');
const TEST_PHOTO = path.join(__dirname, '../../fixtures/test-photo.jpg');
const TEST_NONIMAGE = path.join(__dirname, '../../fixtures/test-nonimage.txt');
@@ -34,31 +34,37 @@ test('V2: submit without content shows a validation error or stays on /post', as
});
// ── V3: Photo limit (max 4) ───────────────────────────────────────────────────
test('V3: photo picker caps attachments at 4', async ({ page }) => {
test('V3: FilePond caps attachments at the limit (4)', async ({ page }) => {
await page.goto('/post');
const input = page.locator('input.photo-picker__input');
const browser = page.locator('input.filepond--browser');
// Attach 4 photos (same fixture — we only need four items).
await input.setInputFiles([TEST_PHOTO, TEST_PHOTO, TEST_PHOTO, TEST_PHOTO]);
await waitForPhotoUpload(page, 4);
await browser.setInputFiles([TEST_PHOTO, TEST_PHOTO, TEST_PHOTO, TEST_PHOTO]);
await page.waitForFunction(() =>
document.querySelectorAll('.filepond--item').length === 4, { timeout: 10_000 });
// A 5th is rejected once the limit is reached — no new card, and a hint shows.
await input.setInputFiles([TEST_PHOTO]);
// A 5th is ignored once the limit is reached.
await browser.setInputFiles([TEST_PHOTO]);
await page.waitForTimeout(500);
await expect(page.locator('.photo-card')).toHaveCount(4);
await expect(page.locator('.photo-picker__hint')).toContainText(/up to 4/i);
expect(await page.locator('.filepond--item').count()).toBe(4);
});
// ── V4: Non-image file rejected (fail-closed) ─────────────────────────────────
test('V4: a non-image upload fails closed and is not attached', async ({ page }) => {
// ── V4: Non-image file rejected ───────────────────────────────────────────────
test('V4: FilePond rejects a non-image file', async ({ page }) => {
await page.goto('/post');
// The picker accepts anything the OS dialog allows; the server's uploadFiles
// accept-check (image/*) rejects a .txt, so the card ends in the error state
// and never reaches "done" — the original is never posted.
await page.locator('input.photo-picker__input').setInputFiles(TEST_NONIMAGE);
await page.locator('input.filepond--browser').setInputFiles(TEST_NONIMAGE);
await page.waitForTimeout(1_000);
await expect(page.locator('.photo-card.is-error')).toBeVisible({ timeout: 15_000 });
await expect(page.locator('.photo-card.is-done')).toHaveCount(0);
const items = page.locator('.filepond--item');
const count = await items.count();
if (count > 0) {
// If added, it must not reach processing-complete.
const state = await items.first().getAttribute('data-filepond-item-state');
expect(state).not.toBe('processing-complete');
} else {
// Silently rejected before adding — also a pass.
expect(count).toBe(0);
}
});