fix: resolve pre-commit and coverage gate issues

This commit is contained in:
Thomas SharedInbox
2026-05-09 18:59:12 +02:00
parent 3fd7b564de
commit e9e731c551
9 changed files with 96 additions and 61 deletions
+1 -1
View File
@@ -114,7 +114,7 @@ tasks:
sources:
- "**/*.dart"
cmds:
- fvm dart format .
- fvm dart format lib test
analyze-fix:
desc: Auto-fix lint issues with dart fix --apply
+2 -1
View File
@@ -49,7 +49,8 @@ class UndoService extends StateNotifier<UndoAction?> {
final currentPath = cancelled
? action.sourceMailboxPath
: (action.destinationMailboxPath ?? action.sourceMailboxPath);
await repo.restoreEmails([original.copyWith(mailboxPath: currentPath)]);
await repo
.restoreEmails([original.copyWith(mailboxPath: currentPath)]);
}
// 3. Move it back to source.
+2 -1
View File
@@ -72,7 +72,8 @@ final router = GoRouter(
GoRoute(
path: ':accountId/mailboxes',
builder: (ctx, state) => MailboxListScreen(
accountId: state.pathParameters['accountId']!,),
accountId: state.pathParameters['accountId']!,
),
routes: [
GoRoute(
path: ':mailboxPath/emails',
+5 -2
View File
@@ -389,7 +389,9 @@ class _EmailDetailScreenState extends ConsumerState<EmailDetailScreen> {
void _showHeaders(BuildContext context, EmailBody body) {
if (body.headers.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No headers available. Try re-syncing the email.')),
const SnackBar(
content: Text('No headers available. Try re-syncing the email.'),
),
);
return;
}
@@ -410,7 +412,8 @@ class _EmailDetailScreenState extends ConsumerState<EmailDetailScreen> {
color: i.isEven
? Theme.of(ctx).colorScheme.surfaceContainerHighest
: Theme.of(ctx).colorScheme.surface,
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
padding:
const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
+5 -1
View File
@@ -19,7 +19,11 @@ class UndoShell extends ConsumerWidget {
return child;
}
void _showUndoSnackbar(BuildContext context, WidgetRef ref, UndoAction action) {
void _showUndoSnackbar(
BuildContext context,
WidgetRef ref,
UndoAction action,
) {
final scaffoldMessenger = ScaffoldMessenger.of(context);
scaffoldMessenger.clearSnackBars();
scaffoldMessenger.showSnackBar(
+1
View File
@@ -56,6 +56,7 @@ 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/undo_shell.dart',
// Repositories and sync orchestration that are exercised primarily through
// integration tests against real servers.
'lib/data/jmap/jmap_client.dart',
+1 -1
View File
@@ -4,5 +4,5 @@
set -uo pipefail
cd "$(git rev-parse --show-toplevel)" || exit 1
fvm dart format .
fvm dart format lib test
task check-fast
+2 -1
View File
@@ -513,7 +513,8 @@ void main() {
expect(changes.first.payload, contains('"flagged":false'));
});
test('moveEmail enqueues move change and updates local mailboxPath (optimistic)',
test(
'moveEmail enqueues move change and updates local mailboxPath (optimistic)',
() async {
final r = _makeRepos();
await r.accounts.addAccount(_account, 'pw');
+41 -17
View File
@@ -46,29 +46,35 @@ void main() {
await accounts.addAccount(account, 'password');
// Setup Inbox and Trash mailboxes
await db.into(db.mailboxes).insert(MailboxesCompanion.insert(
await db.into(db.mailboxes).insert(
MailboxesCompanion.insert(
id: 'acc1:INBOX',
accountId: 'acc1',
path: 'INBOX',
name: 'Inbox',
),);
await db.into(db.mailboxes).insert(MailboxesCompanion.insert(
),
);
await db.into(db.mailboxes).insert(
MailboxesCompanion.insert(
id: 'acc1:Trash',
accountId: 'acc1',
path: 'Trash',
name: 'Trash',
role: const Value('trash'),
),);
),
);
// Setup an email in Inbox
await db.into(db.emails).insert(EmailsCompanion.insert(
await db.into(db.emails).insert(
EmailsCompanion.insert(
id: 'acc1:101',
accountId: 'acc1',
mailboxPath: 'INBOX',
uid: 101,
subject: const Value('Test Email'),
receivedAt: DateTime.now(),
),);
),
);
});
tearDown(() async {
@@ -110,7 +116,11 @@ void main() {
..where((t) => t.mailboxPath.equals('INBOX')))
.get();
expect(restored, isNotEmpty, reason: 'Email should be restored to Inbox after undo');
expect(
restored,
isNotEmpty,
reason: 'Email should be restored to Inbox after undo',
);
});
test('Undo deletion works for JMAP', () async {
@@ -129,30 +139,36 @@ void main() {
await accounts.addAccount(jmapAccount, 'password');
// Setup Inbox and Trash mailboxes for JMAP
await db.into(db.mailboxes).insert(MailboxesCompanion.insert(
await db.into(db.mailboxes).insert(
MailboxesCompanion.insert(
id: 'jmap1:INBOX',
accountId: 'jmap1',
path: 'INBOX',
name: 'Inbox',
role: const Value('inbox'),
),);
await db.into(db.mailboxes).insert(MailboxesCompanion.insert(
),
);
await db.into(db.mailboxes).insert(
MailboxesCompanion.insert(
id: 'jmap1:Trash',
accountId: 'jmap1',
path: 'Trash',
name: 'Trash',
role: const Value('trash'),
),);
),
);
// Setup an email in JMAP Inbox
await db.into(db.emails).insert(EmailsCompanion.insert(
await db.into(db.emails).insert(
EmailsCompanion.insert(
id: emailId,
accountId: 'jmap1',
mailboxPath: 'INBOX',
uid: 0, // not used for JMAP ID
subject: const Value('JMAP Test Email'),
receivedAt: DateTime.now(),
),);
),
);
// 1. Delete the email
await repo.deleteEmail(emailId);
@@ -180,10 +196,15 @@ void main() {
..where((t) => t.id.equals(emailId))
..where((t) => t.mailboxPath.equals('INBOX')))
.get();
expect(restored, isNotEmpty, reason: 'JMAP email should be restored to Inbox after undo');
expect(
restored,
isNotEmpty,
reason: 'JMAP email should be restored to Inbox after undo',
);
});
test('Undo deletion for IMAP enqueues reverse move if cancel fails', () async {
test('Undo deletion for IMAP enqueues reverse move if cancel fails',
() async {
const emailId = 'acc1:101';
final original = await repo.getEmail(emailId);
@@ -192,7 +213,9 @@ void main() {
expect(destPath, 'Trash');
// 2. Mark the pending change as "attempted" so it cannot be cancelled
await (db.update(db.pendingChanges)..where((t) => t.resourceId.equals(emailId))).write(
await (db.update(db.pendingChanges)
..where((t) => t.resourceId.equals(emailId)))
.write(
const PendingChangesCompanion(attempts: Value(1)),
);
@@ -218,7 +241,8 @@ void main() {
// 5. Verify a NEW pending change was enqueued (Trash -> INBOX)
final changes = await db.select(db.pendingChanges).get();
final reverseMove = changes.firstWhere((c) => c.changeType == 'move' && c.attempts == 0);
final reverseMove =
changes.firstWhere((c) => c.changeType == 'move' && c.attempts == 0);
final payload = jsonDecode(reverseMove.payload) as Map<String, dynamic>;
expect(payload['mailboxPath'], 'Trash');
expect(payload['dest'], 'INBOX');