feat(recommendation): 추천 배너 언어 필터를 적용한다

This commit is contained in:
2026-08-19 17:10:05 +09:00
parent b1be87b46f
commit 1731b3a8c1
15 changed files with 154 additions and 18 deletions
@@ -12,6 +12,7 @@ import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTab
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesContent
import kr.co.vividnext.sodalive.i18n.Lang
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.MemberRole
import kr.co.vividnext.sodalive.member.block.BlockMember
@@ -96,6 +97,38 @@ class DefaultAudioRecommendationQueryRepositoryTest @Autowired constructor(
assertEquals(visibleCreator.id, safeBanners.first().creatorId)
}
@Test
@DisplayName("콘텐츠 추천 배너는 언어 필터를 limit보다 먼저 적용한다")
fun shouldFilterBannersByLangBeforeLimit() {
val recommendationTab = saveContentRecommendationTab()
val koBanner = saveBanner(
"ko-audio-banner.png",
AudioContentBannerType.LINK,
1,
link = "https://ko.test",
tab = recommendationTab,
lang = Lang.KO
)
val jaBanner = saveBanner(
"ja-audio-banner.png",
AudioContentBannerType.LINK,
2,
link = "https://ja.test",
tab = recommendationTab,
lang = Lang.JA
)
flushAndClear()
assertEquals(
listOf("https://cdn.test/${koBanner.thumbnailImage}"),
repository.findBanners(1, null, false, Lang.KO).map { it.imageUrl }
)
assertEquals(
listOf("https://cdn.test/${jaBanner.thumbnailImage}"),
repository.findBanners(1, null, false, Lang.JA).map { it.imageUrl }
)
}
@Test
@DisplayName("오리지널 시리즈는 활성 원본 시리즈를 최신순으로 반환하고 성인/차단 조건을 적용한다")
fun shouldFindOriginalSeriesWithVisibilityConditions() {
@@ -404,11 +437,13 @@ class DefaultAudioRecommendationQueryRepositoryTest @Autowired constructor(
isAdult: Boolean = false,
creator: Member? = null,
link: String? = null,
tab: AudioContentMainTab? = null
tab: AudioContentMainTab? = null,
lang: Lang = Lang.KO
): AudioContentBanner {
val banner = AudioContentBanner(
thumbnailImage = thumbnailImage,
type = type,
lang = lang,
isAdult = isAdult,
isActive = isActive,
orders = orders
@@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.v2.content.recommendation.application
import kr.co.vividnext.sodalive.i18n.Lang
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.MemberRole
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
@@ -77,7 +78,7 @@ class AudioRecommendationQueryServiceTest {
0,
AudioRecommendationQueryService.RECOMMENDED_AUDIO_LIMIT
)
Mockito.verify(queryPort).findBanners(AudioRecommendationQueryService.BANNER_LIMIT, null, false)
Mockito.verify(queryPort).findBanners(AudioRecommendationQueryService.BANNER_LIMIT, null, false, Lang.KO)
Mockito.verify(queryPort).findLatestAudios(
eqValue(AudioRecommendationQueryService.LATEST_AUDIO_LIMIT),
Mockito.isNull(),
@@ -140,6 +141,7 @@ class AudioRecommendationQueryServiceTest {
fun shouldUseStoredPreferenceForMemberAdultVisibility() {
val member = member(id = 10L)
Mockito.doReturn(true).`when`(preferenceService).canViewAdultContent(member)
Mockito.doReturn("JP").`when`(preferenceService).resolveCountryCode(member)
stubFallback(
RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL,
0,
@@ -150,6 +152,7 @@ class AudioRecommendationQueryServiceTest {
service.getRecommendations(member)
Mockito.verify(preferenceService).canViewAdultContent(member)
Mockito.verify(queryPort).findBanners(AudioRecommendationQueryService.BANNER_LIMIT, member.id, true, Lang.JA)
Mockito.verify(preferenceService, Mockito.never()).initializeDefaultPreference(member)
verifyFallback(
RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL,