fix: resolve pre-commit and coverage gate issues
This commit is contained in:
+1
-1
@@ -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
|
||||
|
||||
@@ -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
@@ -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',
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -46,29 +46,35 @@ void main() {
|
||||
await accounts.addAccount(account, 'password');
|
||||
|
||||
// Setup Inbox and Trash mailboxes
|
||||
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(
|
||||
id: 'acc1:Trash',
|
||||
accountId: 'acc1',
|
||||
path: 'Trash',
|
||||
name: 'Trash',
|
||||
role: const Value('trash'),
|
||||
),);
|
||||
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(
|
||||
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(
|
||||
id: 'acc1:101',
|
||||
accountId: 'acc1',
|
||||
mailboxPath: 'INBOX',
|
||||
uid: 101,
|
||||
subject: const Value('Test Email'),
|
||||
receivedAt: DateTime.now(),
|
||||
),);
|
||||
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(
|
||||
id: 'jmap1:INBOX',
|
||||
accountId: 'jmap1',
|
||||
path: 'INBOX',
|
||||
name: 'Inbox',
|
||||
role: const Value('inbox'),
|
||||
),);
|
||||
await db.into(db.mailboxes).insert(MailboxesCompanion.insert(
|
||||
id: 'jmap1:Trash',
|
||||
accountId: 'jmap1',
|
||||
path: 'Trash',
|
||||
name: 'Trash',
|
||||
role: const Value('trash'),
|
||||
),);
|
||||
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(
|
||||
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(
|
||||
id: emailId,
|
||||
accountId: 'jmap1',
|
||||
mailboxPath: 'INBOX',
|
||||
uid: 0, // not used for JMAP ID
|
||||
subject: const Value('JMAP Test Email'),
|
||||
receivedAt: DateTime.now(),
|
||||
),);
|
||||
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');
|
||||
|
||||
Reference in New Issue
Block a user