diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/data/DmChatRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/data/DmChatRepository.kt new file mode 100644 index 00000000..4fe09ded --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/data/DmChatRepository.kt @@ -0,0 +1,60 @@ +package kr.co.vividnext.sodalive.v2.main.chat.dm.data + +import io.reactivex.rxjava3.core.Single +import kr.co.vividnext.sodalive.common.ApiResponse + +class DmChatRepository(private val api: DmChatApi) { + fun createOrGetRoom( + token: String, + creatorId: Long + ): Single> = api.createDmChatRoom( + authHeader = bearer(token), + request = CreateDmChatRoomRequest(creatorId = creatorId) + ) + + fun openRoom( + token: String, + roomId: Long, + limit: Int = DEFAULT_LIMIT + ): Single> = api.openDmChatRoom( + authHeader = bearer(token), + roomId = roomId, + limit = limit + ) + + fun getMessages( + token: String, + roomId: Long, + cursor: Long?, + limit: Int = DEFAULT_LIMIT + ): Single> = api.getDmChatMessages( + authHeader = bearer(token), + roomId = roomId, + cursor = cursor, + limit = limit + ) + + fun sendTextMessage( + token: String, + roomId: Long, + textMessage: String + ): Single> = api.sendDmTextMessage( + authHeader = bearer(token), + roomId = roomId, + request = SendDmTextMessageRequest(textMessage = textMessage) + ) + + fun disconnectRealtime( + token: String, + roomId: Long + ): Single> = api.disconnectRealtime( + authHeader = bearer(token), + roomId = roomId + ) + + private fun bearer(token: String) = "Bearer $token" + + private companion object { + const val DEFAULT_LIMIT = 20 + } +} diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRepositoryTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRepositoryTest.kt new file mode 100644 index 00000000..a423274b --- /dev/null +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRepositoryTest.kt @@ -0,0 +1,171 @@ +package kr.co.vividnext.sodalive.v2.main.chat.dm + +import io.reactivex.rxjava3.core.Single +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.CreateDmChatRoomRequest +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.CreateDmChatRoomResponse +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.DmChatApi +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.DmChatMessageResponse +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.DmChatMessagesPageResponse +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.DmChatRepository +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.DmChatRoomOpenResponse +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.SendDmChatMessageResponse +import kr.co.vividnext.sodalive.v2.main.chat.dm.data.SendDmTextMessageRequest +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test + +class DmChatRepositoryTest { + + private val api = FakeDmChatApi() + private val repository = DmChatRepository(api) + + @Test + fun `createOrGetRoom은 bearer header와 creatorId를 API에 위임한다`() { + repository.createOrGetRoom(token = "test-token", creatorId = 11L).blockingGet() + + assertEquals("Bearer test-token", api.lastAuthHeader) + assertEquals(CreateDmChatRoomRequest(creatorId = 11L), api.lastCreateRequest) + } + + @Test + fun `openRoom은 기본 limit 20과 bearer header를 API에 위임한다`() { + repository.openRoom(token = "test-token", roomId = 12L).blockingGet() + + assertEquals("Bearer test-token", api.lastAuthHeader) + assertEquals(12L, api.lastRoomId) + assertEquals(20, api.lastLimit) + } + + @Test + fun `getMessages는 cursor와 limit을 API에 위임한다`() { + repository.getMessages(token = "test-token", roomId = 12L, cursor = 30L, limit = 10).blockingGet() + + assertEquals("Bearer test-token", api.lastAuthHeader) + assertEquals(12L, api.lastRoomId) + assertEquals(30L, api.lastCursor) + assertEquals(10, api.lastLimit) + } + + @Test + fun `sendTextMessage는 textMessage request를 API에 위임한다`() { + repository.sendTextMessage(token = "test-token", roomId = 12L, textMessage = "안녕").blockingGet() + + assertEquals("Bearer test-token", api.lastAuthHeader) + assertEquals(12L, api.lastRoomId) + assertEquals(SendDmTextMessageRequest(textMessage = "안녕"), api.lastSendRequest) + } + + @Test + fun `disconnectRealtime은 bearer header와 roomId를 API에 위임한다`() { + repository.disconnectRealtime(token = "test-token", roomId = 12L).blockingGet() + + assertEquals("Bearer test-token", api.lastAuthHeader) + assertEquals(12L, api.lastRoomId) + assertNull(api.lastSendRequest) + } + + private class FakeDmChatApi : DmChatApi { + var lastAuthHeader: String? = null + var lastCreateRequest: CreateDmChatRoomRequest? = null + var lastSendRequest: SendDmTextMessageRequest? = null + var lastRoomId: Long? = null + var lastCursor: Long? = null + var lastLimit: Int? = null + + override fun createDmChatRoom( + authHeader: String, + request: CreateDmChatRoomRequest + ): Single> { + lastAuthHeader = authHeader + lastCreateRequest = request + return Single.just(ApiResponse(success = true, data = CreateDmChatRoomResponse(roomId = 12L))) + } + + override fun openDmChatRoom( + authHeader: String, + roomId: Long, + limit: Int + ): Single> { + lastAuthHeader = authHeader + lastRoomId = roomId + lastLimit = limit + return Single.just( + ApiResponse( + success = true, + data = DmChatRoomOpenResponse( + roomId = roomId, + opponentNickname = "상대", + opponentProfileImageUrl = "https://example.com/profile.png", + messages = emptyList(), + hasMore = false, + nextCursor = null + ) + ) + ) + } + + override fun getDmChatMessages( + authHeader: String, + roomId: Long, + cursor: Long?, + limit: Int + ): Single> { + lastAuthHeader = authHeader + lastRoomId = roomId + lastCursor = cursor + lastLimit = limit + return Single.just( + ApiResponse( + success = true, + data = DmChatMessagesPageResponse( + messages = emptyList(), + hasMore = false, + nextCursor = null + ) + ) + ) + } + + override fun sendDmTextMessage( + authHeader: String, + roomId: Long, + request: SendDmTextMessageRequest + ): Single> { + lastAuthHeader = authHeader + lastRoomId = roomId + lastSendRequest = request + return Single.just( + ApiResponse( + success = true, + data = SendDmChatMessageResponse( + message = message(), + deliveredRealtime = true, + pushSent = false + ) + ) + ) + } + + override fun disconnectRealtime( + authHeader: String, + roomId: Long + ): Single> { + lastAuthHeader = authHeader + lastRoomId = roomId + return Single.just(ApiResponse(success = true, data = true)) + } + + private fun message() = DmChatMessageResponse( + messageId = 1L, + messageType = "TEXT", + mine = true, + createdAt = 1000L, + textMessage = "안녕", + voiceMessageUrl = null, + senderId = 2L, + senderNickname = "나", + senderProfileImageUrl = "https://example.com/profile.png" + ) + } +}