More tests, better functionality, the server serves the dashboard now on configurable ports. websocket stuff fixed, though I dont think data is really being sent / recieved...
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
import 'dart:io';
|
||||
import 'package:sqlite3/sqlite3.dart';
|
||||
import '../lib/src/database/database_manager.dart';
|
||||
|
||||
/// Creates golden test databases with specific scenarios for testing
|
||||
void main(List<String> args) {
|
||||
if (args.isEmpty) {
|
||||
print('Usage: dart create_golden_db.dart <scenario> [output_file]');
|
||||
print('');
|
||||
print('Available scenarios:');
|
||||
print(' high_achiever - User with many achievements and high level');
|
||||
print(' new_user - Fresh user with minimal data');
|
||||
print(' level_up_ready - User close to leveling up');
|
||||
print(' achievement_rich - User with many recent achievements');
|
||||
print(' focus_master - User with many focus sessions');
|
||||
print('');
|
||||
print('Examples:');
|
||||
print(' dart create_golden_db.dart high_achiever high_achiever_test.db');
|
||||
print(' dart create_golden_db.dart new_user new_user_test.db');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
final scenario = args[0];
|
||||
final outputFile = args.length > 1 ? args[1] : '${scenario}_test.db';
|
||||
|
||||
// Remove existing file if it exists
|
||||
final file = File(outputFile);
|
||||
if (file.existsSync()) {
|
||||
file.deleteSync();
|
||||
}
|
||||
|
||||
final db = sqlite3.open(outputFile);
|
||||
final dbManager = DatabaseManager(db);
|
||||
dbManager.initDatabase();
|
||||
|
||||
switch (scenario) {
|
||||
case 'high_achiever':
|
||||
_createHighAchieverScenario(dbManager);
|
||||
break;
|
||||
case 'new_user':
|
||||
_createNewUserScenario(dbManager);
|
||||
break;
|
||||
case 'level_up_ready':
|
||||
_createLevelUpReadyScenario(dbManager);
|
||||
break;
|
||||
case 'achievement_rich':
|
||||
_createAchievementRichScenario(dbManager);
|
||||
break;
|
||||
case 'focus_master':
|
||||
_createFocusMasterScenario(dbManager);
|
||||
break;
|
||||
default:
|
||||
print('Unknown scenario: $scenario');
|
||||
db.dispose();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
db.dispose();
|
||||
print('✅ Golden test database created: $outputFile');
|
||||
print('📊 Scenario: $scenario');
|
||||
}
|
||||
|
||||
void _createHighAchieverScenario(DatabaseManager dbManager) {
|
||||
print('🏆 Creating high achiever scenario...');
|
||||
|
||||
final now = DateTime.now();
|
||||
final today = now.toIso8601String().substring(0, 10);
|
||||
final timestamp = now.millisecondsSinceEpoch;
|
||||
|
||||
// High-level user with lots of XP
|
||||
dbManager.updateDailyStats(2500, 28800, 7200); // Level 8-9 range
|
||||
|
||||
// Extensive activity history
|
||||
dbManager.saveActivityEvent('coding', 'vscode', '{"project": "major_project"}', timestamp - 3600000, 7200);
|
||||
dbManager.saveActivityEvent('coding', 'intellij', '{"project": "backend_service"}', timestamp - 7200000, 5400);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'firefox', '{"url": "stackoverflow.com"}', timestamp - 10800000, 3600);
|
||||
dbManager.saveActivityEvent('collaboration', 'slack', '{"channel": "engineering"}', timestamp - 14400000, 1800);
|
||||
dbManager.saveActivityEvent('meetings', 'zoom', '{"meeting": "architecture-review"}', timestamp - 18000000, 3600);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'chrome', '{"url": "docs.flutter.dev"}', timestamp - 21600000, 2400);
|
||||
|
||||
// Many focus sessions
|
||||
for (int i = 0; i < 8; i++) {
|
||||
dbManager.saveFocusSession(today, 45 + (i % 3) * 15, 60 + (i % 4) * 15, timestamp - (i * 3600000));
|
||||
}
|
||||
|
||||
// Multiple achievements
|
||||
dbManager.saveAchievement('First Steps', 'Complete your first activity', 25, timestamp - 604800000, 1);
|
||||
dbManager.saveAchievement('Code Warrior', 'Code for 8 hours in one day', 100, timestamp - 518400000, 3);
|
||||
dbManager.saveAchievement('Focus Master', 'Complete 5 focus sessions', 75, timestamp - 432000000, 4);
|
||||
dbManager.saveAchievement('Collaboration King', 'Spend 4 hours in meetings', 80, timestamp - 345600000, 5);
|
||||
dbManager.saveAchievement('Deep Thinker', 'Complete 10 focus sessions', 150, timestamp - 259200000, 6);
|
||||
dbManager.saveAchievement('Productivity Guru', 'Reach level 7', 200, timestamp - 172800000, 7);
|
||||
dbManager.saveAchievement('Elite Coder', 'Code for 50 hours total', 300, timestamp - 86400000, 8);
|
||||
|
||||
// Application classifications
|
||||
dbManager.saveApplicationClassification('vscode', 'coding');
|
||||
dbManager.saveApplicationClassification('intellij', 'coding');
|
||||
dbManager.saveApplicationClassification('firefox', 'focused_browsing');
|
||||
dbManager.saveApplicationClassification('chrome', 'focused_browsing');
|
||||
dbManager.saveApplicationClassification('slack', 'collaboration');
|
||||
dbManager.saveApplicationClassification('zoom', 'meetings');
|
||||
}
|
||||
|
||||
void _createNewUserScenario(DatabaseManager dbManager) {
|
||||
print('👶 Creating new user scenario...');
|
||||
|
||||
final now = DateTime.now();
|
||||
final today = now.toIso8601String().substring(0, 10);
|
||||
final timestamp = now.millisecondsSinceEpoch;
|
||||
|
||||
// Minimal stats - new user
|
||||
dbManager.updateDailyStats(50, 1800, 0); // Level 1, 50 XP, 30 min focus
|
||||
|
||||
// Just a few activities
|
||||
dbManager.saveActivityEvent('coding', 'vscode', '{"project": "hello_world"}', timestamp - 1800000, 1800);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'firefox', '{"url": "flutter.dev"}', timestamp - 3600000, 900);
|
||||
|
||||
// One focus session
|
||||
dbManager.saveFocusSession(today, 25, 25, timestamp - 1800000);
|
||||
|
||||
// First achievement only
|
||||
dbManager.saveAchievement('First Steps', 'Welcome to productivity tracking!', 25, timestamp - 1800000, 1);
|
||||
|
||||
// Basic classifications
|
||||
dbManager.saveApplicationClassification('vscode', 'coding');
|
||||
dbManager.saveApplicationClassification('firefox', 'focused_browsing');
|
||||
|
||||
// Some unclassified apps
|
||||
dbManager.trackUnclassifiedApplication('unknown_editor');
|
||||
dbManager.trackUnclassifiedApplication('random_app');
|
||||
}
|
||||
|
||||
void _createLevelUpReadyScenario(DatabaseManager dbManager) {
|
||||
print('🚀 Creating level up ready scenario...');
|
||||
|
||||
final now = DateTime.now();
|
||||
final today = now.toIso8601String().substring(0, 10);
|
||||
final timestamp = now.millisecondsSinceEpoch;
|
||||
|
||||
// Just below level 5 threshold (typically around 800-900 XP)
|
||||
dbManager.updateDailyStats(850, 14400, 3600); // Close to level 5
|
||||
|
||||
// Good amount of activities
|
||||
dbManager.saveActivityEvent('coding', 'vscode', '{"project": "important_feature"}', timestamp - 3600000, 5400);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'firefox', '{"url": "documentation"}', timestamp - 7200000, 2700);
|
||||
dbManager.saveActivityEvent('collaboration', 'slack', '{"channel": "team"}', timestamp - 10800000, 1800);
|
||||
dbManager.saveActivityEvent('meetings', 'zoom', '{"meeting": "planning"}', timestamp - 14400000, 1800);
|
||||
|
||||
// Several focus sessions
|
||||
dbManager.saveFocusSession(today, 45, 50, timestamp - 3600000);
|
||||
dbManager.saveFocusSession(today, 30, 35, timestamp - 7200000);
|
||||
dbManager.saveFocusSession(today, 60, 75, timestamp - 10800000);
|
||||
dbManager.saveFocusSession(today, 25, 30, timestamp - 14400000);
|
||||
|
||||
// Progressive achievements
|
||||
dbManager.saveAchievement('First Steps', 'Started tracking', 25, timestamp - 345600000, 1);
|
||||
dbManager.saveAchievement('Getting Started', 'First hour of focus', 50, timestamp - 259200000, 2);
|
||||
dbManager.saveAchievement('Building Momentum', 'Consistent daily activity', 75, timestamp - 172800000, 3);
|
||||
dbManager.saveAchievement('Focused Worker', 'Multiple focus sessions', 100, timestamp - 86400000, 4);
|
||||
|
||||
// Classifications
|
||||
dbManager.saveApplicationClassification('vscode', 'coding');
|
||||
dbManager.saveApplicationClassification('firefox', 'focused_browsing');
|
||||
dbManager.saveApplicationClassification('slack', 'collaboration');
|
||||
dbManager.saveApplicationClassification('zoom', 'meetings');
|
||||
}
|
||||
|
||||
void _createAchievementRichScenario(DatabaseManager dbManager) {
|
||||
print('🏅 Creating achievement rich scenario...');
|
||||
|
||||
final now = DateTime.now();
|
||||
final today = now.toIso8601String().substring(0, 10);
|
||||
final timestamp = now.millisecondsSinceEpoch;
|
||||
|
||||
// Moderate stats
|
||||
dbManager.updateDailyStats(1200, 18000, 5400);
|
||||
|
||||
// Standard activities
|
||||
dbManager.saveActivityEvent('coding', 'vscode', '{"project": "achievement_test"}', timestamp - 3600000, 3600);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'firefox', '{"url": "research"}', timestamp - 7200000, 1800);
|
||||
dbManager.saveActivityEvent('collaboration', 'slack', '{"channel": "general"}', timestamp - 10800000, 900);
|
||||
|
||||
// Focus sessions
|
||||
dbManager.saveFocusSession(today, 45, 50, timestamp - 3600000);
|
||||
dbManager.saveFocusSession(today, 30, 35, timestamp - 7200000);
|
||||
|
||||
// Many recent achievements (great for testing achievement notifications)
|
||||
final achievementTimestamps = [
|
||||
timestamp - 300000, // 5 minutes ago
|
||||
timestamp - 600000, // 10 minutes ago
|
||||
timestamp - 1800000, // 30 minutes ago
|
||||
timestamp - 3600000, // 1 hour ago
|
||||
timestamp - 7200000, // 2 hours ago
|
||||
];
|
||||
|
||||
dbManager.saveAchievement('Speed Demon', 'Complete task in under 5 minutes', 50, achievementTimestamps[0], 5);
|
||||
dbManager.saveAchievement('Consistency King', 'Work for 7 days straight', 100, achievementTimestamps[1], 5);
|
||||
dbManager.saveAchievement('Focus Champion', 'Complete 3 focus sessions today', 75, achievementTimestamps[2], 5);
|
||||
dbManager.saveAchievement('Code Master', 'Write code for 6 hours', 125, achievementTimestamps[3], 5);
|
||||
dbManager.saveAchievement('Collaboration Expert', 'Participate in 5 meetings', 80, achievementTimestamps[4], 5);
|
||||
|
||||
// Earlier achievements
|
||||
dbManager.saveAchievement('First Steps', 'Welcome!', 25, timestamp - 604800000, 1);
|
||||
dbManager.saveAchievement('Getting Going', 'First week complete', 50, timestamp - 518400000, 2);
|
||||
dbManager.saveAchievement('Momentum Builder', 'Consistent activity', 75, timestamp - 432000000, 3);
|
||||
dbManager.saveAchievement('Steady Progress', 'Level 4 reached', 100, timestamp - 345600000, 4);
|
||||
|
||||
// Classifications
|
||||
dbManager.saveApplicationClassification('vscode', 'coding');
|
||||
dbManager.saveApplicationClassification('firefox', 'focused_browsing');
|
||||
dbManager.saveApplicationClassification('slack', 'collaboration');
|
||||
}
|
||||
|
||||
void _createFocusMasterScenario(DatabaseManager dbManager) {
|
||||
print('🧘 Creating focus master scenario...');
|
||||
|
||||
final now = DateTime.now();
|
||||
final today = now.toIso8601String().substring(0, 10);
|
||||
final timestamp = now.millisecondsSinceEpoch;
|
||||
|
||||
// High focus time stats
|
||||
dbManager.updateDailyStats(1800, 32400, 1800); // 9 hours of focus time!
|
||||
|
||||
// Focus-heavy activities
|
||||
dbManager.saveActivityEvent('coding', 'vscode', '{"project": "deep_work_project"}', timestamp - 3600000, 10800);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'firefox', '{"url": "research_paper"}', timestamp - 14400000, 7200);
|
||||
dbManager.saveActivityEvent('coding', 'vim', '{"project": "algorithm_implementation"}', timestamp - 21600000, 5400);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'chrome', '{"url": "documentation"}', timestamp - 28800000, 3600);
|
||||
|
||||
// Many focus sessions of varying lengths
|
||||
final sessionData = [
|
||||
[90, 120], [60, 80], [45, 60], [120, 150], [30, 40],
|
||||
[75, 95], [50, 65], [105, 130], [25, 35], [80, 100],
|
||||
[40, 50], [95, 115], [35, 45], [110, 140], [55, 70]
|
||||
];
|
||||
|
||||
for (int i = 0; i < sessionData.length; i++) {
|
||||
final duration = sessionData[i][0];
|
||||
final bonusXp = sessionData[i][1];
|
||||
dbManager.saveFocusSession(today, duration, bonusXp, timestamp - (i * 1800000));
|
||||
}
|
||||
|
||||
// Focus-related achievements
|
||||
dbManager.saveAchievement('First Focus', 'Complete first focus session', 25, timestamp - 1209600000, 1);
|
||||
dbManager.saveAchievement('Focus Streak', 'Complete 5 focus sessions', 75, timestamp - 1036800000, 2);
|
||||
dbManager.saveAchievement('Deep Work', 'Complete 90-minute focus session', 100, timestamp - 864000000, 3);
|
||||
dbManager.saveAchievement('Focus Marathon', 'Complete 10 focus sessions in one day', 150, timestamp - 691200000, 4);
|
||||
dbManager.saveAchievement('Concentration Master', 'Complete 2-hour focus session', 200, timestamp - 518400000, 5);
|
||||
dbManager.saveAchievement('Focus Guru', 'Complete 50 total focus sessions', 300, timestamp - 345600000, 6);
|
||||
dbManager.saveAchievement('Zen Master', 'Complete 8 hours of focus in one day', 400, timestamp - 172800000, 7);
|
||||
|
||||
// Classifications
|
||||
dbManager.saveApplicationClassification('vscode', 'coding');
|
||||
dbManager.saveApplicationClassification('vim', 'coding');
|
||||
dbManager.saveApplicationClassification('firefox', 'focused_browsing');
|
||||
dbManager.saveApplicationClassification('chrome', 'focused_browsing');
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:sqlite3/sqlite3.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
import '../lib/src/database/database_manager.dart';
|
||||
import '../lib/src/web/dashboard_server.dart';
|
||||
import '../lib/src/web/websocket_manager.dart';
|
||||
import '../lib/src/models/activity_event.dart';
|
||||
|
||||
void main() {
|
||||
group('WebSocket Integration Tests', () {
|
||||
late Database inMemoryDb;
|
||||
late DatabaseManager dbManager;
|
||||
late DashboardServer server;
|
||||
late WebSocketChannel wsChannel;
|
||||
final int testPort = 8081;
|
||||
|
||||
setUpAll(() async {
|
||||
// Create in-memory database
|
||||
inMemoryDb = sqlite3.openInMemory();
|
||||
dbManager = DatabaseManager(inMemoryDb);
|
||||
dbManager.initDatabase();
|
||||
|
||||
// Populate database with test data
|
||||
await _populateTestData(dbManager);
|
||||
|
||||
// Start server with test database
|
||||
server = DashboardServer.withDatabase(dbManager);
|
||||
await server.start(testPort);
|
||||
|
||||
// Give server time to start
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
await wsChannel.sink.close();
|
||||
await server.stop();
|
||||
inMemoryDb.dispose();
|
||||
});
|
||||
|
||||
test('WebSocket connection and message types', () async {
|
||||
// Connect to WebSocket
|
||||
wsChannel = WebSocketChannel.connect(
|
||||
Uri.parse('ws://localhost:$testPort/ws'),
|
||||
);
|
||||
|
||||
final receivedMessages = <Map<String, dynamic>>[];
|
||||
|
||||
// Listen for messages
|
||||
wsChannel.stream.listen(
|
||||
(message) {
|
||||
final data = jsonDecode(message as String) as Map<String, dynamic>;
|
||||
receivedMessages.add(data);
|
||||
},
|
||||
onError: (error) {
|
||||
fail('WebSocket error: $error');
|
||||
},
|
||||
);
|
||||
|
||||
// Test 1: Ping/Pong
|
||||
print('Testing ping/pong...');
|
||||
wsChannel.sink.add(jsonEncode({
|
||||
'type': 'ping',
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
}));
|
||||
|
||||
// Wait for pong response
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
expect(receivedMessages.length, equals(1));
|
||||
expect(receivedMessages[0]['type'], equals('pong'));
|
||||
expect(receivedMessages[0]['timestamp'], isA<int>());
|
||||
|
||||
receivedMessages.clear();
|
||||
|
||||
// Test 2: Stats Update Message
|
||||
print('Testing stats update broadcast...');
|
||||
final wsManager = WebSocketManager.instance;
|
||||
|
||||
// Create and broadcast stats update
|
||||
final statsData = {
|
||||
'today': {
|
||||
'level': 5,
|
||||
'xp': 450,
|
||||
'focus_time': 7200,
|
||||
'meeting_time': 3600,
|
||||
'focus_sessions': 3,
|
||||
},
|
||||
'streaks': {
|
||||
'current_streak': 7,
|
||||
'longest_streak': 15,
|
||||
},
|
||||
'recent_activity': [
|
||||
{
|
||||
'type': 'coding',
|
||||
'application': 'vscode',
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
'duration_seconds': 1800,
|
||||
}
|
||||
],
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
};
|
||||
|
||||
wsManager.broadcast({
|
||||
'type': 'stats_update',
|
||||
'data': statsData,
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(receivedMessages.length, equals(1));
|
||||
expect(receivedMessages[0]['type'], equals('stats_update'));
|
||||
expect(receivedMessages[0]['data']['today']['level'], equals(5));
|
||||
expect(receivedMessages[0]['data']['today']['xp'], equals(450));
|
||||
|
||||
receivedMessages.clear();
|
||||
|
||||
// Test 3: XP Breakdown Update
|
||||
print('Testing XP breakdown update...');
|
||||
final xpBreakdown = {
|
||||
'coding': 300,
|
||||
'focused_browsing': 120,
|
||||
'collaboration': 80,
|
||||
'meetings': 60,
|
||||
'focus_session': 100,
|
||||
};
|
||||
|
||||
wsManager.broadcast({
|
||||
'type': 'xp_breakdown_update',
|
||||
'data': xpBreakdown,
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(receivedMessages.length, equals(1));
|
||||
expect(receivedMessages[0]['type'], equals('xp_breakdown_update'));
|
||||
expect(receivedMessages[0]['data']['coding'], equals(300));
|
||||
expect(receivedMessages[0]['data']['focused_browsing'], equals(120));
|
||||
|
||||
receivedMessages.clear();
|
||||
|
||||
// Test 4: Achievement Unlocked
|
||||
print('Testing achievement unlocked...');
|
||||
final achievement = {
|
||||
'id': 1,
|
||||
'name': 'Code Warrior',
|
||||
'description': 'Spent 10 hours coding in a single day',
|
||||
'xp_reward': 100,
|
||||
'achieved_at': DateTime.now().millisecondsSinceEpoch,
|
||||
'level_at_achievement': 5,
|
||||
};
|
||||
|
||||
wsManager.broadcast({
|
||||
'type': 'achievement_unlocked',
|
||||
'data': achievement,
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(receivedMessages.length, equals(1));
|
||||
expect(receivedMessages[0]['type'], equals('achievement_unlocked'));
|
||||
expect(receivedMessages[0]['data']['name'], equals('Code Warrior'));
|
||||
expect(receivedMessages[0]['data']['xp_reward'], equals(100));
|
||||
|
||||
receivedMessages.clear();
|
||||
|
||||
// Test 5: Level Up
|
||||
print('Testing level up...');
|
||||
wsManager.broadcast({
|
||||
'type': 'level_up',
|
||||
'data': {'level': 6},
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(receivedMessages.length, equals(1));
|
||||
expect(receivedMessages[0]['type'], equals('level_up'));
|
||||
expect(receivedMessages[0]['data']['level'], equals(6));
|
||||
|
||||
receivedMessages.clear();
|
||||
|
||||
// Test 6: Focus Session Complete
|
||||
print('Testing focus session complete...');
|
||||
final focusSession = {
|
||||
'id': 1,
|
||||
'date': DateTime.now().toIso8601String().substring(0, 10),
|
||||
'duration_minutes': 45,
|
||||
'bonus_xp': 50,
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
};
|
||||
|
||||
wsManager.broadcast({
|
||||
'type': 'focus_session_complete',
|
||||
'data': focusSession,
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(receivedMessages.length, equals(1));
|
||||
expect(receivedMessages[0]['type'], equals('focus_session_complete'));
|
||||
expect(receivedMessages[0]['data']['duration_minutes'], equals(45));
|
||||
expect(receivedMessages[0]['data']['bonus_xp'], equals(50));
|
||||
|
||||
receivedMessages.clear();
|
||||
|
||||
print('All WebSocket message types tested successfully!');
|
||||
});
|
||||
|
||||
test('Database integration with WebSocket messages', () async {
|
||||
// Test that database queries work correctly and can feed WebSocket messages
|
||||
|
||||
// Test today's stats
|
||||
final todayStats = dbManager.getTodayStats();
|
||||
expect(todayStats['level'], greaterThan(0));
|
||||
expect(todayStats['xp'], greaterThan(0));
|
||||
|
||||
// Test XP breakdown
|
||||
final xpBreakdown = dbManager.getTodayXPBreakdown();
|
||||
expect(xpBreakdown, isNotEmpty);
|
||||
expect(xpBreakdown.containsKey('coding'), isTrue);
|
||||
|
||||
// Test achievements
|
||||
final achievements = dbManager.getAllAchievements();
|
||||
expect(achievements.length, greaterThan(0));
|
||||
|
||||
// Test recent activities
|
||||
final activities = dbManager.getRecentActivity();
|
||||
expect(activities.length, greaterThan(0));
|
||||
|
||||
// Test focus sessions
|
||||
final focusSessions = dbManager.getRecentFocusSessions();
|
||||
expect(focusSessions.length, greaterThan(0));
|
||||
|
||||
print('Database integration verified successfully!');
|
||||
});
|
||||
|
||||
test('WebSocket connection management', () async {
|
||||
final wsManager = WebSocketManager.instance;
|
||||
final initialConnectionCount = wsManager.connectionCount;
|
||||
|
||||
// Connect additional WebSocket
|
||||
final wsChannel2 = WebSocketChannel.connect(
|
||||
Uri.parse('ws://localhost:$testPort/ws'),
|
||||
);
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(wsManager.connectionCount, equals(initialConnectionCount + 1));
|
||||
|
||||
// Test broadcasting to multiple connections
|
||||
final receivedMessages2 = <Map<String, dynamic>>[];
|
||||
|
||||
// Only listen to the new channel to avoid "already listened" error
|
||||
wsChannel2.stream.listen((message) {
|
||||
receivedMessages2.add(jsonDecode(message as String));
|
||||
});
|
||||
|
||||
// Broadcast a message
|
||||
wsManager.broadcast({
|
||||
'type': 'test_broadcast',
|
||||
'data': {'message': 'Hello all connections!'},
|
||||
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
|
||||
// Verify the new connection received the broadcast
|
||||
expect(receivedMessages2.length, greaterThan(0));
|
||||
expect(receivedMessages2.last['type'], equals('test_broadcast'));
|
||||
|
||||
// Close second connection
|
||||
await wsChannel2.sink.close();
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
|
||||
expect(wsManager.connectionCount, equals(initialConnectionCount));
|
||||
|
||||
print('WebSocket connection management tested successfully!');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _populateTestData(DatabaseManager dbManager) async {
|
||||
final now = DateTime.now();
|
||||
final today = now.toIso8601String().substring(0, 10);
|
||||
final timestamp = now.millisecondsSinceEpoch;
|
||||
|
||||
// Add activity events
|
||||
dbManager.saveActivityEvent('coding', 'vscode', '{"project": "test"}', timestamp - 3600000, 1800);
|
||||
dbManager.saveActivityEvent('focused_browsing', 'firefox', '{"url": "docs.flutter.dev"}', timestamp - 7200000, 1200);
|
||||
dbManager.saveActivityEvent('collaboration', 'slack', '{"channel": "dev-team"}', timestamp - 10800000, 900);
|
||||
dbManager.saveActivityEvent('meetings', 'zoom', '{"meeting": "standup"}', timestamp - 14400000, 1800);
|
||||
dbManager.saveActivityEvent('misc', 'keepassxc', null, timestamp - 18000000, 300);
|
||||
|
||||
// Update daily stats
|
||||
dbManager.updateDailyStats(450, 7200, 3600);
|
||||
|
||||
// Add focus sessions
|
||||
dbManager.saveFocusSession(today, 45, 50, timestamp - 3600000);
|
||||
dbManager.saveFocusSession(today, 30, 30, timestamp - 7200000);
|
||||
dbManager.saveFocusSession(today, 60, 75, timestamp - 10800000);
|
||||
|
||||
// Add achievements
|
||||
dbManager.saveAchievement(
|
||||
'First Steps',
|
||||
'Complete your first activity tracking session',
|
||||
25,
|
||||
timestamp - 86400000,
|
||||
1,
|
||||
);
|
||||
dbManager.saveAchievement(
|
||||
'Code Warrior',
|
||||
'Spend 10 hours coding in a single day',
|
||||
100,
|
||||
timestamp - 43200000,
|
||||
3,
|
||||
);
|
||||
dbManager.saveAchievement(
|
||||
'Focus Master',
|
||||
'Complete 5 focus sessions in one day',
|
||||
75,
|
||||
timestamp - 21600000,
|
||||
4,
|
||||
);
|
||||
|
||||
// Add application classifications
|
||||
dbManager.saveApplicationClassification('vscode', 'coding');
|
||||
dbManager.saveApplicationClassification('firefox', 'focused_browsing');
|
||||
dbManager.saveApplicationClassification('slack', 'collaboration');
|
||||
dbManager.saveApplicationClassification('zoom', 'meetings');
|
||||
|
||||
// Add some unclassified applications
|
||||
dbManager.trackUnclassifiedApplication('unknown_app_1');
|
||||
dbManager.trackUnclassifiedApplication('unknown_app_2');
|
||||
|
||||
print('Test data populated successfully');
|
||||
}
|
||||
Reference in New Issue
Block a user