#!/usr/bin/env python3 """ Quick verification script for automation progress bar fix Tests that the AutomationService methods return correct data structures """ import sys import os # Add backend to path sys.path.insert(0, '/data/app/igny8/backend') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings') import django django.setup() from igny8_core.business.automation.models import AutomationRun from igny8_core.business.automation.services import AutomationService def test_processing_state(): """Test that get_current_processing_state returns correct structure""" print("=" * 80) print("AUTOMATION PROGRESS BAR FIX - VERIFICATION TEST") print("=" * 80) # Find a recent running or paused run runs = AutomationRun.objects.filter(status__in=['running', 'paused']).order_by('-started_at')[:5] if not runs.exists(): print("\n❌ No running or paused automation runs found") print(" To test: Start an automation run from the UI") return print(f"\n✓ Found {runs.count()} active run(s)") for run in runs: print(f"\n{'='*80}") print(f"Run ID: {run.run_id}") print(f"Status: {run.status}") print(f"Current Stage: {run.current_stage}") print(f"Started: {run.started_at}") try: service = AutomationService.from_run_id(run.run_id) state = service.get_current_processing_state() if state is None: print("❌ get_current_processing_state() returned None") print(f" This should not happen for status='{run.status}'") continue # Verify required fields required_fields = [ 'stage_number', 'stage_name', 'stage_type', 'total_items', 'processed_items', 'percentage', 'currently_processing', 'up_next', 'remaining_count' ] print("\n✓ State object returned successfully") print("\nField values:") missing_fields = [] for field in required_fields: if field in state: value = state[field] if isinstance(value, list): print(f" • {field}: [{len(value)} items]") else: print(f" • {field}: {value}") else: missing_fields.append(field) print(f" ❌ {field}: MISSING") if missing_fields: print(f"\n❌ Missing fields: {', '.join(missing_fields)}") else: print("\n✓ All required fields present") # Verify progress calculation if state['total_items'] > 0: expected_pct = round((state['processed_items'] / state['total_items']) * 100) if state['percentage'] == expected_pct: print(f"✓ Progress calculation correct: {state['processed_items']}/{state['total_items']} = {state['percentage']}%") else: print(f"❌ Progress mismatch: expected {expected_pct}%, got {state['percentage']}%") # Check if paused state works if run.status == 'paused': print("\n✓ PAUSED RUN FIX VERIFIED: State returned for paused run!") print(" (Previously this would have returned None and caused blank card)") except Exception as e: print(f"❌ Error getting state: {e}") import traceback traceback.print_exc() print("\n" + "="*80) print("VERIFICATION COMPLETE") print("="*80) # Check for trace files print("\nChecking for JSONL trace files...") import glob trace_files = glob.glob('/data/app/logs/automation/*/*/run_*/run_trace.jsonl') if trace_files: print(f"✓ Found {len(trace_files)} trace file(s)") latest = sorted(trace_files, key=os.path.getmtime, reverse=True)[:3] print("\nMost recent trace files:") for f in latest: size = os.path.getsize(f) print(f" • {f} ({size} bytes)") # Check for stage_item_processed events try: with open(f, 'r') as tf: content = tf.read() if 'stage_item_processed' in content: count = content.count('stage_item_processed') print(f" ✓ Contains {count} stage_item_processed event(s)") else: print(f" ℹ No stage_item_processed events (may be older run)") except Exception: pass else: print("ℹ No trace files found yet (will appear for new runs)") print("\n" + "="*80) print("NEXT STEPS:") print("1. Start a new automation run from the UI") print("2. Watch the progress bar - it should animate smoothly") print("3. Try pausing - card should stay visible with yellow theme") print("4. Check logs in: /data/app/logs/automation////") print("5. Verify run_trace.jsonl contains 'stage_item_processed' events") print("="*80) if __name__ == '__main__': test_processing_state()