feat: Global E2E tests, multi-agent fixes, SIP agent tracing

- 13 Global Hospital smoke tests (CC Agent + Supervisor)
- Auto-unlock agent session in test setup via maint API
- agent-status-toggle sends agentId from localStorage (was missing)
- maint-otp-modal injects agentId from localStorage into all calls
- SIP manager logs agent identity on connect/disconnect/state changes
- seed-data.ts: added CC agent + marketing users, idempotent member
  creation, cleanup phase before seeding
- .gitignore: exclude test-results/ and playwright-report/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-11 12:12:22 +05:30
parent f09250f3ef
commit cb4894ddc3
9 changed files with 247 additions and 8 deletions

View File

@@ -68,6 +68,14 @@ async function ensureWorkspaceContext() {
async function mkMember(email: string, password: string, firstName: string, lastName: string, roleName?: string): Promise<string> {
await ensureWorkspaceContext();
// Check if already exists
const existing = await gql('{ workspaceMembers { edges { node { id userEmail } } } }');
const found = existing.workspaceMembers.edges.find((e: any) => e.node.userEmail.toLowerCase() === email.toLowerCase());
if (found) {
console.log(` (exists) ${email}${found.node.id}`);
return found.node.id;
}
// Create the user + link to workspace
await gql(
`mutation($email: String!, $password: String!, $workspaceId: UUID!, $workspaceInviteHash: String!) {
@@ -99,11 +107,37 @@ async function mkMember(email: string, password: string, firstName: string, last
return memberId;
}
async function clearAll() {
// Delete in reverse dependency order
const entities = ['followUp', 'leadActivity', 'call', 'appointment', 'lead', 'patient', 'doctorVisitSlot', 'doctor', 'campaign', 'clinic'];
for (const entity of entities) {
const cap = entity[0].toUpperCase() + entity.slice(1);
try {
const data = await gql(`{ ${entity}s(first: 100) { edges { node { id } } } }`);
const ids: string[] = data[`${entity}s`].edges.map((e: any) => e.node.id);
if (ids.length === 0) { console.log(` ${cap}: 0 records`); continue; }
for (const id of ids) {
await gql(`mutation { delete${cap}(id: "${id}") { id } }`);
}
console.log(` ${cap}: deleted ${ids.length}`);
} catch (err: any) {
console.log(` ${cap}: skip (${err.message?.slice(0, 60)})`);
}
}
}
async function main() {
console.log('🌱 Seeding Helix Engage demo data...\n');
await auth();
console.log('✅ Auth OK\n');
// Clean slate — remove all existing entity data (not users)
console.log('🧹 Clearing existing data...');
await clearAll();
console.log('');
await auth();
// ═══════════════════════════════════════════
// CLINICS (needed for doctor visit slots)
// ═══════════════════════════════════════════
@@ -136,6 +170,25 @@ async function main() {
await auth();
// ═══════════════════════════════════════════
// CALL CENTER & MARKETING STAFF
//
// CC agents (HelixEngage User role) handle inbound/outbound calls.
// Marketing executives and supervisors use HelixEngage Supervisor role.
// Email domain uses globalcare.com to match the deployment.
// ═══════════════════════════════════════════
console.log('📞 Call center & marketing staff');
const wmRekha = await mkMember('rekha.cc@globalcare.com', 'Global@123', 'Rekha', 'Nair', 'HelixEngage User');
console.log(` Rekha (CC Agent): ${wmRekha}`);
const wmGanesh = await mkMember('ganesh.cc@globalcare.com', 'Global@123', 'Ganesh', 'Iyer', 'HelixEngage User');
console.log(` Ganesh (CC Agent): ${wmGanesh}`);
const wmSanjay = await mkMember('sanjay.marketing@globalcare.com', 'Global@123', 'Sanjay', 'Verma', 'HelixEngage Supervisor');
console.log(` Sanjay (Marketing): ${wmSanjay}`);
const wmRamesh = await mkMember('dr.ramesh@globalcare.com', 'Global@123', 'Ramesh', 'Gupta', 'HelixEngage Supervisor');
console.log(` Dr. Ramesh (Supervisor): ${wmRamesh}\n`);
await auth();
// ═══════════════════════════════════════════
// DOCTOR WORKSPACE MEMBERS
//