Remade frontend dashboard as flutter dashboard, still WIP
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:sqlite3/sqlite3.dart';
|
||||
import 'package:xp_nix/src/monitors/productivity_monitor.dart';
|
||||
import '../lib/src/testing/mock_idle_monitor.dart';
|
||||
import '../lib/src/testing/mock_activity_detector.dart';
|
||||
import '../lib/src/testing/mock_time_provider.dart';
|
||||
import '../lib/src/testing/mock_desktop_enhancer.dart';
|
||||
import '../lib/src/config/config_manager.dart';
|
||||
|
||||
void main() {
|
||||
group('Deep Idle Event 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 (Monday 9 AM)
|
||||
mockTimeProvider.setTime(DateTime(2024, 1, 1, 9, 0));
|
||||
|
||||
// Create testable monitor with mocked dependencies
|
||||
monitor = ProductivityMonitor(
|
||||
db: db,
|
||||
idleMonitor: mockIdleMonitor,
|
||||
activityDetector: mockActivityDetector,
|
||||
timeProvider: mockTimeProvider,
|
||||
desktopEnhancer: mockDesktopEnhancer,
|
||||
);
|
||||
});
|
||||
|
||||
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('should end current activity and award XP when user goes deep idle', () async {
|
||||
// Start the monitor
|
||||
monitor.start();
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
||||
print('\n🧪 Testing deep idle behavior...');
|
||||
|
||||
// Start a coding activity
|
||||
mockActivityDetector.simulateActivity('vscode', 'main.dart - TestProject');
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
||||
// Work for 30 minutes
|
||||
mockTimeProvider.advanceTime(Duration(minutes: 30));
|
||||
|
||||
// Check that no activity has been saved yet (still in progress)
|
||||
var stats = monitor.getTodayStats();
|
||||
var initialXP = stats['xp'] as int;
|
||||
print('📊 Initial XP before deep idle: $initialXP');
|
||||
|
||||
// User goes deep idle - this should trigger ending the current activity
|
||||
print('😴 User goes deep idle...');
|
||||
mockIdleMonitor.simulateDeepIdle();
|
||||
await Future.delayed(Duration(milliseconds: 50)); // Allow event processing
|
||||
|
||||
// Check that the activity was saved and XP was awarded
|
||||
stats = monitor.getTodayStats();
|
||||
var finalXP = stats['xp'] as int;
|
||||
var focusTime = stats['focus_time'] as int;
|
||||
|
||||
print('📊 Final XP after deep idle: $finalXP');
|
||||
print('📊 Focus time: ${(focusTime / 60).toStringAsFixed(1)} minutes');
|
||||
|
||||
// Verify that XP was awarded for the 30-minute coding session
|
||||
expect(finalXP, greaterThan(initialXP),
|
||||
reason: 'Should have earned XP from the coding session when going deep idle');
|
||||
|
||||
// Expected: 30 minutes * 10 XP/min = 300 XP (base, before multipliers)
|
||||
expect(finalXP, greaterThan(200),
|
||||
reason: 'Should have earned substantial XP from 30 minutes of coding');
|
||||
|
||||
// Should have focus time from coding
|
||||
expect(focusTime, greaterThan(25 * 60),
|
||||
reason: 'Should have at least 25 minutes of focus time recorded');
|
||||
|
||||
print('✅ Deep idle activity ending test passed!');
|
||||
});
|
||||
|
||||
test('should not duplicate XP when going from light idle to deep idle', () async {
|
||||
// Start the monitor
|
||||
monitor.start();
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
||||
print('\n🧪 Testing light idle to deep idle transition...');
|
||||
|
||||
// Start a coding activity
|
||||
mockActivityDetector.simulateActivity('vscode', 'feature.dart');
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
||||
// Work for 20 minutes
|
||||
mockTimeProvider.advanceTime(Duration(minutes: 20));
|
||||
|
||||
// User goes light idle first
|
||||
print('😐 User goes light idle...');
|
||||
mockIdleMonitor.simulateLightIdle();
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
|
||||
var stats = monitor.getTodayStats();
|
||||
var xpAfterLightIdle = stats['xp'] as int;
|
||||
print('📊 XP after light idle: $xpAfterLightIdle');
|
||||
|
||||
// Then user goes deep idle
|
||||
print('😴 User goes deep idle...');
|
||||
mockIdleMonitor.simulateDeepIdle();
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
|
||||
stats = monitor.getTodayStats();
|
||||
var xpAfterDeepIdle = stats['xp'] as int;
|
||||
print('📊 XP after deep idle: $xpAfterDeepIdle');
|
||||
|
||||
// XP should have been awarded when going deep idle, but not duplicated
|
||||
expect(xpAfterDeepIdle, greaterThan(0),
|
||||
reason: 'Should have earned XP from the coding session');
|
||||
|
||||
// The XP should be the same whether we went through light idle or not
|
||||
// (since the activity should only be saved once when going deep idle)
|
||||
expect(xpAfterDeepIdle, greaterThan(150),
|
||||
reason: 'Should have earned XP for 20 minutes of coding');
|
||||
|
||||
print('✅ Light idle to deep idle transition test passed!');
|
||||
});
|
||||
|
||||
test('should handle multiple activity sessions with deep idle interruptions', () async {
|
||||
// Start the monitor
|
||||
monitor.start();
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
||||
print('\n🧪 Testing multiple sessions with deep idle interruptions...');
|
||||
|
||||
// First coding session
|
||||
mockActivityDetector.simulateActivity('vscode', 'session1.dart');
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
mockTimeProvider.advanceTime(Duration(minutes: 25));
|
||||
|
||||
// Go deep idle (should end first session)
|
||||
mockIdleMonitor.simulateDeepIdle();
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
|
||||
var stats = monitor.getTodayStats();
|
||||
var xpAfterFirstSession = stats['xp'] as int;
|
||||
print('📊 XP after first session: $xpAfterFirstSession');
|
||||
|
||||
// User becomes active again
|
||||
mockIdleMonitor.simulateActive();
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
||||
// Second coding session
|
||||
mockActivityDetector.simulateActivity('vscode', 'session2.dart');
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
mockTimeProvider.advanceTime(Duration(minutes: 35));
|
||||
|
||||
// Go deep idle again (should end second session)
|
||||
mockIdleMonitor.simulateDeepIdle();
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
|
||||
stats = monitor.getTodayStats();
|
||||
var finalXP = stats['xp'] as int;
|
||||
var totalFocusTime = stats['focus_time'] as int;
|
||||
|
||||
print('📊 Final XP after both sessions: $finalXP');
|
||||
print('📊 Total focus time: ${(totalFocusTime / 60).toStringAsFixed(1)} minutes');
|
||||
|
||||
// Should have XP from both sessions
|
||||
expect(finalXP, greaterThan(xpAfterFirstSession),
|
||||
reason: 'Should have earned additional XP from second session');
|
||||
|
||||
// Should have substantial XP from 60 minutes total (25 + 35)
|
||||
expect(finalXP, greaterThan(400),
|
||||
reason: 'Should have earned substantial XP from both coding sessions');
|
||||
|
||||
// Should have focus time from both sessions (at least 55 minutes)
|
||||
expect(totalFocusTime, greaterThan(55 * 60),
|
||||
reason: 'Should have focus time from both sessions');
|
||||
|
||||
print('✅ Multiple sessions with deep idle test passed!');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user