feat: implement cross-platform features and UI integration
- iOS: Add BackgroundSyncService, SyncScheduler, SyncWorker, BookmarkViewModel, FeedViewModel - iOS: Add BackgroundSyncService, SyncScheduler, SyncWorker services - Linux: Add settings-store.vala, State.vala signals, view widgets (FeedList, FeedDetail, AddFeed, Search, Settings, Bookmark) - Linux: Add bookmark-store.vala, bookmark vala model, search-service.vala - Android: Add NotificationService, NotificationManager, NotificationPreferencesStore - Android: Add BookmarkDao, BookmarkRepository, SettingsStore - Add unit tests for iOS, Android, Linux - Add integration tests - Add performance benchmarks - Update tasks and documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -338,7 +338,7 @@ public class RSSuper.DatabaseTests {
|
||||
item_store.add(item1);
|
||||
item_store.add(item2);
|
||||
|
||||
// Test FTS search
|
||||
// Test FTS search (returns SearchResult)
|
||||
var results = item_store.search("swift");
|
||||
if (results.length != 1) {
|
||||
printerr("FAIL: Expected 1 result for 'swift', got %d\n", results.length);
|
||||
@@ -359,6 +359,13 @@ public class RSSuper.DatabaseTests {
|
||||
return;
|
||||
}
|
||||
|
||||
// Test fuzzy search
|
||||
results = item_store.search_fuzzy("swif");
|
||||
if (results.length != 1) {
|
||||
printerr("FAIL: Expected 1 result for fuzzy 'swif', got %d\n", results.length);
|
||||
return;
|
||||
}
|
||||
|
||||
print("PASS: test_fts_search\n");
|
||||
} finally {
|
||||
cleanup();
|
||||
@@ -394,6 +401,208 @@ public class RSSuper.DatabaseTests {
|
||||
}
|
||||
}
|
||||
|
||||
public void run_search_service() {
|
||||
try {
|
||||
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
|
||||
db = new Database(test_db_path);
|
||||
} catch (DBError e) {
|
||||
warning("Failed to create test database: %s", e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create subscription
|
||||
var sub_store = new SubscriptionStore(db);
|
||||
var subscription = new FeedSubscription.with_values(
|
||||
"sub_1", "https://example.com/feed.xml", "Example Feed"
|
||||
);
|
||||
sub_store.add(subscription);
|
||||
|
||||
// Add test items
|
||||
var item_store = new FeedItemStore(db);
|
||||
var item1 = new FeedItem.with_values(
|
||||
"item_1",
|
||||
"Introduction to Rust Programming",
|
||||
"https://example.com/rust",
|
||||
"Learn Rust programming language",
|
||||
"Complete Rust tutorial for beginners",
|
||||
"Rust Team",
|
||||
"2024-01-01T12:00:00Z",
|
||||
null,
|
||||
null,
|
||||
null, null, null, null,
|
||||
"sub_1"
|
||||
);
|
||||
|
||||
var item2 = new FeedItem.with_values(
|
||||
"item_2",
|
||||
"Advanced Rust Patterns",
|
||||
"https://example.com/rust-advanced",
|
||||
"Advanced Rust programming patterns",
|
||||
"Deep dive into Rust patterns and best practices",
|
||||
"Rust Team",
|
||||
"2024-01-02T12:00:00Z",
|
||||
null,
|
||||
null,
|
||||
null, null, null, null,
|
||||
"sub_1"
|
||||
);
|
||||
|
||||
item_store.add(item1);
|
||||
item_store.add(item2);
|
||||
|
||||
// Test search service
|
||||
var search_service = new SearchService(db);
|
||||
|
||||
// Perform search
|
||||
var results = search_service.search("rust");
|
||||
if (results.length != 2) {
|
||||
printerr("FAIL: Expected 2 results for 'rust', got %d\n", results.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check history
|
||||
var history = search_service.get_history();
|
||||
if (history.length != 1) {
|
||||
printerr("FAIL: Expected 1 history entry, got %d\n", history.length);
|
||||
return;
|
||||
}
|
||||
if (history[0].query != "rust") {
|
||||
printerr("FAIL: Expected query 'rust', got '%s'\n", history[0].query);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test fuzzy search
|
||||
results = search_service.search("rus");
|
||||
if (results.length != 2) {
|
||||
printerr("FAIL: Expected 2 results for fuzzy 'rus', got %d\n", results.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test suggestions
|
||||
var suggestions = search_service.get_suggestions("rust");
|
||||
if (suggestions.length == 0) {
|
||||
printerr("FAIL: Expected at least 1 suggestion for 'rust'\n");
|
||||
return;
|
||||
}
|
||||
|
||||
print("PASS: test_search_service\n");
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
public void run_bookmark_store() {
|
||||
try {
|
||||
test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
|
||||
db = new Database(test_db_path);
|
||||
} catch (DBError e) {
|
||||
warning("Failed to create test database: %s", e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create subscription
|
||||
var sub_store = new SubscriptionStore(db);
|
||||
var subscription = new FeedSubscription.with_values(
|
||||
"sub_1", "https://example.com/feed.xml", "Example Feed"
|
||||
);
|
||||
sub_store.add(subscription);
|
||||
|
||||
// Add test item
|
||||
var item_store = new FeedItemStore(db);
|
||||
var item = new FeedItem.with_values(
|
||||
"item_1",
|
||||
"Test Article",
|
||||
"https://example.com/test",
|
||||
"Test description",
|
||||
"Test content",
|
||||
"Test Author",
|
||||
"2024-01-01T12:00:00Z",
|
||||
null,
|
||||
null,
|
||||
null, null, null, null,
|
||||
"sub_1"
|
||||
);
|
||||
item_store.add(item);
|
||||
|
||||
// Test bookmark store
|
||||
var bookmark_store = new BookmarkStore(db);
|
||||
|
||||
// Create bookmark
|
||||
var bookmark = new Bookmark.with_values(
|
||||
"bookmark_1",
|
||||
"item_1",
|
||||
"Test Article",
|
||||
"https://example.com/test",
|
||||
"Test description",
|
||||
"Test content",
|
||||
"2024-01-01T12:00:00Z",
|
||||
"test,important"
|
||||
);
|
||||
|
||||
// Add bookmark
|
||||
bookmark_store.add(bookmark);
|
||||
|
||||
// Get bookmark by ID
|
||||
var retrieved = bookmark_store.get_by_id("bookmark_1");
|
||||
if (retrieved == null) {
|
||||
printerr("FAIL: Expected bookmark to exist after add\n");
|
||||
return;
|
||||
}
|
||||
if (retrieved.title != "Test Article") {
|
||||
printerr("FAIL: Expected title 'Test Article', got '%s'\n", retrieved.title);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all bookmarks
|
||||
var all = bookmark_store.get_all();
|
||||
if (all.length != 1) {
|
||||
printerr("FAIL: Expected 1 bookmark, got %d\n", all.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get bookmark count
|
||||
var count = bookmark_store.count();
|
||||
if (count != 1) {
|
||||
printerr("FAIL: Expected count 1, got %d\n", count);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get bookmarks by tag
|
||||
var tagged = bookmark_store.get_by_tag("test");
|
||||
if (tagged.length != 1) {
|
||||
printerr("FAIL: Expected 1 bookmark by tag 'test', got %d\n", tagged.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update bookmark
|
||||
retrieved.tags = "updated,important";
|
||||
bookmark_store.update(retrieved);
|
||||
|
||||
// Delete bookmark
|
||||
bookmark_store.delete("bookmark_1");
|
||||
|
||||
// Verify deletion
|
||||
var deleted = bookmark_store.get_by_id("bookmark_1");
|
||||
if (deleted != null) {
|
||||
printerr("FAIL: Expected bookmark to be deleted\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check count after deletion
|
||||
count = bookmark_store.count();
|
||||
if (count != 0) {
|
||||
printerr("FAIL: Expected count 0 after delete, got %d\n", count);
|
||||
return;
|
||||
}
|
||||
|
||||
print("PASS: test_bookmark_store\n");
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
public static int main(string[] args) {
|
||||
print("Running database tests...\n");
|
||||
|
||||
@@ -417,6 +626,12 @@ public class RSSuper.DatabaseTests {
|
||||
print("\n=== Running FTS search tests ===");
|
||||
tests.run_fts_search();
|
||||
|
||||
print("\n=== Running search service tests ===");
|
||||
tests.run_search_service();
|
||||
|
||||
print("\n=== Running bookmark store tests ===");
|
||||
tests.run_bookmark_store();
|
||||
|
||||
print("\nAll tests completed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user