import 'dart:collection'; import 'package:mocktail/mocktail.dart'; import 'package:habo/habits/habit.dart'; import 'package:habo/repositories/habit_repository.dart'; import 'package:habo/repositories/event_repository.dart'; import 'package:habo/repositories/backup_repository.dart'; /// Mock implementation of HabitRepository for testing class MockHabitRepository extends Mock implements HabitRepository {} /// Mock implementation of EventRepository for testing class MockEventRepository extends Mock implements EventRepository {} /// Mock implementation of BackupRepository for testing class MockBackupRepository extends Mock implements BackupRepository {} /// In-memory implementation of HabitRepository for testing /// /// Provides a real implementation that stores data in memory /// instead of a database, useful for integration testing. class InMemoryHabitRepository implements HabitRepository { final List _habits = []; int _nextId = 1; @override Future> getAllHabits() async { return List.from(_habits); } @override Future createHabit(Habit habit) async { final id = _nextId++; habit.setId = id; _habits.add(habit); return id; } @override Future updateHabit(Habit habit) async { final index = _habits.indexWhere((h) => h.habitData.id == habit.habitData.id); if (index != -1) { _habits[index] = habit; } } @override Future deleteHabit(int id) async { _habits.removeWhere((habit) => habit.habitData.id == id); } @override Future findHabitById(int id) async { try { return _habits.firstWhere((habit) => habit.habitData.id == id); } catch (e) { return null; } } @override Future updateHabitsOrder(List habits) async { // Update positions in memory for (int i = 0; i < habits.length; i++) { habits[i].habitData.position = i; } } @override Future deleteAllHabits() async { _habits.clear(); } @override Future insertHabits(List habits) async { _habits.clear(); for (final habit in habits) { if (habit.habitData.id == null) { habit.setId = _nextId++; } else { _nextId = habit.habitData.id! + 1; } _habits.add(habit); } } /// Test helper method to clear all data void clear() { _habits.clear(); _nextId = 1; } /// Test helper method to get habit count int get habitCount => _habits.length; } /// In-memory implementation of EventRepository for testing class InMemoryEventRepository implements EventRepository { final Map> _events = {}; @override Future> getEventsForHabit(int habitId) async { final eventsMap = _events[habitId] ?? SplayTreeMap(); final events = []; eventsMap.forEach((dateTime, data) { events.add([dateTime, data[0], data[1]]); }); return events; } @override Future> getEventsMapForHabit(int habitId) async { return _events[habitId] ?? SplayTreeMap(); } @override Future insertEvent(int habitId, DateTime date, List event) async { _events[habitId] ??= SplayTreeMap(); _events[habitId]![date] = event; } @override Future deleteEvent(int habitId, DateTime date) async { _events[habitId]?.remove(date); } @override Future deleteAllEventsForHabit(int habitId) async { _events[habitId]?.clear(); } @override Future insertEventsForHabit( int habitId, Map events) async { _events[habitId] ??= SplayTreeMap(); _events[habitId]!.addAll(events); } @override Future deleteAllEvents() async { _events.clear(); } /// Test helper method to clear all data void clear() { _events.clear(); } /// Test helper method to get event count for a habit int getEventCountForHabit(int habitId) { return _events[habitId]?.length ?? 0; } } /// In-memory implementation of BackupRepository for testing class InMemoryBackupRepository implements BackupRepository { final List _backupHabits = []; final Map> _backupEvents = {}; bool _isDatabaseOpen = true; @override Future> exportAllData() async { return { 'habits': _backupHabits.map((h) => h.toJson()).toList(), 'events': _backupEvents, 'version': 3, }; } @override Future importData(Map data) async { _backupHabits.clear(); _backupEvents.clear(); if (data['habits'] != null) { for (var habitJson in data['habits']) { _backupHabits.add(Habit.fromJson(habitJson)); } } if (data['events'] != null) { _backupEvents.addAll(Map>.from(data['events'])); } } @override Future getDatabaseVersion() async { return 3; } @override Future getDatabasePath() async { return '/test/path/habo_test.db'; } @override Future closeDatabase() async { _isDatabaseOpen = false; } @override Future reopenDatabase() async { _isDatabaseOpen = true; } @override Future getHabitCount() async { return _backupHabits.length; } @override Future getEventCount() async { int count = 0; for (var events in _backupEvents.values) { count += events.length; } return count; } @override Future validateDatabaseIntegrity() async { // Simple validation - check if habits have required fields for (final habit in _backupHabits) { if (habit.habitData.id == null || habit.habitData.title.isEmpty) { return false; } } return _isDatabaseOpen; } /// Test helper method to clear all data void clear() { _backupHabits.clear(); _backupEvents.clear(); } /// Test helper method to get backup habit count int get backupHabitCount => _backupHabits.length; /// Test helper method to check if database is open bool get isDatabaseOpen => _isDatabaseOpen; }