91 lines
3.0 KiB
Swift
91 lines
3.0 KiB
Swift
import Testing
|
|
import GRDB
|
|
@testable import MailStore
|
|
@testable import Models
|
|
|
|
@Suite("MailStore Search & Queries")
|
|
struct SearchTests {
|
|
func makeStore() throws -> MailStore {
|
|
try MailStore(dbWriter: DatabaseSetup.openInMemoryDatabase())
|
|
}
|
|
|
|
func seedData(_ store: MailStore) throws {
|
|
try store.insertAccount(AccountRecord(
|
|
id: "acc1", name: "Personal", email: "me@example.com",
|
|
imapHost: "imap.example.com", imapPort: 993
|
|
))
|
|
try store.upsertMailbox(MailboxRecord(
|
|
id: "mb1", accountId: "acc1", name: "INBOX", uidValidity: 1, uidNext: 100
|
|
))
|
|
try store.insertMessages([
|
|
MessageRecord(
|
|
id: "m1", accountId: "acc1", mailboxId: "mb1", uid: 1,
|
|
messageId: "msg001@example.com", inReplyTo: nil, refs: nil,
|
|
subject: "Quarterly planning meeting", fromAddress: "alice@example.com",
|
|
fromName: "Alice Johnson", toAddresses: nil, ccAddresses: nil,
|
|
date: "2024-03-08T10:00:00Z", snippet: "Let's discuss Q2 goals",
|
|
bodyText: "Let's discuss Q2 goals and roadmap priorities.", bodyHtml: nil,
|
|
isRead: false, isFlagged: false, size: 1024
|
|
),
|
|
MessageRecord(
|
|
id: "m2", accountId: "acc1", mailboxId: "mb1", uid: 2,
|
|
messageId: "msg002@example.com", inReplyTo: nil, refs: nil,
|
|
subject: "Invoice #4521", fromAddress: "billing@vendor.com",
|
|
fromName: "Billing Dept", toAddresses: nil, ccAddresses: nil,
|
|
date: "2024-03-07T09:00:00Z", snippet: "Please find attached",
|
|
bodyText: "Your invoice for March is attached.", bodyHtml: nil,
|
|
isRead: true, isFlagged: false, size: 2048
|
|
),
|
|
])
|
|
}
|
|
|
|
@Test("FTS5 search finds messages by subject")
|
|
func searchBySubject() throws {
|
|
let store = try makeStore()
|
|
try seedData(store)
|
|
let results = try store.search(query: "quarterly")
|
|
#expect(results.count == 1)
|
|
#expect(results[0].id == "m1")
|
|
}
|
|
|
|
@Test("FTS5 search finds messages by body text")
|
|
func searchByBody() throws {
|
|
let store = try makeStore()
|
|
try seedData(store)
|
|
let results = try store.search(query: "roadmap")
|
|
#expect(results.count == 1)
|
|
#expect(results[0].id == "m1")
|
|
}
|
|
|
|
@Test("FTS5 search finds messages by sender name")
|
|
func searchBySender() throws {
|
|
let store = try makeStore()
|
|
try seedData(store)
|
|
let results = try store.search(query: "alice")
|
|
#expect(results.count == 1)
|
|
#expect(results[0].fromName == "Alice Johnson")
|
|
}
|
|
|
|
@Test("FTS5 search returns empty for no matches")
|
|
func searchNoMatch() throws {
|
|
let store = try makeStore()
|
|
try seedData(store)
|
|
let results = try store.search(query: "nonexistent")
|
|
#expect(results.isEmpty)
|
|
}
|
|
|
|
@Test("thread summaries include unread count and senders")
|
|
func threadSummaries() throws {
|
|
let store = try makeStore()
|
|
try seedData(store)
|
|
let reconstructor = ThreadReconstructor(store: store)
|
|
let messages = try store.messages(mailboxId: "mb1")
|
|
try reconstructor.processMessages(messages)
|
|
let summaries = try store.threadSummaries(accountId: "acc1")
|
|
#expect(summaries.count == 2)
|
|
// First thread (most recent) should be "Quarterly planning meeting"
|
|
#expect(summaries[0].subject == "Quarterly planning meeting")
|
|
#expect(summaries[0].unreadCount == 1)
|
|
}
|
|
}
|