timetracker/test/features/entries/entries_repository_test.dart
2026-08-03 21:51:48 +02:00

125 lines
3.8 KiB
Dart

import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:timetrack/core/database/app_database.dart' as db;
import 'package:timetrack/features/entries/data/drift_entries_repository.dart';
import 'package:timetrack/features/entries/domain/time_entry.dart';
import 'package:timetrack/features/projects/data/drift_projects_repository.dart';
import '../../helpers/sqlite_test_helper.dart';
TimeEntry makeEntry(int projectId, DateTime start, {DateTime? endTime, bool openEntry = false}) {
if (openEntry) {
return TimeEntry(
id: 0,
projectId: projectId,
startTime: start,
tags: const [],
createdAt: start,
);
}
final end = endTime ?? start.add(const Duration(hours: 1));
return TimeEntry(
id: 0,
projectId: projectId,
startTime: start,
endTime: end,
durationSeconds: end.difference(start).inSeconds,
tags: const [],
createdAt: start,
);
}
void main() {
setUpAll(configureSqliteForTests);
late db.AppDatabase database;
late DriftProjectsRepository projectsRepo;
late DriftTimeEntriesRepository entriesRepo;
setUp(() {
database = db.AppDatabase(NativeDatabase.memory());
projectsRepo = DriftProjectsRepository(database);
entriesRepo = DriftTimeEntriesRepository(database);
});
tearDown(() => database.close());
group('TimeEntriesRepository', () {
Future<int> createProject() =>
projectsRepo.create(name: 'Test', colorValue: 0xFF2563EB);
test('create and watchAll', () async {
final pid = await createProject();
final now = DateTime.now();
await entriesRepo.create(makeEntry(pid, now));
final entries = await entriesRepo.watchAll().first;
expect(entries, hasLength(1));
expect(entries.first.projectId, equals(pid));
});
test('getActiveEntry returns open entry', () async {
final pid = await createProject();
final now = DateTime.now();
await entriesRepo.create(makeEntry(pid, now, openEntry: true));
final active = await entriesRepo.getActiveEntry();
expect(active, isNotNull);
expect(active!.endTime, isNull);
});
test('getActiveEntry returns null when all entries complete', () async {
final pid = await createProject();
final now = DateTime.now();
await entriesRepo.create(
makeEntry(pid, now, endTime: now.add(const Duration(hours: 1))),
);
final active = await entriesRepo.getActiveEntry();
expect(active, isNull);
});
test('update modifies entry note', () async {
final pid = await createProject();
final now = DateTime.now();
await entriesRepo.create(makeEntry(pid, now));
final created = (await entriesRepo.watchAll().first).first;
await entriesRepo.update(created.copyWith(note: 'Updated note'));
final updated = (await entriesRepo.watchAll().first).first;
expect(updated.note, equals('Updated note'));
});
test('delete removes entry', () async {
final pid = await createProject();
final now = DateTime.now();
final id = await entriesRepo.create(makeEntry(pid, now));
await entriesRepo.delete(id);
final entries = await entriesRepo.watchAll().first;
expect(entries, isEmpty);
});
test('watchByDateRange filters correctly', () async {
final pid = await createProject();
final base = DateTime(2026, 6, 15);
await entriesRepo.create(
makeEntry(pid, base, endTime: base.add(const Duration(hours: 1))),
);
await entriesRepo.create(
makeEntry(
pid,
base.add(const Duration(days: 10)),
endTime: base.add(const Duration(days: 10, hours: 1)),
),
);
final inRange = await entriesRepo
.watchByDateRange(DateTime(2026, 6, 14), DateTime(2026, 6, 16))
.first;
expect(inRange, hasLength(1));
});
});
}