feat: search, filter and act on items from the library pages

This commit is contained in:
randogoth 2026-10-11 13:25:57 +03:00
parent 1b426ccd8b
commit 5cd053c8a9
11 changed files with 401 additions and 43 deletions

View file

@ -93,6 +93,45 @@ void main() {
expect(await db.countHistory(), 2);
});
test('a search matches titles and addresses literally', () async {
await db.addBookmark('https://a.example/retro.html', 'Collecting retro phones');
await db.addBookmark('https://b.example/signal.html', 'Signal bars');
await db.addBookmark('https://c.example/100.html', '100% signal');
expect((await db.bookmarksByDate(query: 'retro')).map((b) => b.title),
['Collecting retro phones']);
// The address is searched too.
expect((await db.bookmarksByDate(query: 'b.example')).map((b) => b.title),
['Signal bars']);
// A blank search is not a filter.
expect(await db.bookmarksByDate(query: ' '), hasLength(3));
// The reader types text, not a pattern: LIKE's wildcards match literally.
expect(await db.bookmarksByDate(query: '%'), hasLength(1));
expect((await db.bookmarksByDate(query: '100%')).map((b) => b.title),
['100% signal']);
expect(await db.bookmarksByDate(query: '_'), isEmpty);
});
test('history lists one row per address, newest visit first', () async {
await db.recordVisit('https://a.example/one.html', 'First title');
await db.recordVisit('https://b.example/two.html', 'Page two');
await db.recordVisit('https://a.example/one.html', 'Newer title');
final pages = await db.recentPages();
expect(pages.map((p) => p.url),
['https://a.example/one.html', 'https://b.example/two.html']);
// The row carries the title of the latest visit.
expect(pages.first.title, 'Newer title');
await db.forgetPage('https://a.example/one.html');
expect((await db.recentPages()).map((p) => p.url),
['https://b.example/two.html']);
await db.clearHistory();
expect(await db.recentPages(), isEmpty);
});
test('an older database is recreated rather than migrated', () async {
final dir = Directory.systemTemp.createTempSync('mews-schema');
addTearDown(() => dir.deleteSync(recursive: true));