feat: Add local SQLite analytics tracking
CI / build (push) Has been cancelled
CI / lint (push) Has been cancelled

- AnalyticsEvent: Data class for tracked events
- AnalyticsDao: Room DAO with CRUD operations
- AnalyticsDatabase: Room database singleton
- AnalyticsManager: High-level API for logging events
- Unit tests for AnalyticsEvent

Event types: page_view, session_start, session_end,
idle_reset, admin_access, config_sync, signage_rotate

Supports JSON/CSV export for admin panel integration.
This commit is contained in:
2026-02-03 20:52:10 +00:00
parent 58f960ee2d
commit cef6ab1c6a
7 changed files with 376 additions and 0 deletions
@@ -0,0 +1,110 @@
package farm.hobbs.kioskbrowser
import farm.hobbs.kioskbrowser.analytics.AnalyticsEvent
import org.junit.Assert.*
import org.junit.Test
/**
* Unit tests for AnalyticsEvent data class.
*/
class AnalyticsEventTest {
@Test
fun `event types are defined correctly`() {
assertEquals("page_view", AnalyticsEvent.PAGE_VIEW)
assertEquals("session_start", AnalyticsEvent.SESSION_START)
assertEquals("session_end", AnalyticsEvent.SESSION_END)
assertEquals("idle_reset", AnalyticsEvent.IDLE_RESET)
assertEquals("admin_access", AnalyticsEvent.ADMIN_ACCESS)
assertEquals("config_sync", AnalyticsEvent.CONFIG_SYNC)
assertEquals("signage_rotate", AnalyticsEvent.SIGNAGE_ROTATE)
}
@Test
fun `event has default timestamp`() {
val before = System.currentTimeMillis()
val event = AnalyticsEvent(
deviceId = "test-device",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}"
)
val after = System.currentTimeMillis()
assertTrue(event.timestamp >= before)
assertTrue(event.timestamp <= after)
}
@Test
fun `event has default synced false`() {
val event = AnalyticsEvent(
deviceId = "test-device",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}"
)
assertFalse(event.synced)
}
@Test
fun `event has default id zero`() {
val event = AnalyticsEvent(
deviceId = "test-device",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}"
)
assertEquals(0L, event.id)
}
@Test
fun `event can store json data`() {
val jsonData = """{"url":"https://example.com","duration_ms":5000}"""
val event = AnalyticsEvent(
deviceId = "test-device",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = jsonData
)
assertEquals(jsonData, event.eventData)
}
@Test
fun `event equality works correctly`() {
val event1 = AnalyticsEvent(
id = 1,
deviceId = "device1",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}",
timestamp = 12345L
)
val event2 = AnalyticsEvent(
id = 1,
deviceId = "device1",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}",
timestamp = 12345L
)
assertEquals(event1, event2)
}
@Test
fun `different events are not equal`() {
val event1 = AnalyticsEvent(
id = 1,
deviceId = "device1",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}",
timestamp = 12345L
)
val event2 = AnalyticsEvent(
id = 2,
deviceId = "device1",
eventType = AnalyticsEvent.PAGE_VIEW,
eventData = "{}",
timestamp = 12345L
)
assertNotEquals(event1, event2)
}
}