/** * UX fix — tapping X on the upload composer used to silently discard * staged files + caption. Now opens a ConfirmSheet so a mistap from the * corner is recoverable. */ import { test, expect } from '../../fixtures/test'; test.describe('Mobile — upload composer cancel confirmation', () => { test('typing a caption then tapping X opens the discard ConfirmSheet', async ({ page, guest, signIn, }) => { const g = await guest('CancelConf'); await signIn(page, g); // Land on /upload directly (no staged files; the pending-upload-store is // empty). Typing into the caption flips the dirty flag. await page.goto('/upload'); const caption = page.getByTestId('upload-caption'); // The composer is server-rendered, so the textarea is visible (and fillable) BEFORE Svelte // hydrates its `bind:value`. A fill that lands pre-hydration sets the DOM value but never // reaches the reactive `caption` state — so `cancel()` sees an empty caption and navigates // straight to /feed instead of opening the discard sheet (a reproduced ~1% flake). The // composer auto-focuses the textarea in onMount (which only runs post-hydration), so waiting // for focus is a reliable "the bindings are live now" barrier before we type. await expect(caption).toBeFocused(); await caption.fill('a meaningful caption that I do not want to lose'); // Tap the close (X) button in the composer header. await page.getByRole('button', { name: 'Abbrechen' }).click(); const sheet = page.getByTestId('confirm-sheet'); await expect(sheet).toBeVisible(); await expect(sheet).toContainText(/Verwerfen/); // Cancel — sheet closes, caption is preserved. await page.getByTestId('confirm-sheet-cancel').click(); await expect(sheet).not.toBeVisible(); await expect(caption).toHaveValue(/a meaningful caption/); }); test('with no content, tapping X navigates directly to /feed', async ({ page, guest, signIn, }) => { const g = await guest('CancelEmpty'); await signIn(page, g); await page.goto('/upload'); // Wait for the composer to hydrate (onMount auto-focuses the textarea) before tapping // Abbrechen, so the click reaches a hydrated button. See the test above. await expect(page.getByTestId('upload-caption')).toBeFocused(); await page.getByRole('button', { name: 'Abbrechen' }).click(); await page.waitForURL('**/feed', { timeout: 3_000 }); }); });