#!/usr/bin/env tsx /** * End-to-end test: Simulate UI sync flow * - Start worker (or use existing) * - Trigger sync via syncQueue (like UI does) * - Monitor job status * - Verify database updates */ import 'dotenv/config'; import { syncQueue } from '../lib/queue/syncQueue'; import { db } from '../lib/db'; import { policySettings } from '../lib/db/schema/policySettings'; import { eq, desc } from 'drizzle-orm'; async function simulateUISync() { console.log('=== UI Sync Flow Test ===\n'); const tenantId = 'ui-test-tenant'; try { // Step 1: Enqueue job (like UI button does) console.log('1. Enqueueing sync job (simulating UI click)...'); const job = await syncQueue.add('sync-tenant', { tenantId, source: 'manual_trigger', triggeredAt: new Date().toISOString(), triggeredBy: 'test-user@example.com', }); console.log(` ✓ Job queued: #${job.id}\n`); // Step 2: Monitor job status console.log('2. Monitoring job status...'); let state = await job.getState(); let attempts = 0; const maxAttempts = 60; // 60 seconds timeout while (state !== 'completed' && state !== 'failed' && attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 1000)); state = await job.getState(); attempts++; if (attempts % 5 === 0) { console.log(` Job state: ${state} (${attempts}s elapsed)`); } } if (state === 'completed') { console.log(` ✓ Job completed after ${attempts}s\n`); const result = job.returnvalue; console.log('3. Job result:'); console.log(` Policies found: ${result?.policiesFound || 0}`); console.log(` Settings upserted: ${result?.settingsUpserted || 0}\n`); } else if (state === 'failed') { console.log(` ✗ Job failed: ${job.failedReason}\n`); return; } else { console.log(` ⚠ Job timeout (state: ${state})\n`); return; } // Step 3: Verify database console.log('4. Verifying database updates...'); const settings = await db .select() .from(policySettings) .where(eq(policySettings.tenantId, tenantId)) .orderBy(desc(policySettings.lastSyncedAt)) .limit(5); console.log(` ✓ Found ${settings.length} settings in database\n`); if (settings.length > 0) { console.log('5. Sample settings:'); settings.slice(0, 3).forEach((s, i) => { console.log(` ${i + 1}. ${s.policyName} → ${s.settingName}`); console.log(` Value: ${s.settingValue.substring(0, 60)}${s.settingValue.length > 60 ? '...' : ''}`); }); } console.log('\n=== Test Complete ✓ ==='); process.exit(0); } catch (error) { console.error('\n✗ Test failed:', error instanceof Error ? error.message : String(error)); if (error instanceof Error && error.stack) { console.error('\nStack:', error.stack); } process.exit(1); } } simulateUISync();