// ============================================================ // HOSPITAL COURSE — full workflow: fill inputs → generate → verify // mocked narrative renders → refine → verify rendered replaces. // The older soap-hospital-workflow.spec.js only smokes the save bar; // this one drives the actual AI generate path. // ============================================================ const { test, expect, E2E_BASE, mockAI } = require('../fixtures'); async function openTab(page) { await page.goto(E2E_BASE + '/'); await page.waitForSelector('button.tab-btn', { timeout: 15000 }); const vp = page.viewportSize(); if (vp && vp.width <= 768) { await page.click('#btn-menu-toggle').catch(() => {}); } await page.click('button.tab-btn[data-tab="hospital"]'); await page.waitForFunction(() => { const el = document.getElementById('hospital-tab'); return el && el.classList.contains('active') && el.innerHTML.trim().length > 100; }, { timeout: 15000 }); } test.describe('Hospital Course — generate + refine', () => { test('minimum inputs → generate → mocked narrative renders', async ({ authedPage: _, page }) => { await mockAI(page); await openTab(page); await page.fill('#hc-age', '9 years'); await page.selectOption('#hc-gender', 'Male'); await page.fill('#hc-pmh', 'Asthma, mild intermittent'); // H&P is the minimum "some note" the route needs so it doesn't reject await page.locator('#hc-hp-content').click(); await page.keyboard.type('Admitted for status asthmaticus. Started on continuous albuterol and steroids.'); const [resp] = await Promise.all([ page.waitForResponse('**/api/generate-hospital-course', { timeout: 15000 }), page.click('#hc-generate-btn'), ]); expect(resp.status()).toBe(200); await expect(page.locator('#hc-output')).toBeVisible({ timeout: 10000 }); await expect(page.locator('#hc-course-text')).toContainText('MOCK hospital course narrative'); }); test('refine button on generated course fires /api/refine + updates text', async ({ authedPage: _, page }) => { await mockAI(page, { '**/api/refine': { success: true, refined: 'REFINED-HC course — emphasised hospital day 1 events.', model: 'mock-gpt' }, }); await openTab(page); await page.fill('#hc-age', '5 years'); await page.locator('#hc-hp-content').click(); await page.keyboard.type('Admission for pneumonia, improving on IV cefriaxone.'); await page.click('#hc-generate-btn'); await expect(page.locator('#hc-course-text')).toContainText('MOCK hospital course', { timeout: 10000 }); // Refine with an instruction const refineInput = page.locator('#hc-refine-input, [id*="hc-refine"]').first(); await refineInput.fill('Tighten the prose.'); const [resp] = await Promise.all([ page.waitForResponse('**/api/refine'), page.click('#hc-refine-btn'), ]); expect(resp.status()).toBe(200); await expect(page.locator('#hc-course-text')).toContainText('REFINED-HC course', { timeout: 10000 }); }); test('load popover: opens and closes from both triggers', async ({ authedPage: _, page }) => { await openTab(page); await page.click('#btn-hosp-load'); await expect(page.locator('#hosp-load-popover')).not.toHaveClass(/hidden/, { timeout: 3000 }); await page.locator('#hosp-load-popover .enc-pop-close').click(); await expect(page.locator('#hosp-load-popover')).toHaveClass(/hidden/); }); });