135 lines
4.6 KiB
Dart
135 lines
4.6 KiB
Dart
import 'package:drift/drift.dart' show Value;
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:sharedinbox/core/models/account.dart';
|
|
import 'package:sharedinbox/core/repositories/mailbox_repository.dart';
|
|
import 'package:sharedinbox/data/db/database.dart' hide Account;
|
|
import 'package:sharedinbox/data/repositories/account_repository_impl.dart';
|
|
import 'package:sharedinbox/data/repositories/mailbox_repository_impl.dart';
|
|
|
|
import 'account_repository_impl_test.dart' show MapSecureStorage;
|
|
import 'db_test_helper.dart';
|
|
|
|
// ── Contract ──────────────────────────────────────────────────────────────────
|
|
|
|
/// Verifies the [MailboxRepository] interface contract.
|
|
///
|
|
/// Tests cover only the locally-observable part of the interface
|
|
/// (observe / find) since sync methods require live IMAP/JMAP servers.
|
|
abstract class MailboxRepositoryContract {
|
|
static const _account = Account(
|
|
id: 'm-acc',
|
|
displayName: 'Contract',
|
|
email: 'm@example.com',
|
|
imapHost: 'imap.example.com',
|
|
smtpHost: 'smtp.example.com',
|
|
);
|
|
|
|
/// Return a fresh [MailboxRepository] with [_account] already persisted.
|
|
Future<MailboxRepository> makeRepo();
|
|
|
|
/// Insert a mailbox row into the backing store so tests can verify
|
|
/// observeMailboxes without triggering a network sync.
|
|
Future<void> insertMailbox(
|
|
MailboxRepository repo, {
|
|
required String id,
|
|
required String path,
|
|
String? role,
|
|
int unread = 0,
|
|
int total = 0,
|
|
});
|
|
|
|
void run() {
|
|
test('observeMailboxes starts empty', () async {
|
|
final repo = await makeRepo();
|
|
expect(await repo.observeMailboxes(_account.id).first, isEmpty);
|
|
});
|
|
|
|
test('observeMailboxes emits inserted rows ordered by path', () async {
|
|
final repo = await makeRepo();
|
|
await insertMailbox(repo, id: 'z', path: 'Z');
|
|
await insertMailbox(repo, id: 'a', path: 'A');
|
|
final boxes = await repo.observeMailboxes(_account.id).first;
|
|
expect(boxes.map((b) => b.path), ['A', 'Z']);
|
|
});
|
|
|
|
test('observeMailboxes only returns rows for the given account', () async {
|
|
final repo = await makeRepo();
|
|
await insertMailbox(repo, id: 'mb1', path: 'INBOX');
|
|
expect(await repo.observeMailboxes('other-acc').first, isEmpty);
|
|
});
|
|
|
|
test('findMailboxByRole returns null when no match', () async {
|
|
final repo = await makeRepo();
|
|
expect(await repo.findMailboxByRole(_account.id, 'archive'), isNull);
|
|
});
|
|
|
|
test('findMailboxByRole returns the matching mailbox', () async {
|
|
final repo = await makeRepo();
|
|
await insertMailbox(repo, id: 'arch', path: 'Archive', role: 'archive');
|
|
final box = await repo.findMailboxByRole(_account.id, 'archive');
|
|
expect(box, isNotNull);
|
|
expect(box!.role, 'archive');
|
|
});
|
|
|
|
test('clearForResync removes all mailboxes for the account', () async {
|
|
final repo = await makeRepo();
|
|
await insertMailbox(repo, id: 'mb', path: 'INBOX');
|
|
await repo.clearForResync(_account.id);
|
|
expect(await repo.observeMailboxes(_account.id).first, isEmpty);
|
|
});
|
|
}
|
|
}
|
|
|
|
// ── Impl under test ───────────────────────────────────────────────────────────
|
|
|
|
class _MailboxRepositoryImplContract extends MailboxRepositoryContract {
|
|
static const _account = MailboxRepositoryContract._account;
|
|
|
|
late AppDatabase _db;
|
|
late AccountRepositoryImpl _accountRepo;
|
|
|
|
@override
|
|
Future<MailboxRepository> makeRepo() async {
|
|
_db = openTestDatabase();
|
|
_accountRepo = AccountRepositoryImpl(_db, MapSecureStorage());
|
|
await _accountRepo.addAccount(_account, 'pw');
|
|
return MailboxRepositoryImpl(
|
|
_db,
|
|
_accountRepo,
|
|
imapConnect: (_, __, ___) =>
|
|
Future.error(UnsupportedError('no IMAP in unit tests')),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<void> insertMailbox(
|
|
MailboxRepository repo, {
|
|
required String id,
|
|
required String path,
|
|
String? role,
|
|
int unread = 0,
|
|
int total = 0,
|
|
}) async {
|
|
await _db.into(_db.mailboxes).insert(
|
|
MailboxesCompanion.insert(
|
|
id: id,
|
|
accountId: _account.id,
|
|
path: path,
|
|
name: path.split('/').last,
|
|
unreadCount: Value(unread),
|
|
totalCount: Value(total),
|
|
role: Value(role),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
setUpAll(configureSqliteForTests);
|
|
|
|
group('MailboxRepositoryImpl satisfies MailboxRepository contract', () {
|
|
_MailboxRepositoryImplContract().run();
|
|
});
|
|
}
|