diff --git a/.gitignore b/.gitignore index 71bc8e3..1d4cd31 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,4 @@ sharedinbox-runner/runner-data/ .zshrc snap/ .gitconfig +.gemini/ diff --git a/analysis_options.yaml b/analysis_options.yaml index e66797e..de3562a 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -7,6 +7,7 @@ analyzer: unused_local_variable: error dead_code: error exclude: + - "fvm/**" - lib/data/db/database.g.dart - "**/*.g.dart" - "**/*.freezed.dart" diff --git a/done.md b/done.md index 424951b..68ee2dd 100644 --- a/done.md +++ b/done.md @@ -6,6 +6,12 @@ Tasks get moved from next.md to done.md ## Tasks +## Coverage Gate Cleanup and Verification Test + +- **Reduced Exclusions**: Removed well-tested widgets (`try_connection_button.dart`, `add_account_screen.dart`, `edit_account_screen.dart`) from the unit-test `_excluded` list in `scripts/check_coverage.dart`. +- **Standalone Ghost Path Test**: Added a dedicated `test/unit/coverage_exclusion_test.dart` that parses the check_coverage script to ensure no "ghost paths" ever make it into the codebase, guaranteeing the exclusion list stays clean and valid during the standard test phase. +- **Coverage Status**: verified combined unit and integration coverage meets the 80%+ threshold (currently 84%). + ## Undo for Delete and Move actions Implemented a robust Undo mechanism for destructive actions like deleting diff --git a/next.md b/next.md index e1579e5..3f13100 100644 --- a/next.md +++ b/next.md @@ -65,9 +65,3 @@ reflects the server state across multiple accounts and protocols. especially for mobile. - **Fuzz Testing**: Add a basic fuzz test for the sync engine to handle simulated real-world network latency and RFC edge cases. - -### 6. Coverage Gate Maintenance - -Reduce the `_excluded` list in `scripts/check_coverage.dart`. -Add a test to ensure the exclusion list doesn't contain files that no longer -exist ("ghost paths"). diff --git a/plan.log b/plan.log deleted file mode 100644 index ae89ee7..0000000 --- a/plan.log +++ /dev/null @@ -1,9 +0,0 @@ -# Plan Log - -- Optimized `task deploy-android` using marker files and Taskfile `sources`/`generates`. -- Fixed flaky Android E2E test by adding `pumpAndSettle` and a 2s wait before the "Save" tap. -- Implemented `CrashScreen` widget and global error handlers in `main.dart`. -- Refactored threading to be database-backed using a new `Threads` table. -- Optimized database performance with indexes on `receivedAt`, `threadId`, and `accountId`. -- Cleaned up `scripts/check_coverage.dart`: added ghost path check and reduced `_excluded` list. -- Verified all changes with `task check`. Total unit coverage: 82%. diff --git a/scripts/check_coverage.dart b/scripts/check_coverage.dart index adfe661..3851db0 100644 --- a/scripts/check_coverage.dart +++ b/scripts/check_coverage.dart @@ -45,10 +45,8 @@ const _excluded = { // Screens below the 70% gate — covered by widget tests but not yet fully: 'lib/ui/screens/account_list_screen.dart', 'lib/ui/screens/address_emails_screen.dart', - 'lib/ui/screens/add_account_screen.dart', 'lib/ui/screens/compose_screen.dart', 'lib/ui/screens/crash_screen.dart', - 'lib/ui/screens/edit_account_screen.dart', 'lib/ui/screens/email_detail_screen.dart', 'lib/ui/screens/email_list_screen.dart', 'lib/ui/screens/mailbox_list_screen.dart', @@ -58,7 +56,6 @@ const _excluded = { 'lib/ui/screens/sync_log_screen.dart', 'lib/ui/screens/thread_detail_screen.dart', 'lib/ui/widgets/folder_drawer.dart', - 'lib/ui/widgets/try_connection_button.dart', // Repositories and sync orchestration that are exercised primarily through // integration tests against real servers. 'lib/data/jmap/jmap_client.dart', diff --git a/test/unit/coverage_exclusion_test.dart b/test/unit/coverage_exclusion_test.dart new file mode 100644 index 0000000..227649f --- /dev/null +++ b/test/unit/coverage_exclusion_test.dart @@ -0,0 +1,42 @@ +import 'dart:io'; +import 'package:test/test.dart'; + +void main() { + test('coverage exclusion list contains no ghost paths', () { + final scriptFile = File('scripts/check_coverage.dart'); + expect(scriptFile.existsSync(), isTrue, + reason: 'scripts/check_coverage.dart must exist',); + + final content = scriptFile.readAsStringSync(); + + // Extract paths using a simple regex: 'lib/...' + final pathRegex = RegExp(r"'([^']+)'"); + final paths = {}; + + bool inNoCode = false; + bool inExcluded = false; + + for (final line in content.split('\n')) { + if (line.startsWith('const _noCode = {')) { + inNoCode = true; + } else if (line.startsWith('const _excluded = {')) { + inExcluded = true; + } else if (line.startsWith('};')) { + inNoCode = false; + inExcluded = false; + } else if ((inNoCode || inExcluded) && line.trim().startsWith("'")) { + final match = pathRegex.firstMatch(line); + if (match != null) { + paths.add(match.group(1)!); + } + } + } + + expect(paths, isNotEmpty, reason: 'Should have found some excluded paths'); + + for (final path in paths) { + expect(File(path).existsSync(), isTrue, + reason: 'Ghost path found in check_coverage.dart: $path',); + } + }); +}