Merge branch 'main' into fix-backfill-gaps
This commit is contained in:
@@ -53,6 +53,34 @@ class LibreMailDatabaseTest {
|
||||
isStarred = false,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun observeUnreadCountsAggregatesUnreadSyncedRowsPerAccountAndFolder() = runBlocking {
|
||||
val messageDao = db.messageDao()
|
||||
messageDao.insertNew(
|
||||
listOf(
|
||||
// acct / INBOX: two unread + one read -> counts 2.
|
||||
message("acct:INBOX:1").copy(folder = "INBOX", isRead = false),
|
||||
message("acct:INBOX:2").copy(folder = "INBOX", isRead = false),
|
||||
message("acct:INBOX:3").copy(folder = "INBOX", isRead = true),
|
||||
// acct / Archive: one unread -> counts 1.
|
||||
message("acct:Archive:1").copy(folder = "Archive", isRead = false),
|
||||
// An unread server-search hit (inInbox = false) must never inflate a badge.
|
||||
message("acct:INBOX:search").copy(folder = "INBOX", isRead = false, inInbox = false),
|
||||
// A second account's unread inbox row is counted under its own accountId.
|
||||
message("acct2:INBOX:1").copy(accountId = "acct2", folder = "INBOX", isRead = false),
|
||||
),
|
||||
)
|
||||
|
||||
val counts = messageDao.observeUnreadCounts().first()
|
||||
.associate { (it.accountId to it.folder) to it.unreadCount }
|
||||
|
||||
assertEquals(2, counts[("acct" to "INBOX")])
|
||||
assertEquals(1, counts[("acct" to "Archive")])
|
||||
assertEquals(1, counts[("acct2" to "INBOX")])
|
||||
// Fully-read folders and search-only rows produce no group at all.
|
||||
assertEquals(3, counts.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deletingMessageCascadesToItsAttachments() = runBlocking {
|
||||
val messageDao = db.messageDao()
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.libremail.domain.model.Message
|
||||
import org.libremail.domain.model.OutboxMessage
|
||||
import org.libremail.domain.model.OutgoingMessage
|
||||
import org.libremail.domain.model.ReplyMode
|
||||
import org.libremail.domain.model.UnreadCount
|
||||
import org.libremail.domain.repository.AccountRepository
|
||||
import org.libremail.domain.repository.MailRepository
|
||||
import java.io.File
|
||||
@@ -72,6 +73,7 @@ class FakeMailRepository(
|
||||
private val folders: List<Folder> = emptyList(),
|
||||
private val attachments: List<Attachment> = emptyList(),
|
||||
private val downloadedParts: Set<Int> = emptySet(),
|
||||
private val unreadCounts: List<UnreadCount> = emptyList(),
|
||||
) : MailRepository {
|
||||
|
||||
val sentMessages = mutableListOf<OutgoingMessage>()
|
||||
@@ -93,6 +95,8 @@ class FakeMailRepository(
|
||||
},
|
||||
)
|
||||
|
||||
override fun observeUnreadCounts(): Flow<List<UnreadCount>> = flowOf(unreadCounts)
|
||||
|
||||
override suspend fun refreshFolders(accountId: String): Result<Unit> = Result.success(Unit)
|
||||
|
||||
override suspend fun getMessage(id: String): Message? = messages.firstOrNull { it.id == id }
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.activity.ComponentActivity
|
||||
import androidx.compose.material3.ModalDrawerSheet
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
@@ -145,10 +146,34 @@ class FolderDrawerTest {
|
||||
assertTrue(unifiedTapped)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun folderWithUnreadMail_showsCountBadge_andReadFolderShowsNone() {
|
||||
setContent(
|
||||
accounts = listOf(alice),
|
||||
drawerAccount = alice,
|
||||
folders = listOf(
|
||||
folder("imap:a", "INBOX", "INBOX", FolderRole.INBOX),
|
||||
folder("imap:a", "Archive", "Archive", FolderRole.ARCHIVE),
|
||||
),
|
||||
folderUnreadCounts = mapOf("INBOX" to 3),
|
||||
)
|
||||
|
||||
// The inbox badge announces its exact count for screen readers.
|
||||
val threeUnread = composeTestRule.activity.resources
|
||||
.getQuantityString(R.plurals.folder_unread_count_description, 3, 3)
|
||||
composeTestRule.onNodeWithContentDescription(threeUnread).assertIsDisplayed()
|
||||
// Archive has no unread mail, so no badge is rendered for it.
|
||||
val oneUnread = composeTestRule.activity.resources
|
||||
.getQuantityString(R.plurals.folder_unread_count_description, 1, 1)
|
||||
composeTestRule.onNodeWithContentDescription(oneUnread).assertDoesNotExist()
|
||||
}
|
||||
|
||||
private fun setContent(
|
||||
accounts: List<Account>,
|
||||
drawerAccount: Account?,
|
||||
folders: List<Folder>,
|
||||
folderUnreadCounts: Map<String, Int> = emptyMap(),
|
||||
accountsWithUnread: Set<String> = emptySet(),
|
||||
selectedAccountId: String? = null,
|
||||
selectedFolder: String = "INBOX",
|
||||
onSelectUnifiedInbox: () -> Unit = {},
|
||||
@@ -162,6 +187,8 @@ class FolderDrawerTest {
|
||||
accounts = accounts,
|
||||
drawerAccount = drawerAccount,
|
||||
folders = folders,
|
||||
folderUnreadCounts = folderUnreadCounts,
|
||||
accountsWithUnread = accountsWithUnread,
|
||||
selectedAccountId = selectedAccountId,
|
||||
selectedFolder = selectedFolder,
|
||||
onSelectUnifiedInbox = onSelectUnifiedInbox,
|
||||
|
||||
Reference in New Issue
Block a user