refactor(sessions): extract search formatting and paging logic

Extract SessionSearchFormatting and SessionsPaging helpers.
Deduplicate paging calculation in SessionsViewModel and add unit tests.
This commit is contained in:
Hy4ri committed 2026-09-11 17:53:02 +03:00
1 parent f0c2d2f87b
commit 6876db0393
7 files changed
+315 -112

No files matched your search

@@ -0,0 +1,72 @@
package com.m57.hermescontrol.ui.sessions
import com.m57.hermescontrol.data.model.SessionSearchResult
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
class SessionSearchFormattingTest {
@Test
fun `clean search snippet strips highlight markers from plain text`() {
assertEquals(
"Find the deployment logs",
cleanSearchSnippet(">>>Find<<< the deployment logs"),
)
}
@Test
fun `clean search snippet extracts text from JSON payload`() {
assertEquals(
"Find the deployment logs",
cleanSearchSnippet("{\"role\":\"user\",\"content\":\">>>Find<<< the deployment logs\"}"),
)
}
@Test
fun `clean search snippet extracts nested text array`() {
assertEquals(
"First part second part",
cleanSearchSnippet("{\"parts\":[\">>>First<<< part\",\"second part\"]}"),
)
}
@Test
fun `clean search snippet normalizes whitespace`() {
assertEquals(
"hello world",
cleanSearchSnippet(" hello world \n "),
)
}
@Test
fun `toSessionInfo leaves title null for match layout`() {
val searchResult =
SessionSearchResult(
session_id = "test-123",
session_started = 1700000000.0,
snippet = "matched query excerpt",
source = "cli",
model = "test-model",
)
val info = searchResult.toSessionInfo()
assertEquals("test-123", info.id)
assertNull(info.title)
assertEquals("matched query excerpt", info.preview)
assertEquals("cli", info.source)
assertEquals("test-model", info.model)
}
@Test
fun `formatPlayedAt handles null and negative epoch`() {
assertNull(formatPlayedAt(null))
assertNull(formatPlayedAt(0.0))
assertNull(formatPlayedAt(-100.0))
}
@Test
fun `formatPlayedAt returns formatted string for valid timestamp`() {
val result = formatPlayedAt(1700000000.0)
assertNotNull(result)
}
}
@@ -0,0 +1,75 @@
package com.m57.hermescontrol.ui.sessions
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class SessionsPagingTest {
@Test
fun `resolveInitialPaging hasMore when received full page and total exceeds accumulated`() {
val resolution =
SessionsPaging.resolveInitialPaging(
receivedCount = 50,
pageSize = 50,
backendTotal = 120,
accumulatedCount = 50,
)
assertTrue(resolution.hasMore)
assertEquals(120, resolution.total)
}
@Test
fun `resolveInitialPaging no more when received less than page size`() {
val resolution =
SessionsPaging.resolveInitialPaging(
receivedCount = 30,
pageSize = 50,
backendTotal = 30,
accumulatedCount = 30,
)
assertFalse(resolution.hasMore)
assertEquals(30, resolution.total)
}
@Test
fun `resolveInitialPaging no more when backendTotal equals accumulated`() {
val resolution =
SessionsPaging.resolveInitialPaging(
receivedCount = 50,
pageSize = 50,
backendTotal = 50,
accumulatedCount = 50,
)
assertFalse(resolution.hasMore)
assertEquals(50, resolution.total)
}
@Test
fun `resolveLoadMorePaging hasMore when full page added new items and total exceeds accumulated`() {
val resolution =
SessionsPaging.resolveLoadMorePaging(
receivedCount = 50,
pageSize = 50,
addedNewItems = true,
backendTotal = 150,
accumulatedCount = 100,
)
assertTrue(resolution.hasMore)
assertEquals(150, resolution.total)
}
@Test
fun `resolveLoadMorePaging no more when no new items added`() {
val resolution =
SessionsPaging.resolveLoadMorePaging(
receivedCount = 50,
pageSize = 50,
addedNewItems = false,
backendTotal = 150,
accumulatedCount = 100,
)
assertFalse(resolution.hasMore)
assertEquals(100, resolution.total)
}
}
@@ -92,14 +92,6 @@ class SessionsViewModelTest {
)
}
@Test
fun `clean search snippet extracts text from JSON payload`() {
assertEquals(
"Find the deployment logs",
cleanSearchSnippet("{\"role\":\"user\",\"content\":\">>>Find<<< the deployment logs\"}"),
)
}
@Test
fun `sections request conversations excluding cron and automations from cron`() {
val vm = createViewModel()