Remade frontend dashboard as flutter dashboard, still WIP

This commit is contained in:
Nate Anderson
2025-06-13 09:20:42 -06:00
parent 8ea06b12f7
commit b373a93f0e
207 changed files with 9869 additions and 46 deletions
@@ -0,0 +1,187 @@
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('Simple Productivity Simulation 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('simulates basic coding session with XP calculation', () async {
// Start the monitor
monitor.start();
await Future.delayed(Duration(milliseconds: 10));
print('\n💻 Starting coding session...');
// Simulate 1 hour of coding
mockActivityDetector.simulateActivity('vscode', 'main.dart - TestProject');
await Future.delayed(Duration(milliseconds: 1)); // Allow event to be processed
mockTimeProvider.advanceTime(Duration(minutes: 60));
monitor.flushCurrentActivity();
// Check stats
final stats = monitor.getTodayStats();
print(
'📊 Stats: ${stats['xp']} XP, Level ${stats['level']}, ${(stats['focus_time'] / 3600).toStringAsFixed(1)}h focus',
);
// Verify XP was earned
expect(stats['xp'], greaterThan(0), reason: 'Should have earned XP from coding');
expect(stats['focus_time'], greaterThan(0), reason: 'Should have focus time from coding');
expect(stats['level'], greaterThanOrEqualTo(1), reason: 'Should have at least level 1');
// Expected: 60 minutes * 10 XP/min = 600 XP (plus any time multipliers)
expect(stats['xp'], greaterThan(500), reason: 'Should have substantial XP from 1 hour coding');
print('✅ Basic coding session test passed!');
});
test('simulates mixed activity day', () async {
monitor.start();
await Future.delayed(Duration(milliseconds: 10));
print('\n🔄 Simulating mixed activity day...');
// Morning coding (2 hours)
mockActivityDetector.simulateActivity('vscode', 'feature.dart');
await Future.delayed(Duration(milliseconds: 1));
mockTimeProvider.advanceTime(Duration(minutes: 120));
monitor.flushCurrentActivity();
// Meeting (1 hour)
mockActivityDetector.simulateActivity('zoom', 'Team Meeting');
await Future.delayed(Duration(milliseconds: 1));
mockTimeProvider.advanceTime(Duration(minutes: 60));
monitor.flushCurrentActivity();
// Research (30 minutes)
mockActivityDetector.simulateActivity('firefox', 'Documentation - dart.dev');
await Future.delayed(Duration(milliseconds: 1));
mockTimeProvider.advanceTime(Duration(minutes: 30));
monitor.flushCurrentActivity();
final stats = monitor.getTodayStats();
print('📊 Mixed day stats: ${stats['xp']} XP, Level ${stats['level']}');
print(
' Focus: ${(stats['focus_time'] / 3600).toStringAsFixed(1)}h, Meetings: ${(stats['meeting_time'] / 3600).toStringAsFixed(1)}h',
);
// Verify different activity types
expect(stats['xp'], greaterThan(1000), reason: 'Should have substantial XP from mixed activities');
expect(stats['focus_time'], greaterThan(0), reason: 'Should have focus time from coding and research');
expect(stats['meeting_time'], greaterThan(0), reason: 'Should have meeting time from zoom');
print('✅ Mixed activity day test passed!');
});
test('demonstrates XP calculation accuracy', () async {
monitor.start();
await Future.delayed(Duration(milliseconds: 10));
print('\n🧮 Testing XP calculation accuracy...');
// Test different activity types with known durations
final activities = [
('vscode', 'coding', 30, 10), // 30 min coding at 10 XP/min = 300 XP
('firefox', 'research', 20, 6), // 20 min research at 6 XP/min = 120 XP
('slack', 'collaboration', 15, 7), // 15 min collaboration at 7 XP/min = 105 XP
('zoom', 'meeting', 60, 3), // 60 min meeting at 3 XP/min = 180 XP
];
int expectedTotalXP = 0;
for (final (app, description, minutes, xpPerMin) in activities) {
mockActivityDetector.simulateActivity(app, description);
await Future.delayed(Duration(milliseconds: 1));
mockTimeProvider.advanceTime(Duration(minutes: minutes));
monitor.flushCurrentActivity();
expectedTotalXP += minutes * xpPerMin;
print(' $description: $minutes min × $xpPerMin XP/min = ${minutes * xpPerMin} XP');
}
final stats = monitor.getTodayStats();
final actualXP = stats['xp'] as int;
print('📊 Expected: ~$expectedTotalXP XP, Actual: $actualXP XP');
// Allow for time multipliers (should be close to expected)
expect(actualXP, greaterThan(expectedTotalXP * 0.8), reason: 'XP should be reasonably close to expected');
expect(actualXP, lessThan(expectedTotalXP * 2.0), reason: 'XP should not be wildly inflated');
print('✅ XP calculation accuracy test passed!');
});
test('verifies level progression', () async {
monitor.start();
await Future.delayed(Duration(milliseconds: 10));
print('\n📈 Testing level progression...');
// Simulate enough activity to level up (need 100+ XP per level)
for (int i = 0; i < 5; i++) {
mockActivityDetector.simulateActivity('vscode', 'level_up_test_$i.dart');
await Future.delayed(Duration(milliseconds: 1));
mockTimeProvider.advanceTime(Duration(minutes: 30)); // 30 min * 10 XP/min = 300 XP
monitor.flushCurrentActivity();
final stats = monitor.getTodayStats();
print(' Session ${i + 1}: ${stats['xp']} XP, Level ${stats['level']}');
}
final finalStats = monitor.getTodayStats();
expect(finalStats['level'], greaterThan(1), reason: 'Should have leveled up');
expect(finalStats['xp'], greaterThan(1000), reason: 'Should have substantial XP');
print('✅ Level progression test passed!');
});
});
}