mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
- 27 Playwright E2E tests covering login (3 roles), CC Agent pages (call desk, call history, patients, appointments, my performance, sidebar, sign-out), and Supervisor pages (all 11 pages + sidebar) - Tests run against live EC2 at ramaiah.engage.healix360.net - Last test completes sign-out to release agent session for next run - Architecture doc with updated Mermaid diagram including telephony dispatcher, service discovery, and multi-tenant topology - Operations runbook with SSH access (VPS + EC2), accounts, container reference, deploy steps, Redis ops, and troubleshooting guide Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
156 lines
5.7 KiB
TypeScript
156 lines
5.7 KiB
TypeScript
/**
|
|
* CC Agent — happy-path smoke tests.
|
|
*
|
|
* Role: cc-agent (ccagent@ramaiahcare.com)
|
|
* Landing: / → Call Desk
|
|
* Pages: Call Desk, Call History, Patients, Appointments, My Performance
|
|
*/
|
|
import { test, expect } from '@playwright/test';
|
|
import { waitForApp } from './helpers';
|
|
|
|
test.describe('CC Agent Smoke', () => {
|
|
|
|
test('lands on Call Desk after login', async ({ page }) => {
|
|
await page.goto('/');
|
|
await waitForApp(page);
|
|
|
|
await expect(page.locator('aside').first()).toContainText(/Call Center/i);
|
|
});
|
|
|
|
test('Call Desk page loads', async ({ page }) => {
|
|
await page.goto('/');
|
|
await waitForApp(page);
|
|
|
|
// Call Desk is the landing — just verify we're not on an error page
|
|
await expect(page.locator('aside').first()).toContainText(/Call Desk/i);
|
|
});
|
|
|
|
test('Call History page loads', async ({ page }) => {
|
|
await page.goto('/call-history');
|
|
await waitForApp(page);
|
|
|
|
// Should show "Call History" title whether or not there are calls
|
|
await expect(page.locator('text="Call History"').first()).toBeVisible();
|
|
|
|
// Filter dropdown present
|
|
await expect(page.locator('text=/All Calls/i').first()).toBeVisible();
|
|
});
|
|
|
|
test('Patients page loads with search', async ({ page }) => {
|
|
await page.goto('/patients');
|
|
await waitForApp(page);
|
|
|
|
const search = page.getByPlaceholder(/search/i).or(page.getByLabel(/search/i));
|
|
await expect(search.first()).toBeVisible();
|
|
});
|
|
|
|
test('Patients search filters results', async ({ page }) => {
|
|
await page.goto('/patients');
|
|
await waitForApp(page);
|
|
|
|
const search = page.getByPlaceholder(/search/i).or(page.getByLabel(/search/i));
|
|
await search.first().fill('zzz-nonexistent-patient');
|
|
await waitForApp(page);
|
|
|
|
// Should show empty state
|
|
const noResults = page.locator('text=/no patient|not found|no results/i');
|
|
const isEmpty = await noResults.isVisible({ timeout: 5_000 }).catch(() => false);
|
|
expect(isEmpty).toBe(true);
|
|
});
|
|
|
|
test('Appointments page loads', async ({ page }) => {
|
|
await page.goto('/appointments');
|
|
await waitForApp(page);
|
|
|
|
await expect(
|
|
page.locator('text=/Appointment|Schedule|No appointment/i').first(),
|
|
).toBeVisible({ timeout: 10_000 });
|
|
});
|
|
|
|
test('My Performance loads with date controls', async ({ page }) => {
|
|
// Intercept API to verify agentId is sent
|
|
const apiHit = page.waitForRequest(
|
|
(r) => r.url().includes('/api/ozonetel/performance') && r.url().includes('agentId='),
|
|
{ timeout: 15_000 },
|
|
);
|
|
|
|
await page.goto('/my-performance');
|
|
const req = await apiHit;
|
|
|
|
const url = new URL(req.url());
|
|
expect(url.searchParams.get('agentId')?.length).toBeGreaterThan(0);
|
|
|
|
await waitForApp(page);
|
|
|
|
await expect(page.getByRole('button', { name: 'Today' })).toBeVisible();
|
|
await expect(page.getByRole('button', { name: 'Yesterday' })).toBeVisible();
|
|
|
|
// Either KPI data or empty state
|
|
await expect(
|
|
page.locator('text=/Total Calls|No performance data/i').first(),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test('sidebar has all CC Agent nav items', async ({ page }) => {
|
|
await page.goto('/');
|
|
await waitForApp(page);
|
|
|
|
const sidebar = page.locator('aside').first();
|
|
for (const item of ['Call Desk', 'Call History', 'Patients', 'Appointments', 'My Performance']) {
|
|
await expect(sidebar.locator(`text="${item}"`)).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test('sign-out shows confirmation modal and cancel keeps session', async ({ page }) => {
|
|
await page.goto('/');
|
|
await waitForApp(page);
|
|
|
|
const sidebar = page.locator('aside').first();
|
|
const accountArea = sidebar.locator('[class*="account"], [class*="avatar"]').last();
|
|
if (await accountArea.isVisible()) {
|
|
await accountArea.click();
|
|
}
|
|
|
|
const signOutBtn = page.locator('button, [role="menuitem"]').filter({ hasText: /sign out/i }).first();
|
|
if (await signOutBtn.isVisible({ timeout: 5_000 }).catch(() => false)) {
|
|
await signOutBtn.click();
|
|
|
|
const modal = page.locator('[role="dialog"]');
|
|
await expect(modal).toBeVisible({ timeout: 5_000 });
|
|
await expect(modal).toContainText(/sign out/i);
|
|
|
|
// Cancel — should stay logged in
|
|
await modal.getByRole('button', { name: /cancel/i }).click();
|
|
await expect(modal).not.toBeVisible();
|
|
await expect(page).not.toHaveURL(/\/login/);
|
|
}
|
|
});
|
|
|
|
// MUST be the last test — completes sign-out so the agent session is
|
|
// released and the next test run won't hit "already logged in".
|
|
test('sign-out completes and redirects to login', async ({ page }) => {
|
|
await page.goto('/');
|
|
await waitForApp(page);
|
|
|
|
const sidebar = page.locator('aside').first();
|
|
const accountArea = sidebar.locator('[class*="account"], [class*="avatar"]').last();
|
|
if (await accountArea.isVisible()) {
|
|
await accountArea.click();
|
|
}
|
|
|
|
const signOutBtn = page.locator('button, [role="menuitem"]').filter({ hasText: /sign out/i }).first();
|
|
if (await signOutBtn.isVisible({ timeout: 5_000 }).catch(() => false)) {
|
|
await signOutBtn.click();
|
|
|
|
const modal = page.locator('[role="dialog"]');
|
|
await expect(modal).toBeVisible({ timeout: 5_000 });
|
|
|
|
// Confirm sign out
|
|
await modal.getByRole('button', { name: /sign out/i }).click();
|
|
|
|
// Should redirect to login
|
|
await expect(page).toHaveURL(/\/login/, { timeout: 15_000 });
|
|
}
|
|
});
|
|
});
|