duplicate
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
import XCTest
|
||||
@testable import RSSuper
|
||||
|
||||
/// Unit tests for SearchHistoryStore
|
||||
final class SearchHistoryStoreTests: XCTestCase {
|
||||
|
||||
private var historyStore: SearchHistoryStore!
|
||||
private var databaseManager: DatabaseManager!
|
||||
|
||||
override func setUp() async throws {
|
||||
// Create in-memory database for testing
|
||||
databaseManager = try await DatabaseManager.inMemory()
|
||||
historyStore = SearchHistoryStore(databaseManager: databaseManager, maxHistoryCount: 10)
|
||||
try await historyStore.initialize()
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
historyStore = nil
|
||||
databaseManager = nil
|
||||
}
|
||||
|
||||
func testRecordSearch() async throws {
|
||||
try await historyStore.recordSearch("test query")
|
||||
|
||||
let exists = try await historyStore.queryExists("test query")
|
||||
XCTAssertTrue(exists)
|
||||
}
|
||||
|
||||
func testRecordSearchUpdatesExisting() async throws {
|
||||
try await historyStore.recordSearch("test query")
|
||||
let firstCount = try await historyStore.getTotalCount()
|
||||
|
||||
try await historyStore.recordSearch("test query")
|
||||
let secondCount = try await historyStore.getTotalCount()
|
||||
|
||||
XCTAssertEqual(firstCount, secondCount) // Should be same, updated not inserted
|
||||
}
|
||||
|
||||
func testGetRecentQueries() async throws {
|
||||
try await historyStore.recordSearch("query 1")
|
||||
try await historyStore.recordSearch("query 2")
|
||||
try await historyStore.recordSearch("query 3")
|
||||
|
||||
let queries = try await historyStore.getRecentQueries(limit: 2)
|
||||
|
||||
XCTAssertEqual(queries.count, 2)
|
||||
XCTAssertEqual(queries[0], "query 3") // Most recent first
|
||||
XCTAssertEqual(queries[1], "query 2")
|
||||
}
|
||||
|
||||
func testGetHistoryWithMetadata() async throws {
|
||||
try await historyStore.recordSearch("test query", resultCount: 42)
|
||||
|
||||
let entries = try await historyStore.getHistoryWithMetadata(limit: 10)
|
||||
|
||||
XCTAssertEqual(entries.count, 1)
|
||||
XCTAssertEqual(entries[0].query, "test query")
|
||||
XCTAssertEqual(entries[0].resultCount, 42)
|
||||
}
|
||||
|
||||
func testRemoveQuery() async throws {
|
||||
try await historyStore.recordSearch("to remove")
|
||||
XCTAssertTrue(try await historyStore.queryExists("to remove"))
|
||||
|
||||
try await historyStore.removeQuery("to remove")
|
||||
XCTAssertFalse(try await historyStore.queryExists("to remove"))
|
||||
}
|
||||
|
||||
func testClearHistory() async throws {
|
||||
try await historyStore.recordSearch("query 1")
|
||||
try await historyStore.recordSearch("query 2")
|
||||
|
||||
XCTAssertEqual(try await historyStore.getTotalCount(), 2)
|
||||
|
||||
try await historyStore.clearHistory()
|
||||
XCTAssertEqual(try await historyStore.getTotalCount(), 0)
|
||||
}
|
||||
|
||||
func testTrimHistory() async throws {
|
||||
// Insert more than maxHistoryCount
|
||||
for i in 1...15 {
|
||||
try await historyStore.recordSearch("query \(i)")
|
||||
}
|
||||
|
||||
let count = try await historyStore.getTotalCount()
|
||||
XCTAssertEqual(count, 10) // Should be trimmed to maxHistoryCount
|
||||
}
|
||||
|
||||
func testGetPopularQueries() async throws {
|
||||
// Record queries with different frequencies
|
||||
try await historyStore.recordSearch("popular")
|
||||
try await historyStore.recordSearch("popular")
|
||||
try await historyStore.recordSearch("popular")
|
||||
try await historyStore.recordSearch("less popular")
|
||||
try await historyStore.recordSearch("less popular")
|
||||
try await historyStore.recordSearch("once")
|
||||
|
||||
let popular = try await historyStore.getPopularQueries(limit: 10)
|
||||
|
||||
XCTAssertEqual(popular.count, 3)
|
||||
XCTAssertEqual(popular[0].query, "popular")
|
||||
XCTAssertEqual(popular[0].count, 3)
|
||||
}
|
||||
|
||||
func testGetTodaysQueries() async throws {
|
||||
try await historyStore.recordSearch("today query 1")
|
||||
try await historyStore.recordSearch("today query 2")
|
||||
|
||||
let todays = try await historyStore.getTodaysQueries()
|
||||
|
||||
XCTAssertTrue(todays.contains("today query 1"))
|
||||
XCTAssertTrue(todays.contains("today query 2"))
|
||||
}
|
||||
|
||||
func testEmptyQueryIgnored() async throws {
|
||||
try await historyStore.recordSearch("")
|
||||
try await historyStore.recordSearch(" ")
|
||||
|
||||
let count = try await historyStore.getTotalCount()
|
||||
XCTAssertEqual(count, 0)
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import XCTest
|
||||
@testable import RSSuper
|
||||
|
||||
/// Unit tests for SearchQuery parsing and manipulation
|
||||
final class SearchQueryTests: XCTestCase {
|
||||
|
||||
func testEmptyQuery() {
|
||||
let query = SearchQuery(rawValue: "")
|
||||
|
||||
XCTAssertEqual(query.terms, [])
|
||||
XCTAssertEqual(query.rawText, "")
|
||||
XCTAssertEqual(query.sort, .relevance)
|
||||
XCTAssertFalse(query.fuzzy)
|
||||
}
|
||||
|
||||
func testSimpleQuery() {
|
||||
let query = SearchQuery(rawValue: "swift programming")
|
||||
|
||||
XCTAssertEqual(query.terms, ["swift", "programming"])
|
||||
XCTAssertEqual(query.rawText, "swift programming")
|
||||
}
|
||||
|
||||
func testQueryWithDateFilter() {
|
||||
let query = SearchQuery(rawValue: "swift date:after:2024-01-01")
|
||||
|
||||
XCTAssertEqual(query.terms, ["swift"])
|
||||
XCTAssertNotNil(query.filters.dateRange)
|
||||
|
||||
if case .after(let date) = query.filters.dateRange! {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "yyyy-MM-dd"
|
||||
let expectedDate = formatter.date(from: "2024-01-01")!
|
||||
XCTAssertEqual(date, expectedDate)
|
||||
} else {
|
||||
XCTFail("Expected .after case")
|
||||
}
|
||||
}
|
||||
|
||||
func testQueryWithFeedFilter() {
|
||||
let query = SearchQuery(rawValue: "swift feed:Apple Developer")
|
||||
|
||||
XCTAssertEqual(query.terms, ["swift"])
|
||||
XCTAssertEqual(query.filters.feedTitle, "Apple Developer")
|
||||
}
|
||||
|
||||
func testQueryWithAuthorFilter() {
|
||||
let query = SearchQuery(rawValue: "swift author:John Doe")
|
||||
|
||||
XCTAssertEqual(query.terms, ["swift"])
|
||||
XCTAssertEqual(query.filters.author, "John Doe")
|
||||
}
|
||||
|
||||
func testQueryWithSortOption() {
|
||||
let query = SearchQuery(rawValue: "swift sort:date_desc")
|
||||
|
||||
XCTAssertEqual(query.terms, ["swift"])
|
||||
XCTAssertEqual(query.sort, .dateDesc)
|
||||
}
|
||||
|
||||
func testQueryWithFuzzyFlag() {
|
||||
let query = SearchQuery(rawValue: "swift ~")
|
||||
|
||||
XCTAssertEqual(query.terms, ["swift"])
|
||||
XCTAssertTrue(query.fuzzy)
|
||||
}
|
||||
|
||||
func testFTSQueryGeneration() {
|
||||
let exactQuery = SearchQuery(rawValue: "swift programming")
|
||||
XCTAssertEqual(exactQuery.ftsQuery(), "\"swift\" OR \"programming\"")
|
||||
|
||||
let fuzzyQuery = SearchQuery(rawValue: "swift ~")
|
||||
XCTAssertEqual(fuzzyQuery.ftsQuery(), "\"*swift*\"")
|
||||
}
|
||||
|
||||
func testDisplayString() {
|
||||
let query = SearchQuery(rawValue: "swift date:after:2024-01-01")
|
||||
XCTAssertEqual(query.displayString, "swift")
|
||||
}
|
||||
|
||||
func testDateRangeLowerBound() {
|
||||
let afterRange = DateRange.after(Date())
|
||||
XCTAssertNotNil(afterRange.lowerBound)
|
||||
XCTAssertNil(afterRange.upperBound)
|
||||
|
||||
let beforeRange = DateRange.before(Date())
|
||||
XCTAssertNil(beforeRange.lowerBound)
|
||||
XCTAssertNotNil(beforeRange.upperBound)
|
||||
|
||||
let exactRange = DateRange.exact(Date())
|
||||
XCTAssertNotNil(exactRange.lowerBound)
|
||||
XCTAssertNotNil(exactRange.upperBound)
|
||||
}
|
||||
|
||||
func testSearchFiltersIsEmpty() {
|
||||
var filters = SearchFilters()
|
||||
XCTAssertTrue(filters.isEmpty)
|
||||
|
||||
filters.dateRange = .after(Date())
|
||||
XCTAssertFalse(filters.isEmpty)
|
||||
|
||||
filters = .empty
|
||||
XCTAssertTrue(filters.isEmpty)
|
||||
}
|
||||
|
||||
func testSortOptionOrderByClause() {
|
||||
XCTAssertEqual(SearchSortOption.relevance.orderByClause(), "rank")
|
||||
XCTAssertEqual(SearchSortOption.dateDesc.orderByClause(), "f.published DESC")
|
||||
XCTAssertEqual(SearchSortOption.titleAsc.orderByClause(), "f.title ASC")
|
||||
XCTAssertEqual(SearchSortOption.feedDesc.orderByClause(), "s.title DESC")
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
import XCTest
|
||||
@testable import RSSuper
|
||||
|
||||
/// Unit tests for SearchResult and related types
|
||||
final class SearchResultTests: XCTestCase {
|
||||
|
||||
func testArticleResultCreation() {
|
||||
let result = SearchResult.article(
|
||||
id: "article-123",
|
||||
title: "Test Article",
|
||||
snippet: "This is a snippet",
|
||||
link: "https://example.com/article",
|
||||
feedTitle: "Test Feed",
|
||||
published: Date(),
|
||||
score: 0.95,
|
||||
author: "Test Author"
|
||||
)
|
||||
|
||||
XCTAssertEqual(result.id, "article-123")
|
||||
XCTAssertEqual(result.type, .article)
|
||||
XCTAssertEqual(result.title, "Test Article")
|
||||
XCTAssertEqual(result.snippet, "This is a snippet")
|
||||
XCTAssertEqual(result.link, "https://example.com/article")
|
||||
XCTAssertEqual(result.feedTitle, "Test Feed")
|
||||
XCTAssertEqual(result.score, 0.95)
|
||||
XCTAssertEqual(result.author, "Test Author")
|
||||
}
|
||||
|
||||
func testFeedResultCreation() {
|
||||
let result = SearchResult.feed(
|
||||
id: "feed-456",
|
||||
title: "Test Feed",
|
||||
link: "https://example.com/feed.xml",
|
||||
score: 0.85
|
||||
)
|
||||
|
||||
XCTAssertEqual(result.id, "feed-456")
|
||||
XCTAssertEqual(result.type, .feed)
|
||||
XCTAssertEqual(result.title, "Test Feed")
|
||||
XCTAssertEqual(result.link, "https://example.com/feed.xml")
|
||||
XCTAssertEqual(result.score, 0.85)
|
||||
}
|
||||
|
||||
func testSuggestionResultCreation() {
|
||||
let result = SearchResult.suggestion(
|
||||
text: "swift programming",
|
||||
score: 0.75
|
||||
)
|
||||
|
||||
XCTAssertEqual(result.type, .suggestion)
|
||||
XCTAssertEqual(result.title, "swift programming")
|
||||
XCTAssertEqual(result.score, 0.75)
|
||||
}
|
||||
|
||||
func testSearchResultTypeEncoding() {
|
||||
XCTAssertEqual(SearchResultType.article.rawValue, "article")
|
||||
XCTAssertEqual(SearchResultType.feed.rawValue, "feed")
|
||||
XCTAssertEqual(SearchResultType.suggestion.rawValue, "suggestion")
|
||||
XCTAssertEqual(SearchResultType.tag.rawValue, "tag")
|
||||
XCTAssertEqual(SearchResultType.author.rawValue, "author")
|
||||
}
|
||||
|
||||
func testSearchResultEquatable() {
|
||||
let result1 = SearchResult.article(id: "1", title: "Test")
|
||||
let result2 = SearchResult.article(id: "1", title: "Test")
|
||||
let result3 = SearchResult.article(id: "2", title: "Test")
|
||||
|
||||
XCTAssertEqual(result1, result2)
|
||||
XCTAssertNotEqual(result1, result3)
|
||||
}
|
||||
|
||||
func testSearchResults totalCount() {
|
||||
let results = SearchResults(
|
||||
articles: [SearchResult.article(id: "1", title: "A")],
|
||||
feeds: [SearchResult.feed(id: "2", title: "F")],
|
||||
suggestions: []
|
||||
)
|
||||
|
||||
XCTAssertEqual(results.totalCount, 2)
|
||||
XCTAssertTrue(results.hasResults)
|
||||
}
|
||||
|
||||
func testSearchResultsEmpty() {
|
||||
let results = SearchResults(articles: [], feeds: [], suggestions: [])
|
||||
|
||||
XCTAssertEqual(results.totalCount, 0)
|
||||
XCTAssertFalse(results.hasResults)
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import XCTest
|
||||
@testable import RSSuper
|
||||
|
||||
/// Unit tests for SyncScheduler
|
||||
final class SyncSchedulerTests: XCTestCase {
|
||||
|
||||
private var scheduler: SyncScheduler!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
scheduler = SyncScheduler()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
scheduler = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testDefaultSyncInterval() {
|
||||
XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.defaultSyncInterval)
|
||||
}
|
||||
|
||||
func testSyncIntervalClamping() {
|
||||
// Test minimum clamping
|
||||
scheduler.preferredSyncInterval = 60 // 1 minute
|
||||
XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.minimumSyncInterval)
|
||||
|
||||
// Test maximum clamping
|
||||
scheduler.preferredSyncInterval = 48 * 3600 // 48 hours
|
||||
XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.maximumSyncInterval)
|
||||
}
|
||||
|
||||
func testIsSyncDue() {
|
||||
// Fresh scheduler should have sync due
|
||||
XCTAssertTrue(scheduler.isSyncDue)
|
||||
|
||||
// Set last sync date to recent past
|
||||
scheduler.lastSyncDate = Date().addingTimeInterval(-1 * 3600) // 1 hour ago
|
||||
XCTAssertFalse(scheduler.isSyncDue)
|
||||
|
||||
// Set last sync date to far past
|
||||
scheduler.lastSyncDate = Date().addingTimeInterval(-12 * 3600) // 12 hours ago
|
||||
XCTAssertTrue(scheduler.isSyncDue)
|
||||
}
|
||||
|
||||
func testTimeSinceLastSync() {
|
||||
scheduler.lastSyncDate = Date().addingTimeInterval(-3600) // 1 hour ago
|
||||
|
||||
let timeSince = scheduler.timeSinceLastSync
|
||||
XCTAssertGreaterThan(timeSince, 3500)
|
||||
XCTAssertLessThan(timeSince, 3700)
|
||||
}
|
||||
|
||||
func testResetSyncSchedule() {
|
||||
scheduler.preferredSyncInterval = 12 * 3600
|
||||
scheduler.lastSyncDate = Date().addingTimeInterval(-100)
|
||||
|
||||
scheduler.resetSyncSchedule()
|
||||
|
||||
XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.defaultSyncInterval)
|
||||
XCTAssertNil(scheduler.lastSyncDate)
|
||||
}
|
||||
|
||||
func testUserActivityLevelCalculation() {
|
||||
// High activity
|
||||
XCTAssertEqual(UserActivityLevel.calculate(from: 5, lastOpenedAgo: 3600), .high)
|
||||
XCTAssertEqual(UserActivityLevel.calculate(from: 1, lastOpenedAgo: 60), .high)
|
||||
|
||||
// Medium activity
|
||||
XCTAssertEqual(UserActivityLevel.calculate(from: 2, lastOpenedAgo: 3600), .medium)
|
||||
XCTAssertEqual(UserActivityLevel.calculate(from: 0, lastOpenedAgo: 43200), .medium)
|
||||
|
||||
// Low activity
|
||||
XCTAssertEqual(UserActivityLevel.calculate(from: 0, lastOpenedAgo: 172800), .low)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user