the-mews/app/test/controllers_test.dart

164 lines
5.7 KiB
Dart
Raw Normal View History

import 'package:drift/drift.dart' show Value;
import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mews/application/controllers/bookmarks_controller.dart';
import 'package:mews/application/controllers/reader_settings_controller.dart';
import 'package:mews/application/controllers/subscriptions_controller.dart';
import 'package:mews/database/database.dart';
import 'package:mews/mews/document.dart';
void main() {
late MewsDatabase db;
setUp(() {
db = MewsDatabase.test(NativeDatabase.memory());
});
tearDown(() async {
await db.close();
});
test('settings round-trip through the database', () async {
final settings = ReaderSettingsController(db);
await settings.setFont('Atkinson Hyperlegible');
await settings.increaseSize();
await settings.setThemeMode('dark');
await settings.setVariant('warm');
final reloaded = ReaderSettingsController(db);
await reloaded.load();
expect(reloaded.font.value, 'Atkinson Hyperlegible');
expect(reloaded.fontScale.value, 1.125);
expect(reloaded.themeMode.value, 'dark');
expect(reloaded.variant.value, 'warm');
});
test('text size stays within its limits', () async {
final settings = ReaderSettingsController(db);
for (var i = 0; i < 30; i++) {
await settings.increaseSize();
}
expect(settings.fontScale.value, ReaderSettingsController.maxScale);
for (var i = 0; i < 40; i++) {
await settings.decreaseSize();
}
expect(settings.fontScale.value, ReaderSettingsController.minScale);
});
test('bookmarks toggle and persist', () async {
final bookmarks = BookmarksController(db);
await bookmarks.load();
await bookmarks.toggle('https://example.com/', 'Example');
expect(bookmarks.isBookmarked('https://example.com/'), isTrue);
final reloaded = BookmarksController(db);
await reloaded.load();
expect(reloaded.isBookmarked('https://example.com/'), isTrue);
await reloaded.toggle('https://example.com/', 'Example');
expect(reloaded.isBookmarked('https://example.com/'), isFalse);
});
test('subscribing takes on the back catalogue without flagging it', () async {
final subscriptions = SubscriptionsController(db);
await subscriptions.load();
final firstPost = MewsEntry(
url: 'https://example.com/a.html',
date: DateTime(2026, 9, 21),
title: 'First post');
await subscriptions.toggle(_page('https://example.com/', [firstPost]));
expect(subscriptions.isSubscribed('https://example.com/'), isTrue);
// The post was stored, but read, so nothing is waiting for the reader.
expect(await db.unreadCount(), 0);
// Opening the page again finds nothing new.
expect(await subscriptions.refreshSite(_page('https://example.com/', [firstPost])),
isEmpty);
// A later post is new, and stays unread until the reader opens it.
final newPost = MewsEntry(
url: 'https://example.com/b.html',
date: DateTime(2026, 10, 8),
title: 'Second post');
final fresh = await subscriptions
.refreshSite(_page('https://example.com/', [newPost, firstPost]));
expect(fresh.map((e) => e.url), ['https://example.com/b.html']);
expect(await db.unreadCount(siteUrl: 'https://example.com/'), 1);
// Finding it a second time does not report it again.
expect(
await subscriptions
.refreshSite(_page('https://example.com/', [newPost, firstPost])),
isEmpty);
expect(await db.unreadCount(), 1);
});
test('unread posts survive a restart', () async {
final subscriptions = SubscriptionsController(db);
await subscriptions.load();
await subscriptions.toggle(_page('https://example.com/', const []));
await subscriptions.refreshSite(_page('https://example.com/', [
MewsEntry(
url: 'https://example.com/a.html',
date: DateTime(2026, 9, 21),
title: 'First post'),
]));
// A fresh controller over the same database sees the same unread post,
// which the old in-memory count could not do.
final restarted = SubscriptionsController(db);
await restarted.load();
expect(restarted.isSubscribed('https://example.com/'), isTrue);
expect(await db.unreadCount(), 1);
});
test('leaving a site takes its posts with it', () async {
final subscriptions = SubscriptionsController(db);
await subscriptions.load();
await subscriptions.toggle(_page('https://example.com/', const []));
await subscriptions.refreshSite(_page('https://example.com/', [
MewsEntry(
url: 'https://example.com/a.html',
date: DateTime(2026, 9, 21),
title: 'First post'),
]));
expect(await db.unreadCount(), 1);
await subscriptions.remove('https://example.com/');
expect(subscriptions.isSubscribed('https://example.com/'), isFalse);
expect(await db.unreadCount(), 0);
});
test('caches pages for offline reopening', () async {
await db.saveCachedPage(CachedPagesCompanion.insert(
url: 'https://example.com/page.html',
source: 'html',
title: const Value('Page'),
etag: const Value('"v1"'),
));
final cached = await db.cachedPage('https://example.com/page.html');
expect(cached!.source, 'html');
expect(cached.etag, '"v1"');
expect(cached.title, 'Page');
});
test('records history and returns the last visited page', () async {
await db.recordVisit('https://a.example/', 'A');
await db.recordVisit('https://b.example/', 'B');
expect(await db.lastVisitedUrl(), 'https://b.example/');
});
}
MewsPage _page(String url, List<MewsEntry> entries) => MewsPage(
url: url,
body: const [],
lang: 'en',
direction: TextDirection.ltr,
variant: MewsVariant.plain,
entries: entries,
specVersion: '0.1',
);