import { test, expect, type Page } from './fixtures'; // Leaving a form with unsaved work (e.g. a half-filled upload) must prompt so a // misclicked nav link doesn't silently discard everything. const DESKTOP = { width: 1280, height: 720 } as const; async function authed(page: Page) { await page.route('**/api/v1/auth/config', (r) => r.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ self_register_enabled: true, private_mode: false }) }) ); await page.route('**/api/v1/auth/me', (r) => r.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ user: { id: 'u1', username: 'uploader', created_at: '2026-01-01T00:00:00Z', is_admin: false } }) }) ); await page.route('**/api/v1/auth/me/preferences', (r) => r.fulfill({ status: 200, contentType: 'application/json', body: '{}' }) ); await page.route('**/api/v1/genres', (r) => r.fulfill({ status: 200, contentType: 'application/json', body: '[]' }) ); await page.route('**/api/v1/me/bookmarks*', (r) => r.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ items: [], page: { limit: 50, offset: 0, total: 0 } }) }) ); } test('upload form prompts before navigating away with unsaved changes', async ({ page }) => { await authed(page); await page.setViewportSize(DESKTOP); await page.goto('/upload'); // Make the form dirty. await page.getByLabel(/Title/).fill('WIP Manga'); // Cancel the confirm → navigation is blocked, we stay put with our input. let dialogSeen = false; page.once('dialog', (d) => { dialogSeen = true; d.dismiss(); }); await page.getByRole('link', { name: 'Bookmarks' }).click(); await expect.poll(() => dialogSeen).toBe(true); await expect(page).toHaveURL(/\/upload/); await expect(page.getByLabel(/Title/)).toHaveValue('WIP Manga'); });