feat(live-recommend): 추천 크리에이터 배너를 언어별로 등록하고 노출한다
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
package kr.co.vividnext.sodalive.admin.live
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3Client
|
||||
import kr.co.vividnext.sodalive.aws.s3.S3Uploader
|
||||
import kr.co.vividnext.sodalive.can.CanRepository
|
||||
import kr.co.vividnext.sodalive.can.charge.ChargeRepository
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanCalculateRepository
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveCreatorBanner
|
||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveCreatorBannerRepository
|
||||
import kr.co.vividnext.sodalive.live.reservation.LiveReservationRepository
|
||||
import kr.co.vividnext.sodalive.live.room.cancel.LiveRoomCancelRepository
|
||||
import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfoRedisRepository
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
import org.springframework.mock.web.MockMultipartFile
|
||||
import java.net.URL
|
||||
|
||||
class AdminLiveServiceTest {
|
||||
private val recommendCreatorBannerRepository = Mockito.mock(RecommendLiveCreatorBannerRepository::class.java)
|
||||
private val roomInfoRepository = Mockito.mock(LiveRoomInfoRedisRepository::class.java)
|
||||
private val roomCancelRepository = Mockito.mock(LiveRoomCancelRepository::class.java)
|
||||
private val repository = Mockito.mock(AdminLiveRoomQueryRepository::class.java)
|
||||
private val memberRepository = Mockito.mock(MemberRepository::class.java)
|
||||
private val amazonS3Client = Mockito.mock(AmazonS3Client::class.java)
|
||||
private val s3Uploader = S3Uploader(amazonS3Client)
|
||||
private val useCanCalculateRepository = Mockito.mock(UseCanCalculateRepository::class.java)
|
||||
private val reservationRepository = Mockito.mock(LiveReservationRepository::class.java)
|
||||
private val chargeRepository = Mockito.mock(ChargeRepository::class.java)
|
||||
private val canRepository = Mockito.mock(CanRepository::class.java)
|
||||
private val applicationEventPublisher = Mockito.mock(ApplicationEventPublisher::class.java)
|
||||
private val messageSource = SodaMessageSource()
|
||||
private val langContext = LangContext()
|
||||
private val service = AdminLiveService(
|
||||
recommendCreatorBannerRepository = recommendCreatorBannerRepository,
|
||||
roomInfoRepository = roomInfoRepository,
|
||||
roomCancelRepository = roomCancelRepository,
|
||||
repository = repository,
|
||||
memberRepository = memberRepository,
|
||||
s3Uploader = s3Uploader,
|
||||
useCanCalculateRepository = useCanCalculateRepository,
|
||||
reservationRepository = reservationRepository,
|
||||
chargeRepository = chargeRepository,
|
||||
canRepository = canRepository,
|
||||
applicationEventPublisher = applicationEventPublisher,
|
||||
messageSource = messageSource,
|
||||
langContext = langContext,
|
||||
bucket = "test-bucket",
|
||||
coverImageHost = "https://cdn.test"
|
||||
)
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 크리에이터 등록은 소문자 lang 코드를 Lang enum으로 저장한다")
|
||||
fun shouldSaveRecommendCreatorBannerWithIsoLanguageCode() {
|
||||
val image = MockMultipartFile("image", "banner.png", "image/png", "image".toByteArray())
|
||||
val creator = Member(
|
||||
email = "creator@test.com",
|
||||
password = "password",
|
||||
nickname = "creator",
|
||||
role = MemberRole.CREATOR
|
||||
).also {
|
||||
it.id = 7L
|
||||
}
|
||||
var savedBanner: RecommendLiveCreatorBanner? = null
|
||||
|
||||
Mockito.`when`(memberRepository.findCreatorByIdOrNull(7L)).thenReturn(creator)
|
||||
Mockito.doAnswer {
|
||||
val banner = it.arguments[0] as RecommendLiveCreatorBanner
|
||||
banner.id = 55L
|
||||
savedBanner = banner
|
||||
banner
|
||||
}.`when`(recommendCreatorBannerRepository).save(Mockito.any(RecommendLiveCreatorBanner::class.java))
|
||||
Mockito.`when`(amazonS3Client.getUrl(Mockito.eq("test-bucket"), Mockito.anyString()))
|
||||
.thenAnswer { URL("https://cdn.test/${it.arguments[1]}") }
|
||||
|
||||
service.createRecommendCreatorBanner(
|
||||
image = image,
|
||||
creatorId = 7L,
|
||||
startDateString = "2099-01-01 10:00",
|
||||
endDateString = "2099-01-02 10:00",
|
||||
isAdult = false,
|
||||
lang = "ja"
|
||||
)
|
||||
|
||||
assertEquals(Lang.JA, savedBanner?.lang)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 크리에이터 등록은 지원하지 않는 lang 값이면 예외를 던진다")
|
||||
fun shouldThrowWhenRecommendCreatorBannerLangIsInvalid() {
|
||||
val image = MockMultipartFile("image", "banner.png", "image/png", "image".toByteArray())
|
||||
val creator = Member(
|
||||
email = "creator@test.com",
|
||||
password = "password",
|
||||
nickname = "creator",
|
||||
role = MemberRole.CREATOR
|
||||
).also {
|
||||
it.id = 7L
|
||||
}
|
||||
|
||||
Mockito.`when`(memberRepository.findCreatorByIdOrNull(7L)).thenReturn(creator)
|
||||
|
||||
val exception = assertThrows(SodaException::class.java) {
|
||||
service.createRecommendCreatorBanner(
|
||||
image = image,
|
||||
creatorId = 7L,
|
||||
startDateString = "2099-01-01 10:00",
|
||||
endDateString = "2099-01-02 10:00",
|
||||
isAdult = false,
|
||||
lang = "fr"
|
||||
)
|
||||
}
|
||||
|
||||
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
@@ -10,6 +11,7 @@ import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
||||
import kr.co.vividnext.sodalive.member.following.CreatorFollowing
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
|
||||
@@ -34,6 +36,7 @@ class LiveRecommendRepositoryTest @Autowired constructor(
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 크리에이터 조회는 차단 관계를 양방향으로 제외한다")
|
||||
fun shouldExcludeBlockedCreatorsInBothDirections() {
|
||||
val viewer = saveMember(nickname = "viewer", role = MemberRole.USER)
|
||||
val creatorBlockedByViewer = saveMember(nickname = "creator-blocked-by-viewer", role = MemberRole.CREATOR)
|
||||
@@ -50,13 +53,14 @@ class LiveRecommendRepositoryTest @Autowired constructor(
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val result = liveRecommendRepository.getRecommendLive(memberId = viewer.id, isAdult = true)
|
||||
val result = liveRecommendRepository.getRecommendLive(memberId = viewer.id, isAdult = true, lang = Lang.KO)
|
||||
|
||||
assertEquals(1, result.size)
|
||||
assertEquals(creatorAllowed.id, result[0].creatorId)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 크리에이터 조회는 비활성 차단 관계를 제외하지 않는다")
|
||||
fun shouldKeepCreatorWhenBlockRelationIsInactive() {
|
||||
val viewer = saveMember(nickname = "viewer-inactive", role = MemberRole.USER)
|
||||
val creator = saveMember(nickname = "creator-inactive", role = MemberRole.CREATOR)
|
||||
@@ -67,13 +71,14 @@ class LiveRecommendRepositoryTest @Autowired constructor(
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val result = liveRecommendRepository.getRecommendLive(memberId = viewer.id, isAdult = true)
|
||||
val result = liveRecommendRepository.getRecommendLive(memberId = viewer.id, isAdult = true, lang = Lang.KO)
|
||||
|
||||
assertEquals(1, result.size)
|
||||
assertEquals(creator.id, result[0].creatorId)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("크리에이터 팔로잉 전체 조회는 알림 여부를 포함한다")
|
||||
fun shouldReturnFollowingCreatorListWithNotifyFlag() {
|
||||
val viewer = saveMember(nickname = "viewer-following", role = MemberRole.USER)
|
||||
val creatorA = saveMember(nickname = "creator-following-a", role = MemberRole.CREATOR)
|
||||
@@ -98,6 +103,25 @@ class LiveRecommendRepositoryTest @Autowired constructor(
|
||||
assertEquals(false, isNotifyByCreatorId[creatorB.id])
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 크리에이터 조회는 요청 언어와 일치하는 배너만 반환한다")
|
||||
fun shouldReturnOnlyRequestedLanguageBanners() {
|
||||
val viewer = saveMember(nickname = "viewer-lang", role = MemberRole.USER)
|
||||
val koreanCreator = saveMember(nickname = "creator-ko", role = MemberRole.CREATOR)
|
||||
val japaneseCreator = saveMember(nickname = "creator-ja", role = MemberRole.CREATOR)
|
||||
|
||||
saveBanner(creator = koreanCreator, order = 1, lang = Lang.KO)
|
||||
saveBanner(creator = japaneseCreator, order = 2, lang = Lang.JA)
|
||||
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val result = liveRecommendRepository.getRecommendLive(memberId = viewer.id, isAdult = true, lang = Lang.JA)
|
||||
|
||||
assertEquals(1, result.size)
|
||||
assertEquals(japaneseCreator.id, result.first().creatorId)
|
||||
}
|
||||
|
||||
private fun saveMember(nickname: String, role: MemberRole): Member {
|
||||
return memberRepository.saveAndFlush(
|
||||
Member(
|
||||
@@ -110,11 +134,12 @@ class LiveRecommendRepositoryTest @Autowired constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveBanner(creator: Member, order: Int) {
|
||||
private fun saveBanner(creator: Member, order: Int, lang: Lang = Lang.KO) {
|
||||
val banner = RecommendLiveCreatorBanner(
|
||||
startDate = LocalDateTime.now().minusDays(1),
|
||||
endDate = LocalDateTime.now().plusDays(1),
|
||||
isAdult = false,
|
||||
lang = lang,
|
||||
orders = order,
|
||||
image = "recommend/$order.png"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.auth.Auth
|
||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
||||
@@ -58,12 +59,12 @@ class LiveRecommendServiceTest {
|
||||
isAdult = true
|
||||
)
|
||||
)
|
||||
Mockito.`when`(liveRecommendCacheService.getRecommendLive(memberId = member.id, isAdult = true)).thenReturn(expected)
|
||||
Mockito.`when`(liveRecommendCacheService.getRecommendLive(member.id, true, Lang.JA)).thenReturn(expected)
|
||||
|
||||
val result = service.getRecommendLive(member)
|
||||
val result = service.getRecommendLive(member, Lang.JA)
|
||||
|
||||
assertEquals(expected, result)
|
||||
Mockito.verify(liveRecommendCacheService).getRecommendLive(memberId = member.id, isAdult = true)
|
||||
Mockito.verify(liveRecommendCacheService).getRecommendLive(member.id, true, Lang.JA)
|
||||
Mockito.verifyNoInteractions(repository)
|
||||
Mockito.verifyNoInteractions(blockMemberRepository)
|
||||
}
|
||||
@@ -71,12 +72,12 @@ class LiveRecommendServiceTest {
|
||||
@Test
|
||||
fun shouldDelegateToRepositoryAsGuestWhenMemberIsNull() {
|
||||
val expected = listOf(GetRecommendLiveResponse(imageUrl = "https://cdn.test/recommend-guest.png", creatorId = 88L))
|
||||
Mockito.`when`(liveRecommendCacheService.getRecommendLive(memberId = null, isAdult = false)).thenReturn(expected)
|
||||
Mockito.`when`(liveRecommendCacheService.getRecommendLive(null, false, Lang.EN)).thenReturn(expected)
|
||||
|
||||
val result = service.getRecommendLive(null)
|
||||
val result = service.getRecommendLive(null, Lang.EN)
|
||||
|
||||
assertEquals(expected, result)
|
||||
Mockito.verify(liveRecommendCacheService).getRecommendLive(memberId = null, isAdult = false)
|
||||
Mockito.verify(liveRecommendCacheService).getRecommendLive(null, false, Lang.EN)
|
||||
Mockito.verifyNoInteractions(repository)
|
||||
Mockito.verifyNoInteractions(blockMemberRepository)
|
||||
Mockito.verifyNoInteractions(memberContentPreferenceService)
|
||||
|
||||
Reference in New Issue
Block a user