package com.suno.android.common_data.repos.orpheus import app.cash.turbine.test import com.suno.android.common_core_utils.Id import com.suno.android.common_data.repos.orpheus.models.OrpheusSession import com.suno.android.common_networking.orpheus.OrpheusRealtimeClient import com.suno.android.common_networking.sse.RealtimeEvent import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class OrpheusConnectionManagerTest { private val testSessionId = Id("test-session-id") private val testDispatcher = UnconfinedTestDispatcher() private val realtimeClient = mockk(relaxed = true) private val subject = OrpheusConnectionManager( loggerFactory = mockk(relaxed = true), realtimeClient = realtimeClient, dispatcher = testDispatcher, ) @Test fun `given sessionId when connect called then subscribes to realtime client`() = runTest(testDispatcher) { val testEvent = RealtimeEvent.Connected every { realtimeClient.subscribe(testSessionId.value) } returns flowOf(testEvent) subject.connect(sessionId = testSessionId) verify { realtimeClient.subscribe(testSessionId.value) } } @Test fun `given sessionId when connect called then emits events to realtimeEvents flow`() = runTest(testDispatcher) { val testEvent = RealtimeEvent.Connected every { realtimeClient.subscribe(testSessionId.value) } returns flowOf(testEvent) subject.realtimeEvents.test { subject.connect(sessionId = testSessionId) assertEquals(testEvent, awaitItem()) } } @Test fun `given multiple events when connect called then emits all events to realtimeEvents flow`() = runTest(testDispatcher) { val event1 = RealtimeEvent.Connected val event2 = RealtimeEvent.Disconnected every { realtimeClient.subscribe(testSessionId.value) } returns flowOf(event1, event2) subject.realtimeEvents.test { subject.connect(sessionId = testSessionId) assertEquals(event1, awaitItem()) assertEquals(event2, awaitItem()) } } @Test fun `given active connection when connect called again then always resubscribes`() = runTest(testDispatcher) { val firstEvent = RealtimeEvent.Connected every { realtimeClient.subscribe(testSessionId.value) } returns flowOf(firstEvent) subject.connect(sessionId = testSessionId) val secondEvent = RealtimeEvent.Disconnected every { realtimeClient.subscribe(testSessionId.value) } returns flowOf(secondEvent) subject.connect(sessionId = testSessionId) verify(exactly = 2) { realtimeClient.subscribe(testSessionId.value) } } @Test fun `given active connection when disconnect called then cancels subscription`() = runTest(testDispatcher) { val testEvent = RealtimeEvent.Connected every { realtimeClient.subscribe(testSessionId.value) } returns flowOf(testEvent) subject.connect(sessionId = testSessionId) subject.disconnect() verify { realtimeClient.subscribe(testSessionId.value) } } }