# TT-012 — Unit Tests **Type:** Task **Priority:** Medium **Labels:** testing, unit-tests **Depends on:** TT-004, TT-005 **Blocks:** — --- ## Summary Write comprehensive unit tests for all repository methods and Riverpod notifiers. See `.ai/testing.md` for full conventions. ## Scope ### Database / Repository tests All tests use `NativeDatabase.memory()` — never the real file DB. | Test file | What to test | |-----------|-------------| | `test/core/database/app_database_test.dart` | Schema creation, schemaVersion | | `test/features/projects/projects_repository_test.dart` | CRUD, watchActive stream, archive | | `test/features/entries/entries_repository_test.dart` | CRUD, watchByDateRange, getActiveEntry | | `test/features/entries/tags_repository_test.dart` | findOrCreate, setTagsForEntry | | `test/features/reports/reports_repository_test.dart` | getDurationByProject, getDurationByWeekday | ### Notifier tests All notifier tests use `ProviderContainer` with mocked repositories. | Test file | What to test | |-----------|-------------| | `test/features/timer/timer_notifier_test.dart` | start, stop, discard, restore from open entry | | `test/features/projects/projects_notifier_test.dart` | create, update, archive, delete | | `test/features/entries/entries_notifier_test.dart` | create, update, delete | ## Test Patterns ### Repository test pattern ```dart late AppDatabase db; late DriftProjectsRepository repository; setUp(() { db = AppDatabase(NativeDatabase.memory()); repository = DriftProjectsRepository(db); }); tearDown(() => db.close()); test('insert and retrieve project', () async { await repository.create(name: 'Test', colorValue: 0xFF0000FF); final projects = await repository.watchActive().first; expect(projects, hasLength(1)); expect(projects.first.name, equals('Test')); }); ``` ### Notifier test pattern ```dart late ProviderContainer container; late MockProjectsRepository mockRepo; setUp(() { mockRepo = MockProjectsRepository(); container = ProviderContainer(overrides: [ projectsRepositoryProvider.overrideWithValue(mockRepo), ]); }); tearDown(container.dispose); ``` ## Coverage Goals | Layer | Target | |-------|--------| | Repository (CRUD methods) | 100% | | Notifiers | ≥ 80% | | Export service | ≥ 70% | ## Acceptance Criteria - [ ] All listed test files exist and pass - [ ] `flutter test` exits with code 0 - [ ] No test uses the real file database - [ ] Each repository test covers: insert, read, update, delete, stream emission - [ ] `TimerNotifier` test covers: start → running state, stop → idle + entry saved, discard → idle + entry deleted, build with open entry → running state restored - [ ] `flutter test --coverage` generates coverage report ## Running tests ```bash flutter test # all tests flutter test test/features/timer/ # single feature flutter test --coverage # with lcov coverage genhtml coverage/lcov.info -o coverage/html # HTML report ```