feat(recommendation): 인기 커뮤니티 본문 번역을 적용한다
This commit is contained in:
+75
@@ -1,6 +1,7 @@
|
||||
package kr.co.vividnext.sodalive.v2.api.home
|
||||
|
||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunity
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberAdapter
|
||||
@@ -12,6 +13,8 @@ import kr.co.vividnext.sodalive.member.following.CreatorFollowing
|
||||
import kr.co.vividnext.sodalive.member.following.CreatorFollowingRepository
|
||||
import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer
|
||||
import kr.co.vividnext.sodalive.v2.api.home.application.HomeRecommendationFacade
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.application.CreatorCommunityDisplayContent
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.application.CreatorCommunityTranslationService
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.adapter.out.persistence.RecommendationSnapshot
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendationSnapshotWindowPolicy
|
||||
@@ -27,6 +30,7 @@ import org.mockito.Mockito
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.boot.test.mock.mockito.MockBean
|
||||
import org.springframework.boot.test.system.CapturedOutput
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension
|
||||
import org.springframework.http.MediaType
|
||||
@@ -53,6 +57,9 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
private val creatorFollowingRepository: CreatorFollowingRepository,
|
||||
private val entityManager: EntityManager
|
||||
) {
|
||||
@MockBean
|
||||
private lateinit var creatorCommunityTranslationService: CreatorCommunityTranslationService
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 크리에이터 동시 팔로우 비로그인 요청은 Spring Security에서 거부한다")
|
||||
fun shouldRejectAnonymousFollowRequest() {
|
||||
@@ -230,6 +237,60 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
assertTrue(output.out.contains("emptySections="))
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("비회원 홈 추천은 반환된 인기 커뮤니티 게시물만 일본어 표시 본문으로 반환한다")
|
||||
fun shouldReturnJapanesePopularCommunityTranslationForAnonymous() {
|
||||
val translatedCreator = saveMember("popular-community-translated-creator", MemberRole.CREATOR)
|
||||
val fallbackCreator = saveMember("popular-community-fallback-creator", MemberRole.CREATOR)
|
||||
val translatedPost = saveCommunityPost(translatedCreator, "historical translated popular body")
|
||||
val fallbackPost = saveCommunityPost(fallbackCreator, "historical fallback popular body")
|
||||
val snapshotAt = RecommendationSnapshotWindowPolicy()
|
||||
.previousKstDayUtcWindow(LocalDateTime.now(ZoneOffset.UTC))
|
||||
.snapshotAt
|
||||
entityManager.persist(
|
||||
RecommendationSnapshot(
|
||||
sectionType = RecommendedSectionType.POPULAR_COMMUNITY,
|
||||
targetId = translatedPost.id!!,
|
||||
score = 100.0,
|
||||
snapshotAt = snapshotAt,
|
||||
randomTieBreaker = 0.1
|
||||
)
|
||||
)
|
||||
entityManager.persist(
|
||||
RecommendationSnapshot(
|
||||
sectionType = RecommendedSectionType.POPULAR_COMMUNITY,
|
||||
targetId = fallbackPost.id!!,
|
||||
score = 90.0,
|
||||
snapshotAt = snapshotAt,
|
||||
randomTieBreaker = 0.2
|
||||
)
|
||||
)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
Mockito.`when`(
|
||||
creatorCommunityTranslationService.findDisplayContents(
|
||||
listOf(translatedPost.id!!, fallbackPost.id!!),
|
||||
"ja"
|
||||
)
|
||||
).thenReturn(
|
||||
mapOf(
|
||||
translatedPost.id!! to CreatorCommunityDisplayContent("translated popular body ja", true),
|
||||
fallbackPost.id!! to CreatorCommunityDisplayContent("current fallback popular body ja", false)
|
||||
)
|
||||
)
|
||||
|
||||
mockMvc.perform(get("/api/v2/home/recommendations").header("Accept-Language", "ja"))
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(jsonPath("$.data.popularCommunityPosts[0].content").value("translated popular body ja"))
|
||||
.andExpect(jsonPath("$.data.popularCommunityPosts[1].content").value("current fallback popular body ja"))
|
||||
|
||||
Mockito.verify(creatorCommunityTranslationService).findDisplayContents(
|
||||
listOf(translatedPost.id!!, fallbackPost.id!!),
|
||||
"ja"
|
||||
)
|
||||
Mockito.verifyNoMoreInteractions(creatorCommunityTranslationService)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("메인 홈 통합 조회는 인증 회원도 호출 가능하고 성공 응답한다")
|
||||
fun shouldReturnHomeRecommendationsForMember() {
|
||||
@@ -590,6 +651,20 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveCommunityPost(creator: Member, content: String): CreatorCommunity {
|
||||
val post = CreatorCommunity(
|
||||
content = content,
|
||||
price = 0,
|
||||
isCommentAvailable = true,
|
||||
isAdult = false,
|
||||
isActive = true
|
||||
).apply {
|
||||
member = creator
|
||||
}
|
||||
entityManager.persist(post)
|
||||
return post
|
||||
}
|
||||
|
||||
private fun saveLiveRoom(
|
||||
creator: Member,
|
||||
beginDateTime: LocalDateTime,
|
||||
|
||||
+4
-1
@@ -4,6 +4,7 @@ import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.application.CreatorCommunityTranslationService
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeAiCharacterRecommendationRecord
|
||||
@@ -27,10 +28,12 @@ import java.time.LocalDateTime
|
||||
|
||||
class HomeRecommendationFacadeTest {
|
||||
private val queryPort = FakeHomeRecommendationQueryPort()
|
||||
private val creatorCommunityTranslationService = Mockito.mock(CreatorCommunityTranslationService::class.java)
|
||||
private val queryService = HomeRecommendationQueryService(
|
||||
queryPort,
|
||||
EmptyRecommendationSnapshotPort(),
|
||||
langContext = LangContext()
|
||||
langContext = LangContext(),
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
private val preferenceService = Mockito.mock(MemberContentPreferenceService::class.java)
|
||||
private val facade = HomeRecommendationFacade(queryService, preferenceService, "https://cdn.test")
|
||||
|
||||
+146
-15
@@ -3,6 +3,8 @@ package kr.co.vividnext.sodalive.v2.recommendation.application
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.application.CreatorCommunityDisplayContent
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.application.CreatorCommunityTranslationService
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeAiCharacterRecommendationRecord
|
||||
import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeBannerRecommendationRecord
|
||||
@@ -20,6 +22,7 @@ import kr.co.vividnext.sodalive.v2.recommendation.port.out.RecommendationSnapsho
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
@@ -29,7 +32,18 @@ class HomeRecommendationQueryServiceTest {
|
||||
private val port = FakeHomeRecommendationQueryPort()
|
||||
private val snapshotPort = FakeHomeRecommendationSnapshotPort()
|
||||
private val langContext = LangContext()
|
||||
private val service = HomeRecommendationQueryService(port, snapshotPort, langContext = langContext)
|
||||
private val creatorCommunityTranslationService = Mockito.mock(CreatorCommunityTranslationService::class.java)
|
||||
private val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
|
||||
init {
|
||||
Mockito.`when`(creatorCommunityTranslationService.findDisplayContents(Mockito.anyList(), Mockito.anyString()))
|
||||
.thenReturn(emptyMap())
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("다시듣기 테마 콘텐츠는 AUDIO가 아니라 LIVE_REPLAY 활동으로 분류한다")
|
||||
@@ -162,7 +176,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
@DisplayName("AI 캐릭터 추천은 최신 스냅샷 20개를 기준으로 순서를 유지해 상세를 조립한다")
|
||||
fun shouldFindAiCharactersFromLatestSnapshotsWithLimitAndDetails() {
|
||||
val fallback = FakeAiCharacterSnapshotFallbackPort(emptyList())
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, fallback, langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
fallback,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val oldSnapshotAt = LocalDateTime.of(2026, 5, 28, 23, 59, 59)
|
||||
val latestSnapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
@@ -264,7 +284,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
val fallback = FakeAiCharacterSnapshotFallbackPort(
|
||||
listOf(snapshot(RecommendedSectionType.AI_CHARACTER, 10L, 10.0, LocalDateTime.of(2026, 7, 9, 14, 59, 59)))
|
||||
)
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, fallback, langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
fallback,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
port.aiCharacterDetails = listOf(
|
||||
HomeAiCharacterRecommendationRecord(
|
||||
characterId = 10L,
|
||||
@@ -289,7 +315,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
@DisplayName("AI 캐릭터 추천은 fallback 후에도 스냅샷이 없으면 빈 배열을 반환한다")
|
||||
fun shouldReturnEmptyAiCharactersWhenFallbackDoesNotCreateSnapshots() {
|
||||
val fallback = FakeAiCharacterSnapshotFallbackPort(emptyList())
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, fallback, langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
fallback,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
|
||||
val characters = service.findAiCharacterRecommendations()
|
||||
|
||||
@@ -305,7 +337,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
val fallback = FakeAiCharacterSnapshotFallbackPort(
|
||||
listOf(snapshot(RecommendedSectionType.AI_CHARACTER, 99L, 99.0, LocalDateTime.of(2026, 7, 9, 14, 59, 59)))
|
||||
)
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, fallback, langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
fallback,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.AI_CHARACTER,
|
||||
LocalDateTime.of(2026, 7, 9, 14, 59, 59),
|
||||
@@ -328,7 +366,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
val fallback = FakeAiCharacterSnapshotFallbackPort(
|
||||
listOf(snapshot(RecommendedSectionType.AI_CHARACTER, 99L, 99.0, LocalDateTime.of(2026, 7, 9, 14, 59, 59)))
|
||||
)
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, fallback, langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
fallback,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val snapshotAt = LocalDateTime.of(2026, 7, 9, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.AI_CHARACTER,
|
||||
@@ -355,7 +399,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
val fallback = FakeAiCharacterSnapshotFallbackPort(
|
||||
listOf(snapshot(RecommendedSectionType.AI_CHARACTER, 99L, 99.0, LocalDateTime.of(2026, 7, 9, 14, 59, 59)))
|
||||
)
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, fallback, langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
fallback,
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val snapshotAt = LocalDateTime.of(2026, 7, 9, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.AI_CHARACTER,
|
||||
@@ -380,7 +430,8 @@ class HomeRecommendationQueryServiceTest {
|
||||
snapshotPort,
|
||||
cheerCreatorSnapshotFallbackService = fallback,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val snapshotAt = LocalDateTime.of(2026, 7, 9, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
@@ -424,7 +475,8 @@ class HomeRecommendationQueryServiceTest {
|
||||
snapshotPort,
|
||||
cheerCreatorSnapshotFallbackService = fallback,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
port.cheerCreatorDetails = listOf(
|
||||
HomeCheerCreatorRecommendationRecord(
|
||||
@@ -454,7 +506,8 @@ class HomeRecommendationQueryServiceTest {
|
||||
snapshotPort,
|
||||
cheerCreatorSnapshotFallbackService = fallback,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val staleSnapshotAt = LocalDateTime.of(2026, 7, 8, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
@@ -490,7 +543,8 @@ class HomeRecommendationQueryServiceTest {
|
||||
snapshotPort,
|
||||
cheerCreatorSnapshotFallbackService = fallback,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.CHEER_CREATOR,
|
||||
@@ -509,7 +563,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
@Test
|
||||
@DisplayName("인기 커뮤니티 추천은 대상일 스냅샷 10개를 기준으로 크리에이터 중복을 제거하고 상세를 조립한다")
|
||||
fun shouldFindPopularCommunitiesFromTargetDaySnapshotsWithLimitDetailsAndCreatorUniqueness() {
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, clock = fixedClock(), langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val snapshotAt = LocalDateTime.of(2026, 7, 9, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.POPULAR_COMMUNITY,
|
||||
@@ -583,7 +643,13 @@ class HomeRecommendationQueryServiceTest {
|
||||
@Test
|
||||
@DisplayName("인기 커뮤니티 추천은 상위 스냅샷 중복 제거 후 뒤 후보로 기본 10개를 채운다")
|
||||
fun shouldBackfillPopularCommunitiesAfterRemovingDuplicateCreators() {
|
||||
val service = HomeRecommendationQueryService(port, snapshotPort, clock = fixedClock(), langContext = langContext)
|
||||
val service = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val snapshotAt = LocalDateTime.of(2026, 7, 9, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.POPULAR_COMMUNITY,
|
||||
@@ -618,6 +684,47 @@ class HomeRecommendationQueryServiceTest {
|
||||
assertEquals(communities.size, communities.map { it.creatorId }.toSet().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("인기 커뮤니티 추천은 최종 노출 게시물만 일본어 표시 본문으로 일괄 치환하고 원문 폴백을 유지한다")
|
||||
fun shouldTranslateOnlyFinalPopularCommunityRecommendationsInOneJapaneseBatch() {
|
||||
langContext.setLang(Lang.JA)
|
||||
val snapshotAt = LocalDateTime.of(2026, 7, 9, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.POPULAR_COMMUNITY,
|
||||
snapshotAt,
|
||||
(1L..4L).map { targetId ->
|
||||
snapshot(RecommendedSectionType.POPULAR_COMMUNITY, targetId, 100.0 - targetId, snapshotAt)
|
||||
}
|
||||
)
|
||||
port.popularCommunityDetails = listOf(
|
||||
popularCommunity(1L, creatorId = 10L, content = "original-1"),
|
||||
popularCommunity(2L, creatorId = 10L, content = "original-2"),
|
||||
popularCommunity(3L, creatorId = 11L, content = "historical-original-3"),
|
||||
popularCommunity(4L, creatorId = 12L, content = "original-4")
|
||||
)
|
||||
Mockito.`when`(creatorCommunityTranslationService.findDisplayContents(listOf(1L, 3L), "ja"))
|
||||
.thenReturn(
|
||||
mapOf(
|
||||
1L to CreatorCommunityDisplayContent("translated-1-ja", true),
|
||||
3L to CreatorCommunityDisplayContent("current-original-3", false)
|
||||
)
|
||||
)
|
||||
val translatedService = HomeRecommendationQueryService(
|
||||
port,
|
||||
snapshotPort,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
|
||||
val communities = translatedService.findPopularCommunityRecommendations(limit = 2)
|
||||
|
||||
assertEquals(listOf(1L, 3L), communities.map { it.communityId })
|
||||
assertEquals(listOf("translated-1-ja", "current-original-3"), communities.map { it.content })
|
||||
Mockito.verify(creatorCommunityTranslationService).findDisplayContents(listOf(1L, 3L), "ja")
|
||||
Mockito.verifyNoMoreInteractions(creatorCommunityTranslationService)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("인기 커뮤니티 추천은 대상일 스냅샷이 없고 오래된 스냅샷만 있으면 fallback refresh를 호출한다")
|
||||
fun shouldFallbackWhenOnlyStalePopularCommunitySnapshotsExist() {
|
||||
@@ -629,7 +736,8 @@ class HomeRecommendationQueryServiceTest {
|
||||
snapshotPort,
|
||||
popularCommunitySnapshotFallbackService = fallback,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
val staleSnapshotAt = LocalDateTime.of(2026, 7, 8, 14, 59, 59)
|
||||
snapshotPort.replaceSnapshots(
|
||||
@@ -675,7 +783,8 @@ class HomeRecommendationQueryServiceTest {
|
||||
snapshotPort,
|
||||
popularCommunitySnapshotFallbackService = fallback,
|
||||
clock = fixedClock(),
|
||||
langContext = langContext
|
||||
langContext = langContext,
|
||||
creatorCommunityTranslationService = creatorCommunityTranslationService
|
||||
)
|
||||
snapshotPort.replaceSnapshots(
|
||||
RecommendedSectionType.POPULAR_COMMUNITY,
|
||||
@@ -1212,6 +1321,28 @@ class HomeRecommendationQueryServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun popularCommunity(
|
||||
communityId: Long,
|
||||
creatorId: Long,
|
||||
content: String
|
||||
): HomePopularCommunityRecommendationRecord {
|
||||
return HomePopularCommunityRecommendationRecord(
|
||||
communityId = communityId,
|
||||
creatorId = creatorId,
|
||||
creatorNickname = "creator-$creatorId",
|
||||
creatorProfileImage = null,
|
||||
imagePath = null,
|
||||
audioPath = null,
|
||||
content = content,
|
||||
price = 0,
|
||||
createdAt = LocalDateTime.of(2026, 7, 9, 1, 0),
|
||||
likeCount = 0L,
|
||||
commentCount = 0L,
|
||||
existOrdered = false,
|
||||
isLiked = false
|
||||
)
|
||||
}
|
||||
|
||||
private class FakeHomeRecommendationSnapshotPort : RecommendationSnapshotPort {
|
||||
private val snapshots = mutableListOf<RecommendationSnapshotRecord>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user