feat(home): 최근 활동 이동 식별자를 보강한다
This commit is contained in:
@@ -245,6 +245,7 @@ class HomeRecommendationFacade(
|
||||
}
|
||||
|
||||
private fun RecentlyActiveCreatorRecord.toItem() = HomeActiveCreatorItem(
|
||||
creatorId = creatorId,
|
||||
creatorNickname = creatorNickname,
|
||||
creatorProfileImage = profileImageUrl(cloudFrontHost, creatorProfileImage),
|
||||
activityType = activityType.name,
|
||||
|
||||
@@ -36,6 +36,7 @@ data class HomeLiveItem(
|
||||
)
|
||||
|
||||
data class HomeActiveCreatorItem(
|
||||
val creatorId: Long,
|
||||
val creatorNickname: String,
|
||||
val creatorProfileImage: String,
|
||||
val activityType: String,
|
||||
|
||||
@@ -127,7 +127,8 @@ class DefaultHomeRecommendationQueryRepository(
|
||||
includeAdultActivities: Boolean
|
||||
): List<RecentlyActiveCreatorRecord> {
|
||||
val sql = """
|
||||
select ranked.creator_nickname,
|
||||
select ranked.creator_id,
|
||||
ranked.creator_nickname,
|
||||
ranked.creator_profile_image,
|
||||
ranked.activity_type,
|
||||
ranked.activity_at,
|
||||
@@ -144,7 +145,7 @@ class DefaultHomeRecommendationQueryRepository(
|
||||
m.profile_image as creator_profile_image,
|
||||
'LIVE' as activity_type,
|
||||
lr.begin_date_time as activity_at,
|
||||
null as target_id,
|
||||
case when lr.is_active = true then lr.id else null end as target_id,
|
||||
lr.id as target_sort_id
|
||||
from live_room lr
|
||||
join member m on m.id = lr.member_id
|
||||
@@ -199,11 +200,12 @@ class DefaultHomeRecommendationQueryRepository(
|
||||
|
||||
return rows.map { row ->
|
||||
RecentlyActiveCreatorRecord(
|
||||
creatorNickname = row[0] as String,
|
||||
creatorProfileImage = row[1] as String?,
|
||||
activityType = CreatorActivityType.valueOf(row[2] as String),
|
||||
activityAt = toLocalDateTime(row[3]),
|
||||
targetId = (row[4] as Number?)?.toLong()
|
||||
creatorId = (row[0] as Number).toLong(),
|
||||
creatorNickname = row[1] as String,
|
||||
creatorProfileImage = row[2] as String?,
|
||||
activityType = CreatorActivityType.valueOf(row[3] as String),
|
||||
activityAt = toLocalDateTime(row[4]),
|
||||
targetId = (row[5] as Number?)?.toLong()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ data class HomeBannerRecommendationRecord(
|
||||
)
|
||||
|
||||
data class RecentlyActiveCreatorRecord(
|
||||
val creatorId: Long,
|
||||
val creatorNickname: String,
|
||||
val creatorProfileImage: String?,
|
||||
val activityType: CreatorActivityType,
|
||||
|
||||
@@ -524,6 +524,28 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
.andExpect(jsonPath("$.data.items[0].creatorId").value(character.creatorMember!!.id))
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("최근 활동 라이브 크리에이터는 creatorId와 라이브 상태별 targetId를 노출한다")
|
||||
fun shouldExposeNavigationIdsForRecentlyActiveLiveCreators() {
|
||||
val activeCreator = saveMember("active-live-activity", MemberRole.CREATOR)
|
||||
val inactiveCreator = saveMember("inactive-live-activity", MemberRole.CREATOR)
|
||||
val baseAt = LocalDateTime.of(2026, 5, 31, 10, 0)
|
||||
val activeLive = saveLiveRoom(activeCreator, baseAt.plusMinutes(2), "active-live-channel", isAdult = false)
|
||||
saveLiveRoom(inactiveCreator, baseAt.plusMinutes(1), "inactive-live-channel", isAdult = false, isActive = false)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
mockMvc.perform(get("/api/v2/home/recommendations"))
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[0].creatorId").value(activeCreator.id))
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[0].activityType").value("LIVE"))
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[0].targetId").value(activeLive.id))
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[1].creatorId").value(inactiveCreator.id))
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[1].activityType").value("LIVE"))
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[1].targetId").hasJsonPath())
|
||||
.andExpect(jsonPath("$.data.recentlyActiveCreators[1].targetId").doesNotExist())
|
||||
}
|
||||
|
||||
private fun saveMember(seed: String, role: MemberRole): Member {
|
||||
return memberRepository.saveAndFlush(
|
||||
Member(
|
||||
@@ -548,7 +570,8 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
creator: Member,
|
||||
beginDateTime: LocalDateTime,
|
||||
channelName: String,
|
||||
isAdult: Boolean
|
||||
isAdult: Boolean,
|
||||
isActive: Boolean = true
|
||||
): LiveRoom {
|
||||
val room = LiveRoom(
|
||||
title = "live-${creator.nickname}-$channelName",
|
||||
@@ -559,6 +582,7 @@ class HomeRecommendationControllerTest @Autowired constructor(
|
||||
)
|
||||
room.member = creator
|
||||
room.channelName = channelName
|
||||
room.isActive = isActive
|
||||
entityManager.persist(room)
|
||||
return room
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
||||
val replayCreator = saveMember("activity-replay", MemberRole.CREATOR)
|
||||
val communityCreator = saveMember("activity-community", MemberRole.CREATOR)
|
||||
saveAudioContent(liveCreator, baseAt.minusDays(2), isActive = true)
|
||||
saveLiveRoom(liveCreator, baseAt, channelName = "activity-live-channel")
|
||||
val live = saveLiveRoom(liveCreator, baseAt, channelName = "activity-live-channel")
|
||||
val audio = saveAudioContent(audioCreator, baseAt.minusHours(1), isActive = true)
|
||||
val replay = saveAudioContent(replayCreator, baseAt.minusHours(2), isActive = true, themeName = "다시듣기")
|
||||
val community = saveCommunity(communityCreator, isCommentAvailable = true)
|
||||
@@ -426,8 +426,12 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
||||
listOf(liveCreator.nickname, audioCreator.nickname, replayCreator.nickname, communityCreator.nickname),
|
||||
creators.map { it.creatorNickname }
|
||||
)
|
||||
assertEquals(liveCreator.id, byCreatorNickname[liveCreator.nickname]!!.creatorId)
|
||||
assertEquals(audioCreator.id, byCreatorNickname[audioCreator.nickname]!!.creatorId)
|
||||
assertEquals(replayCreator.id, byCreatorNickname[replayCreator.nickname]!!.creatorId)
|
||||
assertEquals(communityCreator.id, byCreatorNickname[communityCreator.nickname]!!.creatorId)
|
||||
assertEquals(CreatorActivityType.LIVE, byCreatorNickname[liveCreator.nickname]!!.activityType)
|
||||
assertEquals(null, byCreatorNickname[liveCreator.nickname]!!.targetId)
|
||||
assertEquals(live.id, byCreatorNickname[liveCreator.nickname]!!.targetId)
|
||||
assertEquals(baseAt, byCreatorNickname[liveCreator.nickname]!!.activityAt)
|
||||
assertEquals(CreatorActivityType.AUDIO, byCreatorNickname[audioCreator.nickname]!!.activityType)
|
||||
assertEquals(audio.id, byCreatorNickname[audioCreator.nickname]!!.targetId)
|
||||
@@ -457,6 +461,7 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
||||
val creators = repository.findRecentlyActiveCreators(limit = 10)
|
||||
|
||||
assertEquals(listOf(inactiveLiveCreator.nickname), creators.map { it.creatorNickname })
|
||||
assertEquals(inactiveLiveCreator.id, creators.single().creatorId)
|
||||
assertEquals(CreatorActivityType.LIVE, creators.single().activityType)
|
||||
assertEquals(baseAt.plusMinutes(2), creators.single().activityAt)
|
||||
assertEquals(null, creators.single().targetId)
|
||||
@@ -470,8 +475,8 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
||||
val adultLiveCreator = saveMember("activity-adult-live", MemberRole.CREATOR)
|
||||
val adultAudioCreator = saveMember("activity-adult-audio", MemberRole.CREATOR)
|
||||
val adultCommunityCreator = saveMember("activity-adult-community", MemberRole.CREATOR)
|
||||
saveLiveRoom(normalLiveCreator, baseAt.plusMinutes(3), channelName = "normal-live", isAdult = false)
|
||||
saveLiveRoom(adultLiveCreator, baseAt.plusMinutes(2), channelName = "adult-live", isAdult = true)
|
||||
val normalLive = saveLiveRoom(normalLiveCreator, baseAt.plusMinutes(3), channelName = "normal-live", isAdult = false)
|
||||
val adultLive = saveLiveRoom(adultLiveCreator, baseAt.plusMinutes(2), channelName = "adult-live", isAdult = true)
|
||||
val adultAudio = saveAudioContent(adultAudioCreator, baseAt.plusMinutes(1), isActive = true, isAdult = true)
|
||||
val adultCommunity = saveCommunity(adultCommunityCreator, isCommentAvailable = true, isAdult = true)
|
||||
updateCreatedAt("CreatorCommunity", adultCommunity.id!!, baseAt)
|
||||
@@ -490,8 +495,8 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
||||
),
|
||||
visibleCreators.map { it.creatorNickname }
|
||||
)
|
||||
assertEquals(null, visibleCreators[0].targetId)
|
||||
assertEquals(null, visibleCreators[1].targetId)
|
||||
assertEquals(normalLive.id, visibleCreators[0].targetId)
|
||||
assertEquals(adultLive.id, visibleCreators[1].targetId)
|
||||
assertEquals(adultAudio.id, visibleCreators[2].targetId)
|
||||
assertEquals(adultCommunity.id, visibleCreators[3].targetId)
|
||||
assertEquals(CreatorActivityType.LIVE, visibleCreators[0].activityType)
|
||||
|
||||
@@ -1012,6 +1012,7 @@ class HomeRecommendationQueryServiceTest {
|
||||
)
|
||||
val activeCreators = listOf(
|
||||
RecentlyActiveCreatorRecord(
|
||||
creatorId = 301L,
|
||||
creatorNickname = "creator",
|
||||
creatorProfileImage = "profile.png",
|
||||
activityType = CreatorActivityType.LIVE,
|
||||
|
||||
Reference in New Issue
Block a user