import { test, expect } from '@playwright/test'; test.describe('Ghostwriter Flow', () => { test('Scenario 2.3.2 (P0): Regeneration respects user critique', async ({ page }) => { // GIVEN: A generated draft exists (mocked) await page.goto('/session/chat'); // Mock the "Drafting" completion state by injecting state or ensuring mock network response await page.route('**/api/llm/generate', async (route) => { const json = { content: 'Draft Version 1' }; await route.fulfill({ json }); }); // Trigger generation (assuming UI state is ready or fast-track used) // For E2E, we might need to simulate the chat flow or use a "Debug: Force Draft" button if available in dev mode // Assuming we can start from a state where the draft sheet is open for this test, or we navigate through chat. // Let's assume we simulate the chat end first. await page.fill('[data-testid="chat-input"]', 'Fast track this'); await page.click('[data-testid="fast-track-btn"]'); await expect(page.locator('[data-testid="draft-sheet"]')).toBeVisible(); await expect(page.locator('[data-testid="markdown-content"]')).toContainText('Draft Version 1'); // WHEN: User clicks Thumbs Down and critiques await page.click('[data-testid="thumbs-down-btn"]'); await expect(page.locator('[data-testid="critique-input"]')).toBeVisible(); await page.fill('[data-testid="critique-input"]', 'Make it shorter'); // Intercept the regeneration request let critiqueSent = false; await page.route('**/api/llm/regenerate', async (route) => { critiqueSent = true; const postData = route.request().postDataJSON(); expect(postData.critique).toBe('Make it shorter'); await route.fulfill({ json: { content: 'Draft Version 2 (Shorter)' } }); }); await page.click('[data-testid="regenerate-submit-btn"]'); // THEN: A new draft is requested with critique context await expect(page.locator('[data-testid="markdown-content"]')).toContainText('Draft Version 2 (Shorter)'); expect(critiqueSent).toBe(true); }); test('Scenario 2.4.1 (P0): Copy button places text in clipboard', async ({ page, context }) => { // Grant clipboard permissions await context.grantPermissions(['clipboard-read', 'clipboard-write']); // GIVEN: A draft is visible await page.goto('/session/chat'); // Mock generation await page.route('**/api/llm/generate', async (route) => { await route.fulfill({ json: { content: 'Final Draft Content' } }); }); await page.fill('[data-testid="chat-input"]', 'Fast track'); await page.click('[data-testid="fast-track-btn"]'); await expect(page.locator('[data-testid="draft-sheet"]')).toBeVisible(); // WHEN: User clicks Copy await page.click('[data-testid="copy-btn"]'); // THEN: Clipboard contains text // Note: Reading clipboard in headless might be tricky, checking for "Copied" toast is a good proxy for PWA checks await expect(page.locator('[data-testid="toast-success"]')).toContainText('Copied to clipboard'); // Optional: layout check (R-2.5) - Verify rendering didn't break await expect(page.locator('[data-testid="markdown-content"]')).toBeVisible(); await expect(page.locator('[data-testid="markdown-content"]')).not.toHaveCSS('overflow-x', 'hidden'); // Crude check for broken layout }); });