diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 13a2b0e9c..8d51bce66 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -170,7 +170,78 @@ This workspace uses the following MCP (Model Context Protocol) tools: - Let the user interact with the browser after navigation or testing - Only use `browser_close` when the user specifically requests it -### 🏥 WebChart Testing Workflow +### � Creating Demo Videos with Playwright + +This project uses Playwright to create automated demonstration videos of WebChart features. Videos should be under 5 minutes and include overlay annotations. + +#### Video Creation Workflow + +**1. Authentication Setup (One-Time)** +- Create an `auth-setup.spec.ts` in the `scripts/` directory +- Script should handle "Standard Login" button click, then username/password login +- Save authentication state to `.auth/webchart-session.json` using `storageState` +- This allows tests to skip login and start pre-authenticated + +**2. Create Demo Script** +- Create test file in `scripts/` directory (e.g., `feature-name.spec.ts`) +- Use saved authentication: `test.use({ storageState: path.join(__dirname, '../.auth/webchart-session.json') })` +- Navigate directly to feature URLs when possible to avoid UI navigation delays +- Include overlay annotations using helper functions: + ```typescript + async function showOverlay(page, text, duration) { + await page.evaluate(({ text, duration }) => { + const overlay = document.createElement('div'); + overlay.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);...'; + overlay.textContent = text; + document.body.appendChild(overlay); + setTimeout(() => overlay.remove(), duration); + }, { text, duration }); + } + ``` + +**3. Video Configuration** (in `playwright.config.ts`) +- Set `video: { mode: 'on', size: { width: 1920, height: 1080 } }` +- Configure `outputDir: './scripts/videos'` for video artifacts +- Set viewport to match video size: `viewport: { width: 1920, height: 1080 }` +- Use single worker: `workers: 1` for sequential execution + +**4. Running Video Creation** +```bash +# First time: Run authentication setup +npx playwright test scripts/auth-setup.spec.ts --headed + +# Then: Run demo script to generate video +npx playwright test scripts/feature-name.spec.ts --headed +``` + +**5. Git LFS for Videos** +- Videos are tracked in Git LFS (see `.gitattributes`) +- Patterns: `scripts/videos/*.webm` and `scripts/videos/*.mp4` +- Videos output to `scripts/videos/` directory +- Directory is in `.gitignore` but files tracked via LFS + +#### Video Best Practices + +- **No login shown**: Use pre-authenticated sessions via `storageState` +- **Direct navigation**: Navigate to feature URLs (`/webchart.cgi?f=chart&s=pat&t=FeatureName&pat_id=TEST-10019`) to skip UI clicks +- **Overlays**: Add text overlays to guide viewers through each step +- **Duration**: Keep under 5 minutes; create separate "quick demo" version if needed +- **Timing**: Add `waitForTimeout()` calls to let actions be visible (500-2000ms) +- **Test patient**: Use TEST-10019 (Hart, William S.) for consistency + +#### File Structure +``` +scripts/ +├── auth-setup.spec.ts # One-time login, saves session +├── feature-name.spec.ts # Demo script with overlays +├── demographics.md # Video script outline +├── videos/ # Generated videos (gitignored, LFS tracked) +└── README.md # Instructions for running tests +.auth/ +└── webchart-session.json # Saved authentication state (gitignored) +``` + +### �🏥 WebChart Testing Workflow When testing WebChart features, documentation, or web pages, follow this standardized procedure: diff --git a/.gitignore b/.gitignore index 514f8b0a5..44fa5b43c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,11 @@ config/_default/menu.en.json .hugo_build.lock .idea .playwright-mcp/ + +# Playwright & Testing +.env +.auth/ +scripts/videos/ +test-results/ +playwright-report/ +playwright/.cache/ diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 000000000..4ebc11f33 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,66 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Playwright configuration for Demographics video demonstrations + * Videos are automatically recorded and saved to scripts/videos/ directory + */ +export default defineConfig({ + testDir: './scripts', + + // Maximum time one test can run for + timeout: 60 * 1000, + + // Run tests in files in parallel + fullyParallel: false, + + // Fail the build on CI if you accidentally left test.only in the source code + forbidOnly: !!process.env.CI, + + // Retry on CI only + retries: process.env.CI ? 2 : 0, + + // Use single worker to ensure tests run sequentially + workers: 1, + + // Reporter to use + reporter: 'html', + + // Shared settings for all the projects below + use: { + // Base URL to use in actions like `await page.goto('/')` + baseURL: 'https://masterdaily.dev.webchart.app', + + // Collect trace when retrying the failed test + trace: 'on-first-retry', + + // Record video on all tests + video: { + mode: 'on', + size: { width: 1920, height: 1080 } + }, + + // Set viewport size + viewport: { width: 1920, height: 1080 }, + + // Screenshot settings + screenshot: 'only-on-failure', + }, + + // Configure projects for major browsers + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + // Store videos in scripts/videos directory + video: { + mode: 'on', + size: { width: 1920, height: 1080 } + }, + }, + }, + ], + + // Output folder for videos and screenshots + outputDir: './scripts/videos', +}); diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..ab1ee7130 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,87 @@ +# Demographics Tab Video Script Tests + +Automated Playwright tests for creating demonstration videos of the WebChart Demographics tab functionality. + +## Setup + +1. **Install dependencies** (if not already done): + ```bash + npm install + ``` + +2. **Configure credentials** in `.env` file: + ``` + WEBCHART_URL=https://masterdaily.dev.webchart.app/ + WEBCHART_USERNAME=dave + WEBCHART_PASSWORD=dave + ``` + +## Running the Tests + +### Step 1: Authenticate and Save Session + +Before running the demonstration tests, you need to establish an authenticated session: + +```bash +npx playwright test scripts/auth-setup.spec.ts --headed +``` + +This will: +- Log into WebChart with the credentials from `.env` +- Save the authentication state to `.auth/webchart-session.json` +- Allow subsequent tests to skip the login process + +**Note**: Run this setup whenever: +- Running tests for the first time +- Session expires +- Switching between different WebChart environments + +### Step 2: Run Demographics Demonstration + +```bash +npx playwright test scripts/demographics.spec.ts --headed --timeout=60000 +``` + +This will run two test scenarios and **automatically record videos**: + +1. **Complete Demographics Tab Walkthrough** (4-5 minutes) + - Full demonstration covering all 10 chapters from the script + - Shows all sections: demographics, employment, contacts, insurance, duplicates + +2. **Quick Demographics Navigation Demo** (2-3 minutes) + - Condensed version focusing on key highlights + - Faster navigation through main sections + +**Videos are automatically saved to**: `scripts/videos/` + +Each test run creates a uniquely named video file with timestamp. + +## Test Features + +- **Pre-authenticated**: Tests use saved session state, no login shown in videos +- **Overlay Annotations**: Each step displays overlay text explaining the action +- **Smooth Navigation**: Automatic scrolling and waiting for proper timing +- **Chapter-based**: Aligned with the demographics.md script structure + +## Files + +- `auth-setup.spec.ts` - Authentication setup (run once before tests) +- `demographics.spec.ts` - Main demonstration tests +- `demographics.md` - Original video script with 10 chapters +- `.auth/webchart-session.json` - Saved authentication state (git-ignored) +- `videos/` - Recorded video files (git-ignored, automatically created) +- `../playwright.config.ts` - Playwright configuration with video settings + +## Troubleshooting + +**Session expired**: Re-run the auth-setup script +```bash +npx playwright test scripts/auth-setup.spec.ts --headed +``` + +**Test timing issues**: Adjust timeout values in the test or use: +```bash +npx playwright test scripts/demographics.spec.ts --headed --timeout=120000 +``` + +**Element not found**: Check that WebChart selectors haven't changed and update test accordingly diff --git a/scripts/auth-setup.spec.ts b/scripts/auth-setup.spec.ts new file mode 100644 index 000000000..a7ee1fa3e --- /dev/null +++ b/scripts/auth-setup.spec.ts @@ -0,0 +1,111 @@ +/** + * Authentication Setup Script + * + * This script logs into WebChart and saves the authentication state + * so that tests can skip the login process and start already authenticated. + * + * Run this before running tests: + * npx playwright test scripts/auth-setup.ts + */ + +import { test as setup } from '@playwright/test'; +import * as dotenv from 'dotenv'; +import * as path from 'path'; + +// Load environment variables +dotenv.config({ path: path.resolve(__dirname, '../.env') }); + +const WEBCHART_URL = process.env.WEBCHART_URL || 'https://masterdaily.dev.webchart.app/'; +const USERNAME = process.env.WEBCHART_USERNAME || 'dave'; +const PASSWORD = process.env.WEBCHART_PASSWORD || 'dave'; + +const authFile = path.join(__dirname, '../.auth/webchart-session.json'); + +setup('authenticate to WebChart', async ({ page }) => { + console.log('Logging into WebChart...'); + + // Navigate to WebChart + await page.goto(WEBCHART_URL); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(2000); + + // First, check if "Standard Login" button exists + const standardLoginButton = await page.getByRole('button', { name: 'Standard Login' }).isVisible().catch(() => false); + + if (standardLoginButton) { + console.log('Clicking Standard Login button...'); + await page.getByRole('button', { name: 'Standard Login' }).click(); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(2000); + } + + // Now check if login form is present - look for the username textbox + const usernameField = page.getByRole('textbox', { name: /Username/ }); + const loginFormVisible = await usernameField.isVisible().catch(() => false); + + if (loginFormVisible) { + console.log('Login form found, entering credentials...'); + + // Fill in credentials using the textbox role + await usernameField.fill(USERNAME); + await page.waitForTimeout(500); + await page.getByRole('textbox', { name: /Password/ }).fill(PASSWORD); + await page.waitForTimeout(500); + + // Submit login - click the Next button (first time) + console.log('Looking for Next button...'); + await page.getByRole('button', { name: 'Next' }).click(); + console.log('First Next button clicked'); + await page.waitForTimeout(2000); + + // Check if there's a second Next button (two-step login process) + const secondNextButton = page.getByRole('button', { name: 'Next' }); + const secondNextVisible = await secondNextButton.isVisible().catch(() => false); + + if (secondNextVisible) { + console.log('Second Next button found (two-step login), clicking...'); + await secondNextButton.click(); + await page.waitForLoadState('networkidle', { timeout: 30000 }); + await page.waitForTimeout(3000); + } else { + console.log('No second Next button, waiting for navigation...'); + await page.waitForLoadState('networkidle', { timeout: 30000 }); + await page.waitForTimeout(3000); + } + + console.log(`Final URL after login: ${page.url()}`); + console.log('Login completed!'); + } else { + console.log('Already logged in or on main page'); + } + + // Wait for page to fully load + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(3000); + + // Verify we're logged in by checking for any main page element + const pageLoaded = await page.locator('body').isVisible(); + if (pageLoaded) { + console.log('Page loaded successfully, saving authentication state...'); + + // Log cookies to debug + const cookies = await page.context().cookies(); + console.log(`Found ${cookies.length} cookies to save`); + + // Check localStorage for tokens + const localStorage = await page.evaluate(() => { + return JSON.stringify(window.localStorage); + }); + console.log(`LocalStorage contents: ${localStorage}`); + + // Check if we see user-specific content to verify login worked + const bodyText = await page.locator('body').textContent(); + console.log(`Page contains "dave": ${bodyText?.includes('dave')}`); + } else { + throw new Error('Page did not load correctly'); + } + + // Save the authentication state + await page.context().storageState({ path: authFile }); + console.log(`Authentication state saved to: ${authFile}`); +}); diff --git a/scripts/demographics.md b/scripts/demographics.md new file mode 100644 index 000000000..77e298411 --- /dev/null +++ b/scripts/demographics.md @@ -0,0 +1,47 @@ +Welcome to the Demographics Chart Tab\! + +In this video, I’ll provide a high-level overview of the Demographics tab, including how to navigate to the tab, what information is displayed, how to update patient details, manage insurance, and handle duplicate charts. + +**Chapter 1: What is the Demographics Tab?** + +The Demographics tab is your central location for viewing and managing a patient’s core information. This includes personal details, contact information, employment and insurance data, and more. Keeping this information accurate is essential for patient safety, billing, and communication. + +**Chapter 2: Navigating to the Demographics Tab** + +To access the Demographics tab, search for the patient’s chart from the E-Chart sidemenu. Once in the chart, click on the Admin tab, then select Demographics from the available subtabs. The Demographics header, which appears in dark grey, will display key patient details such as name, chart status, age, date of birth, sex, home phone, next appointment, and medical record number. You’ll also see counters for tasks, open encounters, due items, order requisitions, and eSigns related to the patient. If a preferred name is entered, it will appear in parentheses next to the legal name. + +**Chapter 3: Understanding the Demographics Header** + +The demographics header is visible on all chart tabs, not just Demographics. Depending on your My Settings preferences, you may also see allergies, current medications, and current conditions displayed here. Any alerts entered into the chart will appear in red below the header, ensuring critical information is always visible. + +**Chapter 4: Viewing and Editing Demographic Information** + +Below the header, you’ll find sections for demographic, employment, marital/contact, and other data. Each section can be quickly edited by clicking the pencil icon in the top right corner of the section. If you have the appropriate security permissions, this allows you to update patient information directly from the Demographics tab. The patient’s photo is also displayed here for identification, and you can add or retake a photo as needed. + +**Chapter 5: Employment, Marital, and Contact Information** + +The Demographics tab includes sections for employment information, such as employer name, address, supervisor, job code, and work location. The Marital/Contact Information section includes marital status, spouse details, and emergency contacts, ensuring you have a complete picture of the patient’s background and support network. + +**Chapter 6: Contacts and Relationships** + +The Contacts/Relationships section is especially powerful. Here, you can view and assign user relationships, such as supervisors, case managers, and portal users. You’ll also see chart relationships, like provider organizations and employer groups, as well as interface pharmacy information. This section helps you track key connections and roles related to the patient, supporting both clinical care and organizational needs. + +**Chapter 7: Other Data and Chart Types** + +The Other Data section allows you to capture additional information, such as birth sex, gender identity, sexual orientation, personal pronouns, and previous names. This section can be customized to fit your organization’s needs. You can also manage chart types and employee numbers from this tab, including adding new partitions or updating chart type as needed. + +**Chapter 8: Managing Insurance Information** + +The Insurance Summary section at the bottom of the Demographics tab displays all current insurance policies for the patient. Here, you can add, edit, or inactivate insurance policies, as well as scan and link insurance card images. Access to these features is based on your security permissions. You can also view pre-certification details and manage insurance card images directly from this section. + +**Chapter 9: Handling Duplicate Charts** + +If the system detects possible duplicate charts based on matching demographics, you’ll see a list of potential matches at the bottom of the Demographics tab. You can review and merge duplicate charts if you have the necessary permissions. For most users, it’s enough to know that this feature helps keep patient records accurate and up to date. + +**Chapter 10: Additional Tips** + +Temporary or inactive records are clearly marked in the demographics header. If you need to merge charts or manage insurance, make sure you have the appropriate security permissions. For more detailed instructions, refer to the help documentation or reach out to your administrative superuser. + +The Demographics tab is designed to make managing patient information simple and efficient. For more detailed instructions, you can find links to additional documentation and videos below this video, or search for “Demographics” in the help search bar for step-by-step guides and support. + +Thanks for watching\! \ No newline at end of file diff --git a/scripts/demographics.spec.ts b/scripts/demographics.spec.ts new file mode 100644 index 000000000..a55800b34 --- /dev/null +++ b/scripts/demographics.spec.ts @@ -0,0 +1,317 @@ +import { test, expect } from '@playwright/test'; +import * as dotenv from 'dotenv'; +import * as path from 'path'; + +// Load environment variables +dotenv.config({ path: path.resolve(__dirname, '../.env') }); + +/** + * Demographics Tab Demonstration + * Automated test that demonstrates the Demographics tab functionality + * with overlay annotations for video recording + * + * Based on: demographics.md script + * Target Duration: <5 minutes + * + * Credentials: Loaded from .env file (WEBCHART_USERNAME, WEBCHART_PASSWORD) + */ + +const WEBCHART_URL = process.env.WEBCHART_URL || 'https://masterdaily.dev.webchart.app/'; + +// Use saved authentication state +test.use({ storageState: path.join(__dirname, '../.auth/webchart-session.json') }); + +// Overlay helper function +async function showOverlay(page: any, text: string, duration: number = 2000) { + await page.evaluate(({ text, duration }) => { + // Remove any existing overlay + const existing = document.getElementById('demo-overlay'); + if (existing) existing.remove(); + + // Create overlay + const overlay = document.createElement('div'); + overlay.id = 'demo-overlay'; + overlay.style.cssText = ` + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); + background: rgba(0, 0, 0, 0.85); + color: white; + padding: 15px 30px; + border-radius: 8px; + font-size: 18px; + font-weight: bold; + z-index: 10000; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); + max-width: 80%; + text-align: center; + `; + overlay.textContent = text; + document.body.appendChild(overlay); + + // Auto-remove after duration + setTimeout(() => { + const el = document.getElementById('demo-overlay'); + if (el) el.remove(); + }, duration); + }, { text, duration }); + + await page.waitForTimeout(duration); +} + +// Highlight element helper +async function highlightElement(page: any, selector: string, duration: number = 1500) { + await page.evaluate(({ selector, duration }) => { + const element = document.querySelector(selector); + if (!element) return; + + const rect = element.getBoundingClientRect(); + + // Create highlight overlay + const highlight = document.createElement('div'); + highlight.className = 'demo-highlight'; + highlight.style.cssText = ` + position: fixed; + top: ${rect.top - 5}px; + left: ${rect.left - 5}px; + width: ${rect.width + 10}px; + height: ${rect.height + 10}px; + border: 3px solid #00ff00; + border-radius: 4px; + z-index: 9999; + pointer-events: none; + animation: pulse 0.5s ease-in-out; + `; + + document.body.appendChild(highlight); + + // Remove after duration + setTimeout(() => { + const highlights = document.querySelectorAll('.demo-highlight'); + highlights.forEach(h => h.remove()); + }, duration); + }, { selector, duration }); + + await page.waitForTimeout(duration); +} + +test.describe('Demographics Tab Demonstration', () => { + test.beforeEach(async ({ page }) => { + // Set viewport for consistent video recording + await page.setViewportSize({ width: 1920, height: 1080 }); + }); + + test('Complete Demographics Tab Walkthrough', async ({ page }) => { + // Chapter 1: Introduction + await showOverlay(page, 'Demographics Tab Demonstration', 3000); + + // Navigate to WebChart home page (already authenticated) + await page.goto(WEBCHART_URL); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(2000); + + // Chapter 2: Navigation + await showOverlay(page, 'Step 1: Navigate to Patient Chart', 2000); + + // Navigate to patient chart via OmniScope search + await page.getByRole('searchbox', { name: 'Search' }).fill('TEST-10019'); + await page.waitForTimeout(1000); + await page.keyboard.press('Enter'); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(1500); + + await showOverlay(page, 'Step 2: Navigate to Admin > Demographics', 2500); + + // Expand Admin section + await page.getByText('Admin (').click(); + await page.waitForTimeout(500); + + // Click Demographics + await page.getByRole('link', { name: 'Demographics', exact: true }).click(); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(1000); + + // Chapter 3: Demographics Header + await showOverlay(page, 'Demographics Header: Patient Information & Photo', 3000); + await page.evaluate(() => window.scrollTo({ top: 0, behavior: 'smooth' })); + await page.waitForTimeout(1000); + + // Chapter 4: Demographic Information Section + await showOverlay(page, 'Demographic Information: Name, Address, Contact Details', 3000); + await page.waitForTimeout(500); + + // Scroll to show edit icons + await showOverlay(page, 'Edit Icons: Click pencil to modify any field', 2500); + await page.waitForTimeout(500); + + // Chapter 5: Employment & Marital Information + await page.evaluate(() => { + const employmentSection = document.querySelector('h2:has-text("Employment Information")'); + if (employmentSection) { + employmentSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Employment Information: Employer, Status, Location', 2500); + await page.waitForTimeout(500); + + await page.evaluate(() => { + const maritalSection = document.querySelector('h2:has-text("Marital / Contact Information")'); + if (maritalSection) { + maritalSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Marital Status & Emergency Contacts', 2500); + await page.waitForTimeout(500); + + // Chapter 6: Contacts & Relationships + await page.evaluate(() => { + const contactsSection = document.querySelector('h2:has-text("Contacts / Relationships")'); + if (contactsSection) { + contactsSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Relationships: Providers, Employers, Pharmacies', 2500); + await page.waitForTimeout(500); + + // Chapter 7: Other Data + await page.evaluate(() => { + const otherDataSection = document.querySelector('h2:has-text("Other Data")'); + if (otherDataSection) { + otherDataSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Other Data: Birth Sex, Gender Identity, Comments', 2500); + await page.waitForTimeout(500); + + // Scroll to show Employee Numbers and Chart Types + await page.evaluate(() => { + const empNumbersSection = document.querySelector('h2:has-text("Employee Numbers")'); + if (empNumbersSection) { + empNumbersSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Employee Numbers & Chart Types', 2000); + await page.waitForTimeout(500); + + // Chapter 8: Insurance Summary + await page.evaluate(() => { + const insuranceSection = document.querySelector('legend:has-text("Insurance Summary")'); + if (insuranceSection) { + insuranceSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Insurance Summary: View & Manage Policies', 3000); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Add New Insurance: Click "Add Insurance" button', 2000); + await page.waitForTimeout(500); + + await showOverlay(page, 'Edit Insurance: Click "Edit" or "Card-Options"', 2000); + await page.waitForTimeout(500); + + // Chapter 9: Duplicate Chart Detection + await page.evaluate(() => { + const duplicateSection = document.querySelector('legend:has-text("Matching Employees")'); + if (duplicateSection) { + duplicateSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Duplicate Detection: System Finds Potential Matches', 3000); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Rating System: Higher rating = Stronger match', 2500); + await page.waitForTimeout(500); + + await showOverlay(page, 'Merge Charts: Preview before merging duplicates', 2500); + await page.waitForTimeout(500); + + // Chapter 10: Tips & Best Practices + await showOverlay(page, 'Tip: Always verify patient info before editing', 2500); + await page.waitForTimeout(500); + + await showOverlay(page, 'Tip: Keep insurance information up-to-date', 2500); + await page.waitForTimeout(500); + + await showOverlay(page, 'Tip: Review duplicate alerts to maintain data integrity', 2500); + await page.waitForTimeout(500); + + // Scroll back to top for final view + await page.evaluate(() => window.scrollTo({ top: 0, behavior: 'smooth' })); + await page.waitForTimeout(1500); + + await showOverlay(page, 'Demographics Tab: Complete Patient Information Hub', 3000); + + // Final pause for video + await page.waitForTimeout(2000); + }); + + test('Quick Demographics Navigation Demo', async ({ page }) => { + /** + * Shorter version focusing on just navigation and key highlights + * for a <3 minute video + */ + + await showOverlay(page, 'Quick Demographics Overview', 2500); + + // Navigate to WebChart (already authenticated) + await page.goto(WEBCHART_URL); + await page.waitForLoadState('domcontentloaded'); + await page.waitForTimeout(1500); + + // Navigate to patient chart via OmniScope + await page.getByRole('searchbox', { name: 'Search' }).fill('TEST-10019'); + await page.waitForTimeout(500); + await page.keyboard.press('Enter'); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(1000); + + await showOverlay(page, 'Navigate: Admin > Demographics', 2000); + await page.getByText('Admin (').click(); + await page.waitForTimeout(300); + await page.getByRole('link', { name: 'Demographics', exact: true }).click(); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(500); + + // Quick tour of sections + await showOverlay(page, 'Patient Demographics: All information in one place', 3000); + + await page.evaluate(() => { + const sections = [ + 'Demographic Information', + 'Employment Information', + 'Contacts / Relationships', + 'Insurance Summary' + ]; + + let delay = 0; + sections.forEach((sectionName) => { + setTimeout(() => { + const section = document.querySelector(`h2:has-text("${sectionName}"), legend:has-text("${sectionName}")`); + if (section) { + section.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }, delay); + delay += 2000; + }); + }); + + await page.waitForTimeout(8000); + + await showOverlay(page, 'Demographics: Your complete patient information resource', 3000); + }); +});