import 'package:test/test.dart'; import 'package:sqlite3/sqlite3.dart'; import 'package:xp_nix/src/config/config_manager.dart'; import 'package:xp_nix/src/monitors/productivity_monitor.dart'; import 'package:xp_nix/src/testing/mock_activity_detector.dart'; import 'package:xp_nix/src/testing/mock_desktop_enhancer.dart'; import 'package:xp_nix/src/testing/mock_idle_monitor.dart'; import 'package:xp_nix/src/testing/mock_time_provider.dart'; void main() { group('Consolidation Tests', () { late Database db; late ProductivityMonitor monitor; late MockIdleMonitor mockIdleMonitor; late MockActivityDetector mockActivityDetector; late MockTimeProvider mockTimeProvider; late MockDesktopEnhancer mockDesktopEnhancer; setUp(() async { // Create in-memory database for testing db = sqlite3.openInMemory(); // Reset and initialize ConfigManager with default config ConfigManager.resetInstance(); await ConfigManager.instance.initialize('/tmp/test_config_${DateTime.now().millisecondsSinceEpoch}.json'); // Create mock dependencies mockIdleMonitor = MockIdleMonitor(); mockActivityDetector = MockActivityDetector(); mockTimeProvider = MockTimeProvider(); mockDesktopEnhancer = MockDesktopEnhancer(); // Set up starting time mockTimeProvider.setTime(DateTime(2024, 1, 1, 9, 0)); // Create monitor with mocked dependencies monitor = ProductivityMonitor( db: db, idleMonitor: mockIdleMonitor, timeProvider: mockTimeProvider, desktopEnhancer: mockDesktopEnhancer, activityDetector: mockActivityDetector, ); }); tearDown(() async { monitor.stop(); // Add a small delay to allow async operations to complete await Future.delayed(Duration(milliseconds: 100)); try { db.dispose(); } catch (e) { // Database might already be closed, ignore the error } }); test('unified monitor can be created and started', () async { expect(() => monitor.start(), returnsNormally); expect(monitor.getTodayStats(), isA>()); }); test('unified monitor processes activities correctly', () async { monitor.start(); await Future.delayed(Duration(milliseconds: 10)); // Simulate coding activity mockActivityDetector.simulateActivity('vscode', 'test.dart'); await Future.delayed(Duration(milliseconds: 10)); // Allow event processing mockTimeProvider.advanceTime(Duration(minutes: 30)); monitor.flushCurrentActivityForced(); final stats = monitor.getTodayStats(); expect(stats['xp'], greaterThan(0)); expect(stats['focus_time'], greaterThan(0)); }); test('unified monitor handles level ups', () async { monitor.start(); await Future.delayed(Duration(milliseconds: 10)); // Simulate enough activity to level up mockActivityDetector.simulateActivity('vscode', 'big_project.dart'); await Future.delayed(Duration(milliseconds: 10)); // Allow event processing mockTimeProvider.advanceTime(Duration(hours: 1)); monitor.flushCurrentActivityForced(); // Manually trigger level up check await monitor.checkForLevelUpNow(); final stats = monitor.getTodayStats(); expect(stats['level'], greaterThanOrEqualTo(2)); // Verify desktop enhancer was called print('Desktop enhancer operations: ${mockDesktopEnhancer.operations}'); expect(mockDesktopEnhancer.operations, isNotEmpty); expect(mockDesktopEnhancer.operations.any((op) => op.contains('celebrateLevelUp')), isTrue); }); test('unified monitor handles idle detection', () async { monitor.start(); await Future.delayed(Duration(milliseconds: 10)); // Start active mockIdleMonitor.simulateActive(); mockActivityDetector.simulateActivity('vscode', 'work.dart'); mockTimeProvider.advanceTime(Duration(minutes: 30)); monitor.flushCurrentActivity(); // Go idle mockIdleMonitor.simulateIdle(); mockTimeProvider.advanceTime(Duration(minutes: 90)); // Come back active mockIdleMonitor.simulateActive(); final stats = monitor.getTodayStats(); expect(stats['focus_sessions'], greaterThan(0)); }); }); }