test(post): share createPhotoEntry helper and fix cleanup leak

Hoist the duplicated per-spec createEntry photo-fixture into a single
createPhotoEntry() in helpers.js (used by delete-flow, edit-mode, and the
anon-view draft). Register the tag for cleanup BEFORE the awaited 15s
success-toast assertion, so a create that lands on disk but whose toast
assertion times out no longer leaks an untracked entry. Add AE3b covering the
disclosure deviation branch (a non-default toggle auto-expands More options).

Code review F2 (leak), F3 (duplication), F6 (coverage).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mpdu3Dt1iVoozHwAMyjrbn
This commit is contained in:
2026-07-07 08:32:09 +02:00
co-authored by Claude Opus 4.8
parent f4dbac6fc2
commit d576487886
5 changed files with 74 additions and 59 deletions
+4 -22
View File
@@ -8,34 +8,18 @@
// - DEL2: Cancel is a real escape hatch — nothing is deleted.
// - DEL3: a failed DELETE keeps the card and surfaces the inline error.
const { test, expect } = require('@playwright/test');
const path = require('path');
const {
fillEditor, waitForPhotoUpload, cleanupEntry, findEntry, ACTIVE_TRIP_URL,
createPhotoEntry, cleanupEntry, findEntry, ACTIVE_TRIP_URL,
} = require('../helpers');
const TEST_PHOTO = path.join(__dirname, '../../fixtures/test-photo.jpg');
const created = [];
// cleanupEntry is a no-op when the entry was already deleted by the test.
test.afterAll(() => created.forEach(cleanupEntry));
/** Post a fresh entry through the create form so a feed card exists to delete. */
async function createEntry(page, tag) {
await page.goto('/post');
await page.fill('input[name="data[title]"]', `UI Test ${tag}`);
await fillEditor(page, `Delete-flow fixture ${tag}. Safe to delete.`);
await page.locator('input.filepond--browser').setInputFiles(TEST_PHOTO);
await waitForPhotoUpload(page);
await page.locator('.btn-post').evaluate(el => el.click());
await expect(page.locator('.form-messages, .notices')).toContainText(
'Entry posted successfully!', { timeout: 15_000 });
}
// ── DEL1: happy delete removes the card and the folder ────────────────────────
test('DEL1: owner deletes an entry — the card disappears and the folder is removed', async ({ page }) => {
const tag = `del1-${Date.now()}`;
await createEntry(page, tag);
created.push(tag);
await createPhotoEntry(page, tag, { created, content: `Delete-flow fixture ${tag}. Safe to delete.` });
await page.goto(ACTIVE_TRIP_URL);
const card = page.locator('.journal-post', { hasText: tag });
@@ -52,8 +36,7 @@ test('DEL1: owner deletes an entry — the card disappears and the folder is rem
// ── DEL2: Cancel keeps the entry ──────────────────────────────────────────────
test('DEL2: cancelling the confirm step keeps the entry on the page and on disk', async ({ page }) => {
const tag = `del2-${Date.now()}`;
await createEntry(page, tag);
created.push(tag);
await createPhotoEntry(page, tag, { created, content: `Delete-flow fixture ${tag}. Safe to delete.` });
await page.goto(ACTIVE_TRIP_URL);
const card = page.locator('.journal-post', { hasText: tag });
@@ -71,8 +54,7 @@ test('DEL2: cancelling the confirm step keeps the entry on the page and on disk'
// ── DEL3: a failed DELETE keeps the card and shows the inline error ───────────
test('DEL3: a failed delete keeps the card and surfaces the inline error', async ({ page }) => {
const tag = `del3-${Date.now()}`;
await createEntry(page, tag);
created.push(tag);
await createPhotoEntry(page, tag, { created, content: `Delete-flow fixture ${tag}. Safe to delete.` });
await page.goto(ACTIVE_TRIP_URL);
// Force the delete request to fail after the confirm.