Rename all OPDS-prefixed models to generic names (Server, Feed, Entry, Link, StreamLink), expand the ServerSoftware interface to cover all server interactions, and implement a full Kavita REST API client that replaces the OPDS delegation. - Rename OPDS* models to generic names across ~60 files - Add database migrations 13 (opds_id → entry_id) and 14 (unify credentials) - Create OPDSServerSoftware wrapping existing OPDS services - Create KavitaApiClient for direct Kavita REST API calls - Create KavitaFeedMapper to convert Kavita JSON to Feed/Entry models - Rewrite KavitaServerSoftware to use native API (no OPDS delegation) - Unify server credentials (remove softwareUsername/softwarePassword) - Simplify add/edit server UI to single auth section - Add test connection button to server add/edit screens - Add progress indicator to PublicationCard using local and server data - Eliminate softwareType branching in reader screens - Add EntryProgress and fetchEntryProgress to ServerSoftware interface - Fix Entry.acquisitionLink crash on empty links - Add 59 new tests covering models, services, and providers
92 lines
2.6 KiB
Dart
92 lines
2.6 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:worldhopper/models/enhanced_metadata.dart';
|
|
import 'package:worldhopper/models/entry.dart';
|
|
import 'package:worldhopper/models/publication.dart';
|
|
|
|
void main() {
|
|
group('Publication', () {
|
|
test('fromEntry uses entry.id as entryId', () {
|
|
const entry = Entry(
|
|
id: 'opds-entry-123',
|
|
title: 'Test Book',
|
|
authors: ['Author'],
|
|
);
|
|
final pub = Publication.fromEntry(
|
|
id: 'pub-1',
|
|
serverId: 's1',
|
|
entry: entry,
|
|
metadata: const EnhancedMetadata.empty(),
|
|
);
|
|
expect(pub.entryId, 'opds-entry-123');
|
|
expect(pub.title, 'Test Book');
|
|
expect(pub.authors, ['Author']);
|
|
});
|
|
|
|
test('toEntry converts back with entryId as id', () {
|
|
final now = DateTime(2024);
|
|
final pub = Publication(
|
|
id: 'pub-1',
|
|
serverId: 's1',
|
|
entryId: 'entry-456',
|
|
title: 'My Book',
|
|
authors: const ['Writer'],
|
|
firstCachedAt: now,
|
|
lastCachedAt: now,
|
|
lastAccessedAt: now,
|
|
);
|
|
final entry = pub.toEntry();
|
|
expect(entry.id, 'entry-456');
|
|
expect(entry.title, 'My Book');
|
|
expect(entry.authors, ['Writer']);
|
|
});
|
|
|
|
test('toDatabase uses entry_id column name', () {
|
|
final now = DateTime(2024);
|
|
final pub = Publication(
|
|
id: 'pub-1',
|
|
serverId: 's1',
|
|
entryId: 'my-entry-id',
|
|
title: 'Book',
|
|
firstCachedAt: now,
|
|
lastCachedAt: now,
|
|
lastAccessedAt: now,
|
|
);
|
|
final row = pub.toDatabase();
|
|
expect(row['entry_id'], 'my-entry-id');
|
|
expect(row.containsKey('opds_id'), isFalse);
|
|
});
|
|
|
|
test('fromDatabase reads entry_id column', () {
|
|
final now = DateTime(2024).millisecondsSinceEpoch;
|
|
final row = {
|
|
'id': 'pub-1',
|
|
'server_id': 's1',
|
|
'entry_id': 'restored-entry-id',
|
|
'title': 'Book',
|
|
'authors': '["Author"]',
|
|
'summary': null,
|
|
'content': null,
|
|
'cover_path': null,
|
|
'thumbnail_path': null,
|
|
'cover_url': null,
|
|
'thumbnail_url': null,
|
|
'series': null,
|
|
'series_position': null,
|
|
'publisher': null,
|
|
'language': null,
|
|
'isbn': null,
|
|
'categories': '[]',
|
|
'links': '[]',
|
|
'stream_link': null,
|
|
'published': null,
|
|
'updated': null,
|
|
'first_cached_at': now,
|
|
'last_cached_at': now,
|
|
'last_accessed_at': now,
|
|
};
|
|
final pub = Publication.fromDatabase(row);
|
|
expect(pub.entryId, 'restored-entry-id');
|
|
expect(pub.title, 'Book');
|
|
});
|
|
});
|
|
}
|